s3-spoolss: use struct spoolss_Notify instead of SPOOL_NOTIFY_INFO_DATA.
[tprouty/samba.git] / source3 / rpc_server / srv_spoolss_nt.c
index a0b689c8a46bcec889af5f2157e5c9573a8540cb..90742d57ae05d43265a3b02c4c1e549f181746fb 100644 (file)
@@ -69,7 +69,7 @@ extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
 
 struct xcv_api_table {
        const char *name;
-       WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
+       WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
 };
 
 /********************************************************************
@@ -673,43 +673,93 @@ static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
        return False;
 }
 
-/* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
+#define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
+       _data->data.integer[0] = _integer; \
+       _data->data.integer[1] = 0;
+
+
+#define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
+       _data->data.string.string = talloc_strdup(mem_ctx, _p); \
+       if (!_data->data.string.string) {\
+               _data->data.string.size = 0; \
+       } \
+       _data->data.string.size = strlen_m_term(_p) * 2;
+
+#define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
+       _data->data.devmode.devmode = _devmode;
+
+#define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
+       _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
+       if (!_data->data.sd.sd) { \
+               _data->data.sd.sd_size = 0; \
+       } \
+       _data->data.sd.sd_size = _size;
+
+static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
+                                  struct tm *t,
+                                  const char **pp,
+                                  uint32_t *plen)
+{
+       struct spoolss_Time st;
+       uint32_t len = 16;
+       char *p;
+
+       if (!init_systemtime(&st, t)) {
+               return;
+       }
+
+       p = talloc_array(mem_ctx, char, len);
+       if (!p) {
+               return;
+       }
+
+       /*
+        * Systemtime must be linearized as a set of UINT16's.
+        * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
+        */
+
+       SSVAL(p, 0, st.year);
+       SSVAL(p, 2, st.month);
+       SSVAL(p, 4, st.day_of_week);
+       SSVAL(p, 6, st.day);
+       SSVAL(p, 8, st.hour);
+       SSVAL(p, 10, st.minute);
+       SSVAL(p, 12, st.second);
+       SSVAL(p, 14, st.millisecond);
+
+       *pp = p;
+       *plen = len;
+}
+
+/* Convert a notification message to a struct spoolss_Notify */
 
 static void notify_one_value(struct spoolss_notify_msg *msg,
-                            SPOOL_NOTIFY_INFO_DATA *data,
+                            struct spoolss_Notify *data,
                             TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = msg->notify.value[0];
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
 }
 
 static void notify_string(struct spoolss_notify_msg *msg,
-                         SPOOL_NOTIFY_INFO_DATA *data,
+                         struct spoolss_Notify *data,
                          TALLOC_CTX *mem_ctx)
 {
-       UNISTR2 unistr;
-
        /* The length of the message includes the trailing \0 */
 
-       init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
-
-       data->notify_data.data.length = msg->len * 2;
-       data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
-
-       if (!data->notify_data.data.string) {
-               data->notify_data.data.length = 0;
+       data->data.string.size = msg->len * 2;
+       data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
+       if (!data->data.string.string) {
+               data->data.string.size = 0;
                return;
        }
-
-       memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
 }
 
 static void notify_system_time(struct spoolss_notify_msg *msg,
-                              SPOOL_NOTIFY_INFO_DATA *data,
+                              struct spoolss_Notify *data,
                               TALLOC_CTX *mem_ctx)
 {
-       SYSTEMTIME systime;
-       prs_struct ps;
+       data->data.string.string = NULL;
+       data->data.string.size = 0;
 
        if (msg->len != sizeof(time_t)) {
                DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
@@ -717,42 +767,15 @@ static void notify_system_time(struct spoolss_notify_msg *msg,
                return;
        }
 
-       if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
-               DEBUG(5, ("notify_system_time: prs_init() failed\n"));
-               return;
-       }
-
-       if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
-               DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
-               prs_mem_free(&ps);
-               return;
-       }
-
-       if (!spoolss_io_system_time("", &ps, 0, &systime)) {
-               prs_mem_free(&ps);
-               return;
-       }
-
-       data->notify_data.data.length = prs_offset(&ps);
-       if (prs_offset(&ps)) {
-               data->notify_data.data.string = (uint16 *)
-                       TALLOC(mem_ctx, prs_offset(&ps));
-               if (!data->notify_data.data.string) {
-                       prs_mem_free(&ps);
-                       return;
-               }
-               prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
-       } else {
-               data->notify_data.data.string = NULL;
-       }
-
-       prs_mem_free(&ps);
+       init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
+                              &data->data.string.string,
+                              &data->data.string.size);
 }
 
 struct notify2_message_table {
        const char *name;
        void (*fn)(struct spoolss_notify_msg *msg,
-                  SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
+                  struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
 };
 
 static struct notify2_message_table printer_notify_table[] = {
@@ -966,9 +989,9 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
        /* loop over all printers */
 
        for (p = printers_list; p; p = p->next) {
-               SPOOL_NOTIFY_INFO_DATA *data;
-               uint32  data_len = 0;
-               uint32  id;
+               struct spoolss_Notify *notifies;
+               uint32_t count = 0;
+               uint32_t id;
                int     i;
 
                /* Is there notification on this handle? */
@@ -989,13 +1012,11 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
 
                /* allocate the max entries possible */
 
-               data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
-               if (!data) {
+               notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
+               if (!notifies) {
                        return;
                }
 
-               ZERO_STRUCTP(data);
-
                /* build the array of change notifications */
 
                sending_msg_count = 0;
@@ -1044,17 +1065,17 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
                                }
                        }
 
-                       construct_info_data( &data[data_len], msg->type, msg->field, id );
+                       construct_info_data( &notifies[count], msg->type, msg->field, id );
 
                        switch(msg->type) {
                        case PRINTER_NOTIFY_TYPE:
                                if ( printer_notify_table[msg->field].fn )
-                                       printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
+                                       printer_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
                                break;
 
                        case JOB_NOTIFY_TYPE:
                                if ( job_notify_table[msg->field].fn )
-                                       job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
+                                       job_notify_table[msg->field].fn(msg, &notifies[count], mem_ctx);
                                break;
 
                        default:
@@ -1062,7 +1083,7 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
                                goto done;
                        }
 
-                       data_len++;
+                       count++;
                }
 
                if ( sending_msg_count ) {
@@ -1399,187 +1420,146 @@ void reset_all_printerdata(struct messaging_context *msg,
        return;
 }
 
-/********************************************************************
- Copy routines used by convert_to_openprinterex()
- *******************************************************************/
+/****************************************************************
+ _spoolss_OpenPrinter
+****************************************************************/
 
-static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
+WERROR _spoolss_OpenPrinter(pipes_struct *p,
+                           struct spoolss_OpenPrinter *r)
 {
-       DEVICEMODE *d;
-       int len;
-
-       if (!devmode)
-               return NULL;
+       struct spoolss_OpenPrinterEx e;
+       WERROR werr;
 
-       DEBUG (8,("dup_devmode\n"));
+       ZERO_STRUCT(e.in.userlevel);
 
-       /* bulk copy first */
-
-       d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
-       if (!d)
-               return NULL;
-
-       /* dup the pointer members separately */
-
-       len = unistrlen(devmode->devicename.buffer);
-       if (len != -1) {
-               d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
-               if (!d->devicename.buffer) {
-                       return NULL;
-               }
-               if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
-                       return NULL;
-       }
+       e.in.printername        = r->in.printername;
+       e.in.datatype           = r->in.datatype;
+       e.in.devmode_ctr        = r->in.devmode_ctr;
+       e.in.access_mask        = r->in.access_mask;
+       e.in.level              = 0;
 
+       e.out.handle            = r->out.handle;
 
-       len = unistrlen(devmode->formname.buffer);
-       if (len != -1) {
-               d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
-               if (!d->formname.buffer) {
-                       return NULL;
-               }
-               if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
-                       return NULL;
-       }
+       werr = _spoolss_OpenPrinterEx(p, &e);
 
-       if (devmode->driverextra) {
-               d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
-                                               devmode->driverextra);
-               if (!d->dev_private) {
-                       return NULL;
-               }
-       } else {
-               d->dev_private = NULL;
+       if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
+               /* OpenPrinterEx returns this for a bad
+                * printer name. We must return WERR_INVALID_PRINTER_NAME
+                * instead.
+                */
+               werr = WERR_INVALID_PRINTER_NAME;
        }
-       return d;
-}
-
-static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
-{
-       if (!new_ctr || !ctr)
-               return;
-
-       DEBUG(8,("copy_devmode_ctr\n"));
 
-       new_ctr->size = ctr->size;
-       new_ctr->devmode_ptr = ctr->devmode_ptr;
-
-       if(ctr->devmode_ptr)
-               new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
-}
-
-static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
-{
-       if (!new_def || !def)
-               return;
-
-       DEBUG(8,("copy_printer_defaults\n"));
-
-       new_def->datatype_ptr = def->datatype_ptr;
-
-       if (def->datatype_ptr)
-               copy_unistr2(&new_def->datatype, &def->datatype);
-
-       copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
-
-       new_def->access_required = def->access_required;
+       return werr;
 }
 
 /********************************************************************
- * Convert a SPOOL_Q_OPEN_PRINTER structure to a
- * SPOOL_Q_OPEN_PRINTER_EX structure
+ FIXME: temporary convert_devicemode_new function
  ********************************************************************/
 
-static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
+static bool convert_devicemode_new(const char *printername,
+                                  struct spoolss_DeviceMode *devmode,
+                                  NT_DEVICEMODE **pp_nt_devmode)
 {
-       if (!q_u_ex || !q_u)
-               return WERR_OK;
+       NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
 
-       DEBUG(8,("convert_to_openprinterex\n"));
+       /*
+        * Ensure nt_devmode is a valid pointer
+        * as we will be overwriting it.
+        */
 
-       if ( q_u->printername ) {
-               q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
-               if (q_u_ex->printername == NULL)
-                       return WERR_NOMEM;
-               copy_unistr2(q_u_ex->printername, q_u->printername);
+       if (nt_devmode == NULL) {
+               DEBUG(5, ("convert_devicemode_new: allocating a generic devmode\n"));
+               if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
+                       return false;
        }
 
-       copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
-
-       return WERR_OK;
-}
-
-/********************************************************************
- * spoolss_open_printer
- *
- * called from the spoolss dispatcher
- ********************************************************************/
-
-WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
-{
-       SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
-       SPOOL_R_OPEN_PRINTER_EX r_u_ex;
-
-       if (!q_u || !r_u)
-               return WERR_NOMEM;
-
-       ZERO_STRUCT(q_u_ex);
-       ZERO_STRUCT(r_u_ex);
-
-       /* convert the OpenPrinter() call to OpenPrinterEx() */
+       rpcstr_push(nt_devmode->devicename, devmode->devicename, 31, 0);
+       rpcstr_push(nt_devmode->formname, devmode->formname, 31, 0);
+
+       nt_devmode->specversion         = devmode->specversion;
+       nt_devmode->driverversion       = devmode->driverversion;
+       nt_devmode->size                = devmode->size;
+       nt_devmode->fields              = devmode->fields;
+       nt_devmode->orientation         = devmode->orientation;
+       nt_devmode->papersize           = devmode->papersize;
+       nt_devmode->paperlength         = devmode->paperlength;
+       nt_devmode->paperwidth          = devmode->paperwidth;
+       nt_devmode->scale               = devmode->scale;
+       nt_devmode->copies              = devmode->copies;
+       nt_devmode->defaultsource       = devmode->defaultsource;
+       nt_devmode->printquality        = devmode->printquality;
+       nt_devmode->color               = devmode->color;
+       nt_devmode->duplex              = devmode->duplex;
+       nt_devmode->yresolution         = devmode->yresolution;
+       nt_devmode->ttoption            = devmode->ttoption;
+       nt_devmode->collate             = devmode->collate;
+
+       nt_devmode->logpixels           = devmode->logpixels;
+       nt_devmode->bitsperpel          = devmode->bitsperpel;
+       nt_devmode->pelswidth           = devmode->pelswidth;
+       nt_devmode->pelsheight          = devmode->pelsheight;
+       nt_devmode->displayflags        = devmode->displayflags;
+       nt_devmode->displayfrequency    = devmode->displayfrequency;
+       nt_devmode->icmmethod           = devmode->icmmethod;
+       nt_devmode->icmintent           = devmode->icmintent;
+       nt_devmode->mediatype           = devmode->mediatype;
+       nt_devmode->dithertype          = devmode->dithertype;
+       nt_devmode->reserved1           = devmode->reserved1;
+       nt_devmode->reserved2           = devmode->reserved2;
+       nt_devmode->panningwidth        = devmode->panningwidth;
+       nt_devmode->panningheight       = devmode->panningheight;
 
-       r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
-       if (!W_ERROR_IS_OK(r_u_ex.status))
-               return r_u_ex.status;
-
-       r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
+       /*
+        * Only change private and driverextra if the incoming devmode
+        * has a new one. JRA.
+        */
 
-       /* convert back to OpenPrinter() */
+       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)
+                       return false;
+               memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
+       }
 
-       memcpy(r_u, &r_u_ex, sizeof(*r_u));
+       *pp_nt_devmode = nt_devmode;
 
-       if (W_ERROR_EQUAL(r_u->status, WERR_INVALID_PARAM)) {
-               /* OpenPrinterEx returns this for a bad
-                * printer name. We must return WERR_INVALID_PRINTER_NAME
-                * instead.
-                */
-               r_u->status = WERR_INVALID_PRINTER_NAME;
-       }
-       return r_u->status;
+       return true;
 }
 
-/********************************************************************
- ********************************************************************/
+/****************************************************************
+ _spoolss_OpenPrinterEx
+****************************************************************/
 
-WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
+WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
+                             struct spoolss_OpenPrinterEx *r)
 {
-       PRINTER_DEFAULT         *printer_default = &q_u->printer_default;
-       POLICY_HND              *handle = &r_u->handle;
-
-       fstring name;
+       POLICY_HND              *handle = r->out.handle;
+       char *name = CONST_DISCARD(char *, r->in.printername);
        int snum;
        Printer_entry *Printer=NULL;
 
-       if (!q_u->printername) {
+       if (!name) {
                return WERR_INVALID_PARAM;
        }
 
        /* some sanity check because you can open a printer or a print server */
        /* aka: \\server\printer or \\server */
 
-       unistr2_to_ascii(name, q_u->printername, sizeof(name));
-
        DEBUGADD(3,("checking name: %s\n",name));
 
        if (!open_printer_hnd(p, handle, name, 0)) {
+               ZERO_STRUCTP(r->out.handle);
                return WERR_INVALID_PARAM;
        }
 
        Printer=find_printer_index_by_hnd(p, handle);
        if ( !Printer ) {
-               DEBUG(0,(" _spoolss_open_printer_ex: logic error.  Can't find printer "
+               DEBUG(0,("_spoolss_OpenPrinterEx: logic error.  Can't find printer "
                        "handle we created for printer %s\n", name ));
                close_printer_handle(p,handle);
+               ZERO_STRUCTP(r->out.handle);
                return WERR_INVALID_PARAM;
        }
 
@@ -1618,29 +1598,31 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
 
                /* Map standard access rights to object specific access rights */
 
-               se_map_standard(&printer_default->access_required,
+               se_map_standard(&r->in.access_mask,
                                &printserver_std_mapping);
 
                /* Deny any object specific bits that don't apply to print
                   servers (i.e printer and job specific bits) */
 
-               printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
+               r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
 
-               if (printer_default->access_required &
+               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);
+                       ZERO_STRUCTP(r->out.handle);
                        return WERR_ACCESS_DENIED;
                }
 
                /* Allow admin access */
 
-               if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
+               if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
                {
                        SE_PRIV se_printop = SE_PRINT_OPERATOR;
 
                        if (!lp_ms_add_printer_wizard()) {
                                close_printer_handle(p, handle);
+                               ZERO_STRUCTP(r->out.handle);
                                return WERR_ACCESS_DENIED;
                        }
 
@@ -1656,17 +1638,18 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
                                    p->server_info->ptok,
                                    lp_printer_admin(snum))) {
                                close_printer_handle(p, handle);
+                               ZERO_STRUCTP(r->out.handle);
                                return WERR_ACCESS_DENIED;
                        }
 
-                       printer_default->access_required = SERVER_ACCESS_ADMINISTER;
+                       r->in.access_mask = SERVER_ACCESS_ADMINISTER;
                }
                else
                {
-                       printer_default->access_required = SERVER_ACCESS_ENUMERATE;
+                       r->in.access_mask = SERVER_ACCESS_ENUMERATE;
                }
 
-               DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
+               DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
                        ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
 
                /* We fall through to return WERR_OK */
@@ -1678,14 +1661,15 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
 
                if (!get_printer_snum(p, handle, &snum, NULL)) {
                        close_printer_handle(p, handle);
+                       ZERO_STRUCTP(r->out.handle);
                        return WERR_BADFID;
                }
 
-               se_map_standard(&printer_default->access_required, &printer_std_mapping);
+               se_map_standard(&r->in.access_mask, &printer_std_mapping);
 
                /* map an empty access mask to the minimum access mask */
-               if (printer_default->access_required == 0x0)
-                       printer_default->access_required = PRINTER_ACCESS_USE;
+               if (r->in.access_mask == 0x0)
+                       r->in.access_mask = PRINTER_ACCESS_USE;
 
                /*
                 * If we are not serving the printer driver for this printer,
@@ -1694,49 +1678,53 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
                 */
 
                if (lp_use_client_driver(snum)
-                       && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
+                       && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
                {
-                       printer_default->access_required = PRINTER_ACCESS_USE;
+                       r->in.access_mask = PRINTER_ACCESS_USE;
                }
 
                /* check smb.conf parameters and the the sec_desc */
 
                if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
                        DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
+                       ZERO_STRUCTP(r->out.handle);
                        return WERR_ACCESS_DENIED;
                }
 
                if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
                                   p->server_info->ptok, snum) ||
                    !print_access_check(p->server_info, snum,
-                                       printer_default->access_required)) {
+                                       r->in.access_mask)) {
                        DEBUG(3, ("access DENIED for printer open\n"));
                        close_printer_handle(p, handle);
+                       ZERO_STRUCTP(r->out.handle);
                        return WERR_ACCESS_DENIED;
                }
 
-               if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
+               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);
+                       ZERO_STRUCTP(r->out.handle);
                        return WERR_ACCESS_DENIED;
                }
 
-               if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
-                       printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
+               if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
+                       r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
                else
-                       printer_default->access_required = PRINTER_ACCESS_USE;
+                       r->in.access_mask = PRINTER_ACCESS_USE;
 
-               DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
+               DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
                        ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
 
                break;
 
        default:
                /* sanity check to prevent programmer error */
+               ZERO_STRUCTP(r->out.handle);
                return WERR_BADFID;
        }
 
-       Printer->access_granted = printer_default->access_required;
+       Printer->access_granted = r->in.access_mask;
 
        /*
         * If the client sent a devmode in the OpenPrinter() call, then
@@ -1744,20 +1732,21 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
         */
 
         if ( (Printer->printer_type != SPLHND_SERVER)
-               && q_u->printer_default.devmode_cont.devmode_ptr )
+               && r->in.devmode_ctr.devmode )
         {
-               convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
-                       &Printer->nt_devmode );
+               convert_devicemode_new(Printer->sharename,
+                                      r->in.devmode_ctr.devmode,
+                                      &Printer->nt_devmode);
         }
 
 #if 0  /* JERRY -- I'm doubtful this is really effective */
        /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
           optimization in Windows 2000 clients  --jerry */
 
-       if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
+       if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
                && (RA_WIN2K == get_remote_arch()) )
        {
-               DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
+               DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
                sys_usleep( 500000 );
        }
 #endif
@@ -1768,55 +1757,239 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
 /****************************************************************************
 ****************************************************************************/
 
-static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
-                               NT_PRINTER_INFO_LEVEL *printer, uint32 level)
+static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
+                                             NT_PRINTER_INFO_LEVEL_2 *d)
+{
+       DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
+
+       if (!r || !d) {
+               return false;
+       }
+
+       d->attributes           = r->attributes;
+       d->priority             = r->priority;
+       d->default_priority     = r->defaultpriority;
+       d->starttime            = r->starttime;
+       d->untiltime            = r->untiltime;
+       d->status               = r->status;
+       d->cjobs                = r->cjobs;
+
+       fstrcpy(d->servername,  r->servername);
+       fstrcpy(d->printername, r->printername);
+       fstrcpy(d->sharename,   r->sharename);
+       fstrcpy(d->portname,    r->portname);
+       fstrcpy(d->drivername,  r->drivername);
+       slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
+       fstrcpy(d->location,    r->location);
+       fstrcpy(d->sepfile,     r->sepfile);
+       fstrcpy(d->printprocessor, r->printprocessor);
+       fstrcpy(d->datatype,    r->datatype);
+       fstrcpy(d->parameters,  r->parameters);
+
+       return true;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static bool convert_printer_info_new(struct spoolss_SetPrinterInfoCtr *info_ctr,
+                                    NT_PRINTER_INFO_LEVEL *printer)
 {
        bool ret;
 
-       switch (level) {
-               case 2:
-                       /* allocate memory if needed.  Messy because
-                          convert_printer_info is used to update an existing
-                          printer or build a new one */
-
-                       if ( !printer->info_2 ) {
-                               printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
-                               if ( !printer->info_2 ) {
-                                       DEBUG(0,("convert_printer_info: talloc() failed!\n"));
-                                       return False;
-                               }
+       switch (info_ctr->level) {
+       case 2:
+               /* allocate memory if needed.  Messy because
+                  convert_printer_info is used to update an existing
+                  printer or build a new one */
+
+               if (!printer->info_2) {
+                       printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
+                       if (!printer->info_2) {
+                               DEBUG(0,("convert_printer_info_new: "
+                                       "talloc() failed!\n"));
+                               return false;
                        }
+               }
+
+               ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
+                                                       printer->info_2);
+               printer->info_2->setuptime = time(NULL);
+               return ret;
+       }
+
+       return false;
+}
 
-                       ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
-                       printer->info_2->setuptime = time(NULL);
+/*******************************************************************
+********************************************************************/
+
+static bool string_array_to_fstring_array(const char **sarray, fstring **farray)
+{
+       int i;
 
-                       return ret;
+       if (!sarray) {
+               *farray = NULL;
+               return true;
        }
 
-       return False;
+       *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 convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
-                                       NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
+/*******************************************************************
+********************************************************************/
+
+static bool driver_info6_to_nt_driver_info6(struct spoolss_AddDriverInfo6 *r,
+                                           NT_PRINTER_DRIVER_INFO_LEVEL_6 **p)
 {
-       bool result = True;
+       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 (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
-                               result = False;
-                       break;
-               case 6:
-                       printer->info_6=NULL;
-                       if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
-                               result = False;
-                       break;
-               default:
-                       break;
+       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 result;
+       return true;
 }
 
 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
@@ -2631,6 +2804,7 @@ static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
                                        POLICY_HND *handle, struct sockaddr_storage *client_ss)
 {
        WERROR result;
+       NTSTATUS status;
 
        /*
         * If it's the first connection, contact the client
@@ -2662,14 +2836,15 @@ static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
 
        smb_connections++;
 
-       result = rpccli_spoolss_reply_open_printer(notify_cli_pipe,
-                       talloc_tos(),
-                       printer,
-                       localprinter,
-                       type,
-                       handle);
-
-       if (!W_ERROR_IS_OK(result))
+       status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
+                                                printer,
+                                                localprinter,
+                                                type,
+                                                0,
+                                                NULL,
+                                                handle,
+                                                &result);
+       if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
                DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
                        win_errstr(result)));
 
@@ -2747,25 +2922,12 @@ WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNE
  ********************************************************************/
 
 void spoolss_notify_server_name(int snum,
-                                      SPOOL_NOTIFY_INFO_DATA *data,
+                                      struct spoolss_Notify *data,
                                       print_queue_struct *queue,
                                       NT_PRINTER_INFO_LEVEL *printer,
                                       TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
 }
 
 /*******************************************************************
@@ -2773,14 +2935,11 @@ void spoolss_notify_server_name(int snum,
  ********************************************************************/
 
 void spoolss_notify_printer_name(int snum,
-                                       SPOOL_NOTIFY_INFO_DATA *data,
+                                       struct spoolss_Notify *data,
                                        print_queue_struct *queue,
                                        NT_PRINTER_INFO_LEVEL *printer,
                                        TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
        /* the notify name should not contain the \\server\ part */
        char *p = strrchr(printer->info_2->printername, '\\');
 
@@ -2790,17 +2949,7 @@ void spoolss_notify_printer_name(int snum,
                p++;
        }
 
-       len = rpcstr_push_talloc(mem_ctx, &temp, p);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
 }
 
 /*******************************************************************
@@ -2808,26 +2957,12 @@ void spoolss_notify_printer_name(int snum,
  ********************************************************************/
 
 void spoolss_notify_share_name(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
-
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
 }
 
 /*******************************************************************
@@ -2835,27 +2970,12 @@ void spoolss_notify_share_name(int snum,
  ********************************************************************/
 
 void spoolss_notify_port_name(int snum,
-                                    SPOOL_NOTIFY_INFO_DATA *data,
+                                    struct spoolss_Notify *data,
                                     print_queue_struct *queue,
                                     NT_PRINTER_INFO_LEVEL *printer,
                                     TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       /* even if it's strange, that's consistant in all the code */
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
 }
 
 /*******************************************************************
@@ -2864,25 +2984,12 @@ void spoolss_notify_port_name(int snum,
  ********************************************************************/
 
 void spoolss_notify_driver_name(int snum,
-                                      SPOOL_NOTIFY_INFO_DATA *data,
+                                      struct spoolss_Notify *data,
                                       print_queue_struct *queue,
                                       NT_PRINTER_INFO_LEVEL *printer,
                                       TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
 }
 
 /*******************************************************************
@@ -2890,28 +2997,20 @@ void spoolss_notify_driver_name(int snum,
  ********************************************************************/
 
 void spoolss_notify_comment(int snum,
-                                  SPOOL_NOTIFY_INFO_DATA *data,
+                                  struct spoolss_Notify *data,
                                   print_queue_struct *queue,
                                   NT_PRINTER_INFO_LEVEL *printer,
                                   TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
+       char *p;
 
-       if (*printer->info_2->comment == '\0')
-               len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
-       else
-               len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
-
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
+       if (*printer->info_2->comment == '\0') {
+               p = lp_comment(snum);
        } else {
-               data->notify_data.data.string = NULL;
+               p = printer->info_2->comment;
        }
+
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
 }
 
 /*******************************************************************
@@ -2920,25 +3019,12 @@ void spoolss_notify_comment(int snum,
  ********************************************************************/
 
 void spoolss_notify_location(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
 }
 
 /*******************************************************************
@@ -2947,14 +3033,13 @@ void spoolss_notify_location(int snum,
  ********************************************************************/
 
 static void spoolss_notify_devmode(int snum,
-                                  SPOOL_NOTIFY_INFO_DATA *data,
+                                  struct spoolss_Notify *data,
                                   print_queue_struct *queue,
                                   NT_PRINTER_INFO_LEVEL *printer,
                                   TALLOC_CTX *mem_ctx)
 {
        /* for a dummy implementation we have to zero the fields */
-       data->notify_data.data.length = 0;
-       data->notify_data.data.string = NULL;
+       SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
 }
 
 /*******************************************************************
@@ -2962,25 +3047,12 @@ static void spoolss_notify_devmode(int snum,
  ********************************************************************/
 
 void spoolss_notify_sepfile(int snum,
-                                  SPOOL_NOTIFY_INFO_DATA *data,
+                                  struct spoolss_Notify *data,
                                   print_queue_struct *queue,
                                   NT_PRINTER_INFO_LEVEL *printer,
                                   TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
 }
 
 /*******************************************************************
@@ -2989,25 +3061,12 @@ void spoolss_notify_sepfile(int snum,
  ********************************************************************/
 
 void spoolss_notify_print_processor(int snum,
-                                          SPOOL_NOTIFY_INFO_DATA *data,
+                                          struct spoolss_Notify *data,
                                           print_queue_struct *queue,
                                           NT_PRINTER_INFO_LEVEL *printer,
                                           TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
 }
 
 /*******************************************************************
@@ -3016,25 +3075,12 @@ void spoolss_notify_print_processor(int snum,
  ********************************************************************/
 
 void spoolss_notify_parameters(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
 }
 
 /*******************************************************************
@@ -3043,25 +3089,12 @@ void spoolss_notify_parameters(int snum,
  ********************************************************************/
 
 void spoolss_notify_datatype(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
 }
 
 /*******************************************************************
@@ -3071,13 +3104,14 @@ void spoolss_notify_datatype(int snum,
  ********************************************************************/
 
 static void spoolss_notify_security_desc(int snum,
-                                        SPOOL_NOTIFY_INFO_DATA *data,
+                                        struct spoolss_Notify *data,
                                         print_queue_struct *queue,
                                         NT_PRINTER_INFO_LEVEL *printer,
                                         TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
-       data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
+       SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
+                                         printer->info_2->secdesc_buf->sd_size,
+                                         printer->info_2->secdesc_buf->sd);
 }
 
 /*******************************************************************
@@ -3086,13 +3120,12 @@ static void spoolss_notify_security_desc(int snum,
  ********************************************************************/
 
 void spoolss_notify_attributes(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = printer->info_2->attributes;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
 }
 
 /*******************************************************************
@@ -3100,13 +3133,12 @@ void spoolss_notify_attributes(int snum,
  ********************************************************************/
 
 static void spoolss_notify_priority(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = printer->info_2->priority;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
 }
 
 /*******************************************************************
@@ -3114,13 +3146,12 @@ static void spoolss_notify_priority(int snum,
  ********************************************************************/
 
 static void spoolss_notify_default_priority(int snum,
-                                           SPOOL_NOTIFY_INFO_DATA *data,
+                                           struct spoolss_Notify *data,
                                            print_queue_struct *queue,
                                            NT_PRINTER_INFO_LEVEL *printer,
                                            TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = printer->info_2->default_priority;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
 }
 
 /*******************************************************************
@@ -3128,13 +3159,12 @@ static void spoolss_notify_default_priority(int snum,
  ********************************************************************/
 
 static void spoolss_notify_start_time(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = printer->info_2->starttime;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
 }
 
 /*******************************************************************
@@ -3142,13 +3172,12 @@ static void spoolss_notify_start_time(int snum,
  ********************************************************************/
 
 static void spoolss_notify_until_time(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = printer->info_2->untiltime;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
 }
 
 /*******************************************************************
@@ -3156,7 +3185,7 @@ static void spoolss_notify_until_time(int snum,
  ********************************************************************/
 
 static void spoolss_notify_status(int snum,
-                                 SPOOL_NOTIFY_INFO_DATA *data,
+                                 struct spoolss_Notify *data,
                                  print_queue_struct *queue,
                                  NT_PRINTER_INFO_LEVEL *printer,
                                  TALLOC_CTX *mem_ctx)
@@ -3164,8 +3193,7 @@ static void spoolss_notify_status(int snum,
        print_status_struct status;
 
        print_queue_length(snum, &status);
-       data->notify_data.value[0]=(uint32) status.status;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
 }
 
 /*******************************************************************
@@ -3173,13 +3201,12 @@ static void spoolss_notify_status(int snum,
  ********************************************************************/
 
 void spoolss_notify_cjobs(int snum,
-                                SPOOL_NOTIFY_INFO_DATA *data,
+                                struct spoolss_Notify *data,
                                 print_queue_struct *queue,
                                 NT_PRINTER_INFO_LEVEL *printer,
                                 TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0] = print_queue_length(snum, NULL);
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
 }
 
 /*******************************************************************
@@ -3187,15 +3214,14 @@ void spoolss_notify_cjobs(int snum,
  ********************************************************************/
 
 static void spoolss_notify_average_ppm(int snum,
-                                      SPOOL_NOTIFY_INFO_DATA *data,
+                                      struct spoolss_Notify *data,
                                       print_queue_struct *queue,
                                       NT_PRINTER_INFO_LEVEL *printer,
                                       TALLOC_CTX *mem_ctx)
 {
        /* always respond 8 pages per minutes */
        /* a little hard ! */
-       data->notify_data.value[0] = printer->info_2->averageppm;
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
 }
 
 /*******************************************************************
@@ -3203,25 +3229,12 @@ static void spoolss_notify_average_ppm(int snum,
  ********************************************************************/
 
 static void spoolss_notify_username(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
 }
 
 /*******************************************************************
@@ -3229,13 +3242,12 @@ static void spoolss_notify_username(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_status(int snum,
-                                     SPOOL_NOTIFY_INFO_DATA *data,
+                                     struct spoolss_Notify *data,
                                      print_queue_struct *queue,
                                      NT_PRINTER_INFO_LEVEL *printer,
                                      TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=nt_printj_status(queue->status);
-       data->notify_data.value[1] = 0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
 }
 
 /*******************************************************************
@@ -3243,25 +3255,12 @@ static void spoolss_notify_job_status(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_name(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
-
-       len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
 }
 
 /*******************************************************************
@@ -3269,7 +3268,7 @@ static void spoolss_notify_job_name(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_status_string(int snum,
-                                            SPOOL_NOTIFY_INFO_DATA *data,
+                                            struct spoolss_Notify *data,
                                             print_queue_struct *queue,
                                             NT_PRINTER_INFO_LEVEL *printer,
                                             TALLOC_CTX *mem_ctx)
@@ -3279,8 +3278,6 @@ static void spoolss_notify_job_status_string(int snum,
         */
 
        const char *p = "";
-       smb_ucs2_t *temp = NULL;
-       uint32 len;
 
 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
        p = "unknown";
@@ -3301,17 +3298,7 @@ static void spoolss_notify_job_status_string(int snum,
        }
 #endif /* NO LONGER NEEDED. */
 
-       len = rpcstr_push_talloc(mem_ctx, &temp, p);
-       if (len == (uint32)-1) {
-               len = 0;
-       }
-
-       data->notify_data.data.length = len;
-       if (len) {
-               data->notify_data.data.string = (uint16 *)temp;
-       } else {
-               data->notify_data.data.string = NULL;
-       }
+       SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
 }
 
 /*******************************************************************
@@ -3319,13 +3306,12 @@ static void spoolss_notify_job_status_string(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_time(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=0x0;
-       data->notify_data.value[1]=0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
 }
 
 /*******************************************************************
@@ -3333,39 +3319,37 @@ static void spoolss_notify_job_time(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_size(int snum,
-                                   SPOOL_NOTIFY_INFO_DATA *data,
+                                   struct spoolss_Notify *data,
                                    print_queue_struct *queue,
                                    NT_PRINTER_INFO_LEVEL *printer,
                                    TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=queue->size;
-       data->notify_data.value[1]=0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
 }
 
 /*******************************************************************
  * fill a notify_info_data with page info
  ********************************************************************/
 static void spoolss_notify_total_pages(int snum,
-                               SPOOL_NOTIFY_INFO_DATA *data,
+                               struct spoolss_Notify *data,
                                print_queue_struct *queue,
                                NT_PRINTER_INFO_LEVEL *printer,
                                TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=queue->page_count;
-       data->notify_data.value[1]=0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
 }
 
 /*******************************************************************
  * fill a notify_info_data with pages printed info.
  ********************************************************************/
 static void spoolss_notify_pages_printed(int snum,
-                               SPOOL_NOTIFY_INFO_DATA *data,
+                               struct spoolss_Notify *data,
                                print_queue_struct *queue,
                                NT_PRINTER_INFO_LEVEL *printer,
                                TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=0;  /* Add code when back-end tracks this */
-       data->notify_data.value[1]=0;
+       /* Add code when back-end tracks this */
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
 }
 
 /*******************************************************************
@@ -3373,13 +3357,12 @@ static void spoolss_notify_pages_printed(int snum,
  ********************************************************************/
 
 static void spoolss_notify_job_position(int snum,
-                                       SPOOL_NOTIFY_INFO_DATA *data,
+                                       struct spoolss_Notify *data,
                                        print_queue_struct *queue,
                                        NT_PRINTER_INFO_LEVEL *printer,
                                        TALLOC_CTX *mem_ctx)
 {
-       data->notify_data.value[0]=queue->job;
-       data->notify_data.value[1]=0;
+       SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
 }
 
 /*******************************************************************
@@ -3387,44 +3370,18 @@ static void spoolss_notify_job_position(int snum,
  ********************************************************************/
 
 static void spoolss_notify_submitted_time(int snum,
-                                         SPOOL_NOTIFY_INFO_DATA *data,
+                                         struct spoolss_Notify *data,
                                          print_queue_struct *queue,
                                          NT_PRINTER_INFO_LEVEL *printer,
                                          TALLOC_CTX *mem_ctx)
 {
-       struct tm *t;
-       uint32 len;
-       SYSTEMTIME st;
-       char *p;
-
-       t=gmtime(&queue->time);
-
-       len = sizeof(SYSTEMTIME);
-
-       data->notify_data.data.length = len;
-       data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
+       data->data.string.string = NULL;
+       data->data.string.size = 0;
 
-       if (!data->notify_data.data.string) {
-               data->notify_data.data.length = 0;
-               return;
-       }
-
-       make_systemtime(&st, t);
-
-       /*
-        * Systemtime must be linearized as a set of UINT16's.
-        * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
-        */
+       init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
+                              &data->data.string.string,
+                              &data->data.string.size);
 
-       p = (char *)data->notify_data.data.string;
-       SSVAL(p, 0, st.year);
-       SSVAL(p, 2, st.month);
-       SSVAL(p, 4, st.dayofweek);
-       SSVAL(p, 6, st.day);
-       SSVAL(p, 8, st.hour);
-        SSVAL(p, 10, st.minute);
-       SSVAL(p, 12, st.second);
-       SSVAL(p, 14, st.milliseconds);
 }
 
 struct s_notify_info_data_table
@@ -3433,7 +3390,7 @@ struct s_notify_info_data_table
        uint16 field;
        const char *name;
        uint32 size;
-       void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
+       void (*fn) (int snum, struct spoolss_Notify *data,
                    print_queue_struct *queue,
                    NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
 };
@@ -3571,16 +3528,12 @@ static bool search_notify(uint16 type, uint16 field, int *value)
 /****************************************************************************
 ****************************************************************************/
 
-void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
+void construct_info_data(struct spoolss_Notify *info_data, uint16 type, uint16 field, int id)
 {
-       info_data->type     = type;
-       info_data->field    = field;
-       info_data->reserved = 0;
-
-       info_data->size     = size_of_notify_info_data(type, field);
-       info_data->enc_type = type_of_notify_info_data(type, field);
-
-       info_data->id = id;
+       info_data->type                 = type;
+       info_data->field                = field;
+       info_data->variable_type        = size_of_notify_info_data(type, field);
+       info_data->job_id               = id;
 }
 
 /*******************************************************************
@@ -3598,7 +3551,7 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY
        uint16 type;
        uint16 field;
 
-       SPOOL_NOTIFY_INFO_DATA *current_data;
+       struct spoolss_Notify *current_data;
        NT_PRINTER_INFO_LEVEL *printer = NULL;
        print_queue_struct *queue=NULL;
 
@@ -3619,7 +3572,7 @@ static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY
                if (!search_notify(type, field, &j) )
                        continue;
 
-               if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
+               if((info->data=SMB_REALLOC_ARRAY(info->data, struct spoolss_Notify, info->count+1)) == NULL) {
                        DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
                        free_a_printer(&printer, 2);
                        return False;
@@ -3659,7 +3612,7 @@ static bool construct_notify_jobs_info(print_queue_struct *queue,
        uint16 type;
        uint16 field;
 
-       SPOOL_NOTIFY_INFO_DATA *current_data;
+       struct spoolss_Notify *current_data;
 
        DEBUG(4,("construct_notify_jobs_info\n"));
 
@@ -3675,7 +3628,7 @@ static bool construct_notify_jobs_info(print_queue_struct *queue,
                if (!search_notify(type, field, &j) )
                        continue;
 
-               if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
+               if((info->data=SMB_REALLOC_ARRAY(info->data, struct spoolss_Notify, info->count+1)) == NULL) {
                        DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
                        return False;
                }
@@ -4723,6 +4676,10 @@ WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_
                return WERR_INVALID_PARAM;
        }
 
+       if (offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
+
        rpcbuf_move(q_u->buffer, &r_u->buffer);
        buffer = r_u->buffer;
 
@@ -5080,6 +5037,10 @@ WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GET
                return WERR_INVALID_PARAM;
        }
 
+       if (offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
+
        rpcbuf_move(q_u->buffer, &r_u->buffer);
        buffer = r_u->buffer;
 
@@ -5741,6 +5702,10 @@ WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_
                return WERR_INVALID_PARAM;
        }
 
+       if (offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
+
        rpcbuf_move(q_u->buffer, &r_u->buffer);
        buffer = r_u->buffer;
 
@@ -5830,29 +5795,31 @@ WERROR _spoolss_EndPagePrinter(pipes_struct *p,
        return WERR_OK;
 }
 
-/********************************************************************
- * api_spoolss_getprinter
- * called from the spoolss dispatcher
- *
- ********************************************************************/
+/****************************************************************
+ _spoolss_StartDocPrinter
+****************************************************************/
 
-WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
+WERROR _spoolss_StartDocPrinter(pipes_struct *p,
+                               struct spoolss_StartDocPrinter *r)
 {
-       POLICY_HND *handle = &q_u->handle;
-       DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
-       uint32 *jobid = &r_u->jobid;
-       TALLOC_CTX *ctx = p->mem_ctx;
-       DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
+       POLICY_HND *handle = r->in.handle;
+       uint32_t *jobid = r->out.job_id;
+       struct spoolss_DocumentInfo1 *info_1;
        int snum;
-       char *jobname = NULL;
-       fstring datatype;
        Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
 
        if (!Printer) {
-               DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
+               DEBUG(2,("_spoolss_StartDocPrinter: "
+                       "Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
                return WERR_BADFID;
        }
 
+       if (r->in.level != 1) {
+               return WERR_UNKNOWN_LEVEL;
+       }
+
+       info_1 = r->in.info.info1;
+
        /*
         * a nice thing with NT is it doesn't listen to what you tell it.
         * when asked to send _only_ RAW datas, it tries to send datas
@@ -5861,9 +5828,8 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S
         * So I add checks like in NT Server ...
         */
 
-       if (info_1->p_datatype != 0) {
-               unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
-               if (strcmp(datatype, "RAW") != 0) {
+       if (info_1->datatype) {
+               if (strcmp(info_1->datatype, "RAW") != 0) {
                        (*jobid)=0;
                        return WERR_INVALID_DATATYPE;
                }
@@ -5874,9 +5840,8 @@ WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, S
                return WERR_BADFID;
        }
 
-       jobname = unistr2_to_ascii_talloc(ctx, &info_1->docname);
-
-       Printer->jobid = print_job_start(p->server_info, snum, jobname,
+       Printer->jobid = print_job_start(p->server_info, snum,
+                                        CONST_DISCARD(char *,info_1->document_name),
                                         Printer->nt_devmode);
 
        /* An error occured in print_job_start() so return an appropriate
@@ -5965,18 +5930,18 @@ static WERROR control_printer(POLICY_HND *handle, uint32 command,
                return WERR_BADFID;
 
        switch (command) {
-       case PRINTER_CONTROL_PAUSE:
+       case SPOOLSS_PRINTER_CONTROL_PAUSE:
                if (print_queue_pause(p->server_info, snum, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
-       case PRINTER_CONTROL_RESUME:
-       case PRINTER_CONTROL_UNPAUSE:
+       case SPOOLSS_PRINTER_CONTROL_RESUME:
+       case SPOOLSS_PRINTER_CONTROL_UNPAUSE:
                if (print_queue_resume(p->server_info, snum, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
-       case PRINTER_CONTROL_PURGE:
+       case SPOOLSS_PRINTER_CONTROL_PURGE:
                if (print_queue_purge(p->server_info, snum, &errcode)) {
                        errcode = WERR_OK;
                }
@@ -6022,8 +5987,7 @@ WERROR _spoolss_AbortPrinter(pipes_struct *p,
  * when updating a printer description
  ********************************************************************/
 
-static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
-                                const SPOOL_PRINTER_INFO_LEVEL *info,
+static WERROR update_printer_sec(POLICY_HND *handle,
                                 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
 {
        SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
@@ -6309,9 +6273,9 @@ 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, uint32 level,
-                           const SPOOL_PRINTER_INFO_LEVEL *info,
-                           DEVICEMODE *devmode)
+static WERROR update_printer(pipes_struct *p, POLICY_HND *handle,
+                            struct spoolss_SetPrinterInfoCtr *info_ctr,
+                            struct spoolss_DeviceMode *devmode)
 {
        int snum;
        NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
@@ -6348,7 +6312,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
         * just read from the tdb in the pointer 'printer'.
         */
 
-       if (!convert_printer_info(info, printer, level)) {
+       if (!convert_printer_info_new(info_ctr, printer)) {
                result =  WERR_NOMEM;
                goto done;
        }
@@ -6358,8 +6322,9 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
                   convert it and link it*/
 
                DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
-               if (!convert_devicemode(printer->info_2->printername, devmode,
-                               &printer->info_2->devmode)) {
+               if (!convert_devicemode_new(printer->info_2->printername,
+                                           devmode,
+                                           &printer->info_2->devmode)) {
                        result =  WERR_NOMEM;
                        goto done;
                }
@@ -6503,10 +6468,9 @@ done:
 /****************************************************************************
 ****************************************************************************/
 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
-                                  const SPOOL_PRINTER_INFO_LEVEL *info)
+                                          struct spoolss_SetPrinterInfo7 *info7)
 {
 #ifdef HAVE_ADS
-       SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
        int snum;
        Printer_entry *Printer;
 
@@ -6531,42 +6495,45 @@ static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
        return WERR_UNKNOWN_LEVEL;
 #endif
 }
-/****************************************************************************
-****************************************************************************/
 
-WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
+/****************************************************************
+ _spoolss_SetPrinter
+****************************************************************/
+
+WERROR _spoolss_SetPrinter(pipes_struct *p,
+                          struct spoolss_SetPrinter *r)
 {
-       POLICY_HND *handle = &q_u->handle;
-       uint32 level = q_u->level;
-       SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
-       DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
-       SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
-       uint32 command = q_u->command;
+       POLICY_HND *handle = r->in.handle;
        WERROR result;
 
        Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
 
        if (!Printer) {
-               DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
+               DEBUG(2,("_spoolss_SetPrinter: Invalid handle (%s:%u:%u)\n",
+                       OUR_HANDLE(handle)));
                return WERR_BADFID;
        }
 
        /* check the level */
-       switch (level) {
+       switch (r->in.info_ctr->level) {
                case 0:
-                       return control_printer(handle, command, p);
+                       return control_printer(handle, r->in.command, p);
                case 2:
-                       result = update_printer(p, handle, level, info, devmode_ctr.devmode);
+                       result = update_printer(p, handle,
+                                               r->in.info_ctr,
+                                               r->in.devmode_ctr->devmode);
                        if (!W_ERROR_IS_OK(result))
                                return result;
-                       if (secdesc_ctr)
-                               result = update_printer_sec(handle, level, info, p, secdesc_ctr);
+                       if (r->in.secdesc_ctr->sd)
+                               result = update_printer_sec(handle, p,
+                                                           r->in.secdesc_ctr);
                        return result;
                case 3:
-                       return update_printer_sec(handle, level, info, p,
-                                                 secdesc_ctr);
+                       return update_printer_sec(handle, p,
+                                                 r->in.secdesc_ctr);
                case 7:
-                       return publish_or_unpublish_printer(p, handle, info);
+                       return publish_or_unpublish_printer(p, handle,
+                                                           r->in.info_ctr->info.info7);
                default:
                        return WERR_UNKNOWN_LEVEL;
        }
@@ -6828,6 +6795,10 @@ WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJO
                return WERR_INVALID_PARAM;
        }
 
+       if (offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
+
        rpcbuf_move(q_u->buffer, &r_u->buffer);
        buffer = r_u->buffer;
 
@@ -6882,14 +6853,16 @@ WERROR _spoolss_ScheduleJob(pipes_struct *p,
        return WERR_OK;
 }
 
-/****************************************************************************
-****************************************************************************/
+/****************************************************************
+ _spoolss_SetJob
+****************************************************************/
 
-WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
+WERROR _spoolss_SetJob(pipes_struct *p,
+                      struct spoolss_SetJob *r)
 {
-       POLICY_HND *handle = &q_u->handle;
-       uint32 jobid = q_u->jobid;
-       uint32 command = q_u->command;
+       POLICY_HND *handle = r->in.handle;
+       uint32 jobid = r->in.job_id;
+       uint32 command = r->in.command;
 
        int snum;
        WERROR errcode = WERR_BADFUNC;
@@ -6903,19 +6876,19 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u
        }
 
        switch (command) {
-       case JOB_CONTROL_CANCEL:
-       case JOB_CONTROL_DELETE:
+       case SPOOLSS_JOB_CONTROL_CANCEL:
+       case SPOOLSS_JOB_CONTROL_DELETE:
                if (print_job_delete(p->server_info, snum, jobid, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
-       case JOB_CONTROL_PAUSE:
+       case SPOOLSS_JOB_CONTROL_PAUSE:
                if (print_job_pause(p->server_info, snum, jobid, &errcode)) {
                        errcode = WERR_OK;
                }
                break;
-       case JOB_CONTROL_RESTART:
-       case JOB_CONTROL_RESUME:
+       case SPOOLSS_JOB_CONTROL_RESTART:
+       case SPOOLSS_JOB_CONTROL_RESUME:
                if (print_job_resume(p->server_info, snum, jobid, &errcode)) {
                        errcode = WERR_OK;
                }
@@ -7206,6 +7179,10 @@ WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS
                return WERR_INVALID_PARAM;
        }
 
+       if (offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
+
        rpcbuf_move(q_u->buffer, &r_u->buffer);
        buffer = r_u->buffer;
 
@@ -7294,6 +7271,10 @@ WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMF
                return WERR_INVALID_PARAM;
        }
 
+       if (offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
+
        rpcbuf_move(q_u->buffer, &r_u->buffer);
        buffer = r_u->buffer;
 
@@ -7419,6 +7400,8 @@ WERROR _spoolss_GetForm(pipes_struct *p,
                        return WERR_BADFID;
        }
 
+       ZERO_STRUCT(form_1);
+
        switch (level) {
        case 1:
                if (foundBuiltin) {
@@ -7701,6 +7684,10 @@ WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUM
                return WERR_INVALID_PARAM;
        }
 
+       if (offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
+
        rpcbuf_move(q_u->buffer, &r_u->buffer);
        buffer = r_u->buffer;
 
@@ -7722,11 +7709,13 @@ WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUM
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
-                               const SPOOL_PRINTER_INFO_LEVEL *info,
-                               DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
-                               uint32 user_switch, const SPOOL_USER_CTR *user,
-                               POLICY_HND *handle)
+static WERROR spoolss_addprinterex_level_2(pipes_struct *p,
+                                          const char *server,
+                                          struct spoolss_SetPrinterInfoCtr *info_ctr,
+                                          struct spoolss_DeviceMode *devmode,
+                                          struct security_descriptor *sec_desc,
+                                          struct spoolss_UserLevelCtr *user_ctr,
+                                          POLICY_HND *handle)
 {
        NT_PRINTER_INFO_LEVEL *printer = NULL;
        fstring name;
@@ -7739,7 +7728,7 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
        }
 
        /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
-       if (!convert_printer_info(info, printer, 2)) {
+       if (!convert_printer_info_new(info_ctr, printer)) {
                free_a_printer(&printer, 2);
                return WERR_NOMEM;
        }
@@ -7812,8 +7801,9 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
                */
                DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
 
-               if (!convert_devicemode(printer->info_2->printername, devmode,
-                               &printer->info_2->devmode))
+               if (!convert_devicemode_new(printer->info_2->printername,
+                                           devmode,
+                                           &printer->info_2->devmode))
                        return  WERR_NOMEM;
        }
 
@@ -7828,6 +7818,7 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
                /* Handle open failed - remove addition. */
                del_a_printer(printer->info_2->sharename);
                free_a_printer(&printer,2);
+               ZERO_STRUCTP(handle);
                return WERR_ACCESS_DENIED;
        }
 
@@ -7837,45 +7828,65 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_
        return WERR_OK;
 }
 
-/****************************************************************************
-****************************************************************************/
+/****************************************************************
+ _spoolss_AddPrinterEx
+****************************************************************/
 
-WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
+WERROR _spoolss_AddPrinterEx(pipes_struct *p,
+                            struct spoolss_AddPrinterEx *r)
 {
-       UNISTR2 *uni_srv_name = q_u->server_name;
-       uint32 level = q_u->level;
-       SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
-       DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
-       SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
-       uint32 user_switch = q_u->user_switch;
-       SPOOL_USER_CTR *user = &q_u->user_ctr;
-       POLICY_HND *handle = &r_u->handle;
-
-       switch (level) {
-               case 1:
-                       /* we don't handle yet */
-                       /* but I know what to do ... */
-                       return WERR_UNKNOWN_LEVEL;
-               case 2:
-                       return spoolss_addprinterex_level_2(p, uni_srv_name, info,
-                                                           devmode, sdb,
-                                                           user_switch, user, handle);
-               default:
-                       return WERR_UNKNOWN_LEVEL;
+       switch (r->in.info_ctr->level) {
+       case 1:
+               /* we don't handle yet */
+               /* but I know what to do ... */
+               return WERR_UNKNOWN_LEVEL;
+       case 2:
+               return spoolss_addprinterex_level_2(p, r->in.server,
+                                                   r->in.info_ctr,
+                                                   r->in.devmode_ctr->devmode,
+                                                   r->in.secdesc_ctr->sd,
+                                                   r->in.userlevel_ctr,
+                                                   r->out.handle);
+       default:
+               return WERR_UNKNOWN_LEVEL;
        }
 }
 
-/****************************************************************************
-****************************************************************************/
+/****************************************************************
+ _spoolss_AddPrinterDriver
+****************************************************************/
 
-WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
+WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
+                                struct spoolss_AddPrinterDriver *r)
 {
-       uint32 level = q_u->level;
-       SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
+       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;
+       const char *fn;
+
+       switch (p->hdr_req.opnum) {
+               case NDR_SPOOLSS_ADDPRINTERDRIVER:
+                       fn = "_spoolss_AddPrinterDriver";
+                       break;
+               case NDR_SPOOLSS_ADDPRINTERDRIVEREX:
+                       fn = "_spoolss_AddPrinterDriverEx";
+                       break;
+               default:
+                       return WERR_INVALID_PARAM;
+       }
+
+
+       /* FIXME */
+       if (level != 3 && 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));
+               return WERR_UNKNOWN_LEVEL;
+       }
 
        ZERO_STRUCT(driver);
 
@@ -7919,8 +7930,8 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,
         */
 
        if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
-               DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
-                       driver_name));
+               DEBUG(0,("%s: Failed to send message about upgrading driver [%s]!\n",
+                       fn, driver_name));
        }
 
        /*
@@ -7944,8 +7955,8 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,
                 * 9x printer driver - never delete init data
                */
                case 0:
-                       DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
-                                       driver_name));
+                       DEBUG(10,("%s: init data not deleted for 9x driver [%s]\n",
+                               fn, driver_name));
                        break;
 
                /*
@@ -7961,14 +7972,15 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,
                                 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
                                */
                                if (!del_driver_init(driver_name))
-                                       DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
+                                       DEBUG(6,("%s: del_driver_init(%s) Nt failed!\n",
+                                               fn, driver_name));
                        } else {
                                /*
                                 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
                                */
                                free_a_printer_driver(driver1,3);
-                               DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
-                                               driver_name));
+                               DEBUG(10,("%s: init data not deleted for Nt driver [%s]\n",
+                                       fn, driver_name));
                        }
                }
                break;
@@ -7978,11 +7990,12 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,
                */
                case 3:
                        if (!del_driver_init(driver_name))
-                               DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
+                               DEBUG(6,("%s: del_driver_init(%s) 2k/Xp failed!\n",
+                                       fn, driver_name));
                        break;
 
                default:
-                       DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
+                       DEBUG(0,("%s: invalid level=%d\n", fn, level));
                        break;
        }
 
@@ -7992,64 +8005,47 @@ done:
        return err;
 }
 
-/********************************************************************
* spoolss_addprinterdriverex
- ********************************************************************/
+/****************************************************************
_spoolss_AddPrinterDriverEx
+****************************************************************/
 
-WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
+WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
+                                  struct spoolss_AddPrinterDriverEx *r)
 {
-       SPOOL_Q_ADDPRINTERDRIVER q_u_local;
-       SPOOL_R_ADDPRINTERDRIVER r_u_local;
+       struct spoolss_AddPrinterDriver a;
 
        /*
         * we only support the semantics of AddPrinterDriver()
         * i.e. only copy files that are newer than existing ones
         */
 
-       if ( q_u->copy_flags != APD_COPY_NEW_FILES )
+       if (r->in.flags != APD_COPY_NEW_FILES) {
                return WERR_ACCESS_DENIED;
+       }
 
-       ZERO_STRUCT(q_u_local);
-       ZERO_STRUCT(r_u_local);
-
-       /* just pass the information off to _spoolss_addprinterdriver() */
-       q_u_local.server_name_ptr = q_u->server_name_ptr;
-       copy_unistr2(&q_u_local.server_name, &q_u->server_name);
-       q_u_local.level = q_u->level;
-       memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
-
-       return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
-}
-
-/****************************************************************************
-****************************************************************************/
+       a.in.servername         = r->in.servername;
+       a.in.info_ctr           = r->in.info_ctr;
 
-static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
-{
-       init_unistr(&info->name, name);
+       return _spoolss_AddPrinterDriver(p, &a);
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
+static WERROR getprinterdriverdir_level_1(TALLOC_CTX *mem_ctx,
+                                         const char *servername,
+                                         const char *environment,
+                                         struct spoolss_DriverDirectoryInfo1 *info1,
+                                         uint32_t offered,
+                                         uint32_t *needed)
 {
        char *path = NULL;
-       char *long_archi = NULL;
-       char *servername = NULL;
        const char *pservername = NULL;
+       const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
        const char *short_archi;
-       DRIVER_DIRECTORY_1 *info=NULL;
-       WERROR result = WERR_OK;
-       TALLOC_CTX *ctx = talloc_tos();
 
-       servername = unistr2_to_ascii_talloc(ctx, name);
-       if (!servername) {
-               return WERR_NOMEM;
-       }
-       long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
-       if (!long_archi) {
-               return WERR_NOMEM;
+       if (environment) {
+               long_archi = environment;
        }
 
        pservername = canon_servername(servername);
@@ -8060,71 +8056,67 @@ static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environmen
        if (!(short_archi = get_short_archi(long_archi)))
                return WERR_INVALID_ENVIRONMENT;
 
-       if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
-               return WERR_NOMEM;
-
-       path = talloc_asprintf(ctx,
+       path = talloc_asprintf(mem_ctx,
                        "\\\\%s\\print$\\%s", pservername, short_archi);
        if (!path) {
-               result = WERR_NOMEM;
-               goto out;
+               return WERR_NOMEM;
        }
 
        DEBUG(4,("printer driver directory: [%s]\n", path));
 
-       fill_driverdir_1(info, path);
+       info1->directory_name = path;
 
-       *needed += spoolss_size_driverdir_info_1(info);
+       *needed += ndr_size_spoolss_DriverDirectoryInfo1(info1, NULL, 0);
 
        if (*needed > offered) {
-               result = WERR_INSUFFICIENT_BUFFER;
-               goto out;
-       }
-
-       if (!rpcbuf_alloc_size(buffer, *needed)) {
-               result = WERR_NOMEM;
-               goto out;
+               talloc_free(path);
+               ZERO_STRUCTP(info1);
+               return WERR_INSUFFICIENT_BUFFER;
        }
 
-       smb_io_driverdir_1("", buffer, info, 0);
-
-out:
-       SAFE_FREE(info);
-
-       return result;
+       return WERR_OK;
 }
 
-/****************************************************************************
-****************************************************************************/
+/****************************************************************
+ _spoolss_GetPrinterDriverDirectory
+****************************************************************/
 
-WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
+WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
+                                         struct spoolss_GetPrinterDriverDirectory *r)
 {
-       UNISTR2 *name = &q_u->name;
-       UNISTR2 *uni_environment = &q_u->environment;
-       uint32 level = q_u->level;
-       RPC_BUFFER *buffer = NULL;
-       uint32 offered = q_u->offered;
-       uint32 *needed = &r_u->needed;
+       WERROR werror;
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer && (offered!=0)) {
+       if (!r->in.buffer && (r->in.offered != 0)) {
                return WERR_INVALID_PARAM;
        }
 
-       rpcbuf_move(q_u->buffer, &r_u->buffer);
-       buffer = r_u->buffer;
+       if (r->in.offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
 
-       DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
+       DEBUG(4,("_spoolss_GetPrinterDriverDirectory\n"));
 
-       *needed=0;
+       *r->out.needed = 0;
 
-       switch(level) {
+       switch (r->in.level) {
        case 1:
-               return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
+               werror = getprinterdriverdir_level_1(p->mem_ctx,
+                                                    r->in.server,
+                                                    r->in.environment,
+                                                    &r->out.info->info1,
+                                                    r->in.offered,
+                                                    r->out.needed);
+               if (!W_ERROR_IS_OK(werror)) {
+                       TALLOC_FREE(r->out.info);
+               }
+               break;
        default:
                return WERR_UNKNOWN_LEVEL;
        }
+
+       return werror;
 }
 
 /****************************************************************************
@@ -8394,16 +8386,18 @@ done:
        return status;
 }
 
-/****************************************************************************
-****************************************************************************/
+/****************************************************************
+ _spoolss_ResetPrinter
+****************************************************************/
 
-WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
+WERROR _spoolss_ResetPrinter(pipes_struct *p,
+                            struct spoolss_ResetPrinter *r)
 {
-       POLICY_HND      *handle = &q_u->handle;
+       POLICY_HND      *handle = r->in.handle;
        Printer_entry   *Printer=find_printer_index_by_hnd(p, handle);
        int             snum;
 
-       DEBUG(5,("_spoolss_resetprinter\n"));
+       DEBUG(5,("_spoolss_ResetPrinter\n"));
 
        /*
         * All we do is to check to see if the handle and queue is valid.
@@ -8412,7 +8406,8 @@ WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R
         */
 
        if (!Printer) {
-               DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+               DEBUG(2,("_spoolss_ResetPrinter: Invalid handle (%s:%u:%u).\n",
+                       OUR_HANDLE(handle)));
                return WERR_BADFID;
        }
 
@@ -8746,6 +8741,10 @@ WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS
                return WERR_INVALID_PARAM;
        }
 
+       if (offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
+
        rpcbuf_move(q_u->buffer, &r_u->buffer);
        buffer = r_u->buffer;
 
@@ -8825,6 +8824,10 @@ WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDAT
                return WERR_INVALID_PARAM;
        }
 
+       if (offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
+
        rpcbuf_move(q_u->buffer, &r_u->buffer);
        buffer = r_u->buffer;
 
@@ -8953,6 +8956,10 @@ WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_
                return WERR_INVALID_PARAM;
        }
 
+       if (offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
+
        rpcbuf_move(q_u->buffer, &r_u->buffer);
        buffer = r_u->buffer;
 
@@ -9129,6 +9136,10 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_
                return WERR_INVALID_PARAM;
        }
 
+       if (offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
+
        rpcbuf_move(q_u->buffer, &r_u->buffer);
        buffer = r_u->buffer;
 
@@ -9168,22 +9179,20 @@ WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_
        return wstatus;
 }
 
-/********************************************************************
spoolss_getprinterdataex
+/****************************************************************
_spoolss_GetPrinterDataEx
 
  From MSDN documentation of GetPrinterDataEx: pass request
  to GetPrinterData if key is "PrinterDriverData".
- ********************************************************************/
+****************************************************************/
 
-WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
+WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
+                                struct spoolss_GetPrinterDataEx *r)
 {
-       POLICY_HND      *handle = &q_u->handle;
-       uint32          in_size = q_u->size;
-       uint32          *type = &r_u->type;
-       uint32          *out_size = &r_u->size;
-       uint8           **data = &r_u->data;
-       uint32          *needed = &r_u->needed;
-       fstring         keyname, valuename;
+       POLICY_HND      *handle = r->in.handle;
+       uint8           *data = NULL;
+       const char      *keyname = r->in.key_name;
+       const char      *valuename = r->in.value_name;
 
        Printer_entry   *Printer = find_printer_index_by_hnd(p, handle);
 
@@ -9191,22 +9200,19 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u,
        int                     snum = 0;
        WERROR                  status = WERR_OK;
 
-       DEBUG(4,("_spoolss_getprinterdataex\n"));
-
-        unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
-        unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
+       DEBUG(4,("_spoolss_GetPrinterDataEx\n"));
 
-       DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
+       DEBUG(10, ("_spoolss_GetPrinterDataEx: key => [%s], value => [%s]\n",
                keyname, valuename));
 
        /* in case of problem, return some default values */
 
-       *needed   = 0;
-       *type     = 0;
-       *out_size = in_size;
+       *r->out.needed  = 0;
+       *r->out.type    = 0;
 
        if (!Printer) {
-               DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+               DEBUG(2,("_spoolss_GetPrinterDataEx: "
+                       "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
                status = WERR_BADFID;
                goto done;
        }
@@ -9214,7 +9220,8 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u,
        /* 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"));
+               DEBUG(10,("_spoolss_GetPrinterDataEx: "
+                       "Not implemented for server handles yet\n"));
                status = WERR_INVALID_PARAM;
                goto done;
        }
@@ -9233,7 +9240,8 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u,
        }
 
        if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
-               DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
+               DEBUG(4,("_spoolss_GetPrinterDataEx: "
+                       "Invalid keyname [%s]\n", keyname ));
                free_a_printer( &printer, 2 );
                status = WERR_BADFILE;
                goto done;
@@ -9241,66 +9249,53 @@ WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u,
 
        /* When given a new keyname, we should just create it */
 
-       status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
+       status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename,
+                                    r->out.type, &data, r->out.needed,
+                                    r->in.offered );
 
-       if (*needed > *out_size)
+       if (*r->out.needed > r->in.offered) {
                status = WERR_MORE_DATA;
+       }
 
-done:
-       if ( !W_ERROR_IS_OK(status) )
-       {
-               DEBUG(5, ("error: allocating %d\n", *out_size));
-
-               /* reply this param doesn't exist */
-
-               if ( *out_size )
-               {
-                       if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
-                               status = WERR_NOMEM;
-                               goto done;
-                       }
-               } else {
-                       *data = NULL;
-               }
+       if (W_ERROR_IS_OK(status)) {
+               memcpy(r->out.buffer, data, r->in.offered);
        }
 
+done:
        if ( printer )
        free_a_printer( &printer, 2 );
 
        return status;
 }
 
-/********************************************************************
* spoolss_setprinterdataex
- ********************************************************************/
+/****************************************************************
_spoolss_SetPrinterDataEx
+****************************************************************/
 
-WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
+WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
+                                struct spoolss_SetPrinterDataEx *r)
 {
-       POLICY_HND              *handle = &q_u->handle;
-       uint32                  type = q_u->type;
-       uint8                   *data = q_u->data;
-       uint32                  real_len = q_u->real_len;
-
+       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);
-       fstring                 valuename;
-       fstring                 keyname;
        char                    *oid_string;
 
-       DEBUG(4,("_spoolss_setprinterdataex\n"));
+       DEBUG(4,("_spoolss_SetPrinterDataEx\n"));
 
         /* From MSDN documentation of SetPrinterDataEx: pass request to
            SetPrinterData if key is "PrinterDriverData" */
 
        if (!Printer) {
-               DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+               DEBUG(2,("_spoolss_SetPrinterDataEx: "
+                       "Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
                return WERR_BADFID;
        }
 
        if ( Printer->printer_type == SPLHND_SERVER ) {
-               DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
+               DEBUG(10,("_spoolss_SetPrinterDataEx: "
+                       "Not implemented for server handles yet\n"));
                return WERR_INVALID_PARAM;
        }
 
@@ -9317,7 +9312,8 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u,
 
        if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
        {
-               DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
+               DEBUG(3, ("_spoolss_SetPrinterDataEx: "
+                       "change denied by handle access permissions\n"));
                return WERR_ACCESS_DENIED;
        }
 
@@ -9325,12 +9321,9 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u,
        if (!W_ERROR_IS_OK(status))
                return status;
 
-        unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
-        unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
-
        /* check for OID in valuename */
 
-       if ( (oid_string = strchr( valuename, ',' )) != NULL )
+       if ( (oid_string = strchr( r->in.value_name, ',' )) != NULL )
        {
                *oid_string = '\0';
                oid_string++;
@@ -9338,14 +9331,18 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u,
 
        /* save the registry data */
 
-       status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
+       status = set_printer_dataex( printer, r->in.key_name, r->in.value_name,
+                                    r->in.type, r->in.buffer, r->in.offered );
 
        if ( W_ERROR_IS_OK(status) )
        {
                /* save the OID if one was specified */
                if ( oid_string ) {
-                       fstrcat( keyname, "\\" );
-                       fstrcat( keyname, SPOOL_OID_KEY );
+                       char *str = talloc_asprintf(p->mem_ctx, "%s\\%s",
+                               r->in.key_name, SPOOL_OID_KEY);
+                       if (!str) {
+                               return WERR_NOMEM;
+                       }
 
                        /*
                         * I'm not checking the status here on purpose.  Don't know
@@ -9354,7 +9351,7 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u,
                         * this is right.    --jerry
                         */
 
-                       set_printer_dataex( printer, keyname, valuename,
+                       set_printer_dataex( printer, str, r->in.value_name,
                                            REG_SZ, (uint8 *)oid_string,
                                            strlen(oid_string)+1 );
                }
@@ -9701,80 +9698,79 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
-{
-       init_unistr(&info->name, name);
-}
-
-static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
-                                                UNISTR2 *environment,
-                                                RPC_BUFFER *buffer,
-                                                uint32 offered,
-                                                uint32 *needed)
+static WERROR getprintprocessordirectory_level_1(TALLOC_CTX *mem_ctx,
+                                                const char *servername,
+                                                const char *environment,
+                                                struct spoolss_PrintProcessorDirectoryInfo1 *info1,
+                                                uint32_t offered,
+                                                uint32_t *needed)
 {
-       char *long_archi = NULL;
-       PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
-       WERROR result = WERR_OK;
-       TALLOC_CTX *ctx = talloc_tos();
+       const char *long_archi = SPOOLSS_ARCHITECTURE_NT_X86;
+       const char *short_archi;
 
-       long_archi = unistr2_to_ascii_talloc(ctx, environment);
-       if (!long_archi) {
-               return WERR_NOMEM;
+       if (environment) {
+               long_archi = environment;
        }
 
-       if (!get_short_archi(long_archi))
+       short_archi = get_short_archi(long_archi);
+       if (!short_archi) {
                return WERR_INVALID_ENVIRONMENT;
+       }
 
-       if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
-               return WERR_NOMEM;
+       /* I think this should look like this - gd
+       info1->directory_name = talloc_asprintf(mem_ctx,
+               "C:\\WINNT\\System32\\spool\\PRTPROCS\\%s", short_archi);
+       */
+       info1->directory_name = talloc_strdup(mem_ctx,
+               "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
 
-       fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
+       if (!info1->directory_name) {
+               return WERR_NOMEM;
+       }
 
-       *needed += spoolss_size_printprocessordirectory_info_1(info);
+       *needed += ndr_size_spoolss_PrintProcessorDirectoryInfo1(info1, NULL, 0);
 
        if (*needed > offered) {
-               result = WERR_INSUFFICIENT_BUFFER;
-               goto out;
-       }
-
-       if (!rpcbuf_alloc_size(buffer, *needed)) {
-               result = WERR_INSUFFICIENT_BUFFER;
-               goto out;
+               return WERR_INSUFFICIENT_BUFFER;
        }
 
-       smb_io_printprocessordirectory_1("", buffer, info, 0);
-
-out:
-       SAFE_FREE(info);
-
-       return result;
+       return WERR_OK;
 }
 
-WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
+/****************************************************************
+ _spoolss_GetPrintProcessorDirectory
+****************************************************************/
+
+WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
+                                          struct spoolss_GetPrintProcessorDirectory *r)
 {
-       uint32 level = q_u->level;
-       RPC_BUFFER *buffer = NULL;
-       uint32 offered = q_u->offered;
-       uint32 *needed = &r_u->needed;
        WERROR result;
 
        /* that's an [in out] buffer */
 
-       if (!q_u->buffer && (offered!=0)) {
+       if (!r->in.buffer && (r->in.offered != 0)) {
                return WERR_INVALID_PARAM;
        }
 
-       rpcbuf_move(q_u->buffer, &r_u->buffer);
-       buffer = r_u->buffer;
+       if (r->in.offered > MAX_RPC_DATA_SIZE) {
+               return WERR_INVALID_PARAM;
+       }
 
-       DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
+       DEBUG(5,("_spoolss_GetPrintProcessorDirectory\n"));
 
-       *needed=0;
+       *r->out.needed = 0;
 
-       switch(level) {
+       switch (r->in.level) {
        case 1:
-               result = getprintprocessordirectory_level_1
-                 (&q_u->name, &q_u->environment, buffer, offered, needed);
+               result = getprintprocessordirectory_level_1(p->mem_ctx,
+                                                           r->in.server,
+                                                           r->in.environment,
+                                                           &r->out.info->info1,
+                                                           r->in.offered,
+                                                           r->out.needed);
+               if (!W_ERROR_IS_OK(result)) {
+                       TALLOC_FREE(r->out.info);
+               }
                break;
        default:
                result = WERR_UNKNOWN_LEVEL;
@@ -9783,58 +9779,154 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC
        return result;
 }
 
+/*******************************************************************
+ ********************************************************************/
+
+static bool push_monitorui_buf(TALLOC_CTX *mem_ctx, DATA_BLOB *buf,
+                              const char *dllname)
+{
+       enum ndr_err_code ndr_err;
+       struct spoolss_MonitorUi ui;
+
+       ui.dll_name = dllname;
+
+       ndr_err = ndr_push_struct_blob(buf, mem_ctx, NULL, &ui,
+                      (ndr_push_flags_fn_t)ndr_push_spoolss_MonitorUi);
+       if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
+               NDR_PRINT_DEBUG(spoolss_MonitorUi, &ui);
+       }
+       return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
+}
+
 /*******************************************************************
  Streams the monitor UI DLL name in UNICODE
 *******************************************************************/
 
-static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
-                                RPC_BUFFER *out, uint32 *needed )
+static WERROR xcvtcp_monitorui(TALLOC_CTX *mem_ctx,
+                              NT_USER_TOKEN *token, DATA_BLOB *in,
+                              DATA_BLOB *out, uint32_t *needed)
 {
        const char *dllname = "tcpmonui.dll";
 
        *needed = (strlen(dllname)+1) * 2;
 
-       if ( rpcbuf_get_size(out) < *needed ) {
+       if (out->length < *needed) {
                return WERR_INSUFFICIENT_BUFFER;
        }
 
-       if ( !make_monitorui_buf( out, dllname ) ) {
+       if (!push_monitorui_buf(mem_ctx, out, dllname)) {
                return WERR_NOMEM;
        }
 
        return WERR_OK;
 }
 
+/*******************************************************************
+ ********************************************************************/
+
+static bool pull_port_data_1(TALLOC_CTX *mem_ctx,
+                            struct spoolss_PortData1 *port1,
+                            const DATA_BLOB *buf)
+{
+       enum ndr_err_code ndr_err;
+       ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port1,
+                      (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData1);
+       if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
+               NDR_PRINT_DEBUG(spoolss_PortData1, port1);
+       }
+       return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
+}
+
+/*******************************************************************
+ ********************************************************************/
+
+static bool pull_port_data_2(TALLOC_CTX *mem_ctx,
+                            struct spoolss_PortData2 *port2,
+                            const DATA_BLOB *buf)
+{
+       enum ndr_err_code ndr_err;
+       ndr_err = ndr_pull_struct_blob(buf, mem_ctx, NULL, port2,
+                      (ndr_pull_flags_fn_t)ndr_pull_spoolss_PortData2);
+       if (NDR_ERR_CODE_IS_SUCCESS(ndr_err) && (DEBUGLEVEL >= 10)) {
+               NDR_PRINT_DEBUG(spoolss_PortData2, port2);
+       }
+       return NDR_ERR_CODE_IS_SUCCESS(ndr_err);
+}
+
 /*******************************************************************
  Create a new TCP/IP port
 *******************************************************************/
 
-static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
-                              RPC_BUFFER *out, uint32 *needed )
+static WERROR xcvtcp_addport(TALLOC_CTX *mem_ctx,
+                            NT_USER_TOKEN *token, DATA_BLOB *in,
+                            DATA_BLOB *out, uint32_t *needed)
 {
-       NT_PORT_DATA_1 port1;
-       TALLOC_CTX *ctx = talloc_tos();
+       struct spoolss_PortData1 port1;
+       struct spoolss_PortData2 port2;
        char *device_uri = NULL;
+       uint32_t version;
 
-       ZERO_STRUCT( port1 );
+       const char *portname;
+       const char *hostaddress;
+       const char *queue;
+       uint32_t port_number;
+       uint32_t protocol;
 
-       /* convert to our internal port data structure */
+       /* peek for spoolss_PortData version */
 
-       if ( !convert_port_data_1( &port1, in ) ) {
-               return WERR_NOMEM;
+       if (!in || (in->length < (128 + 4))) {
+               return WERR_GENERAL_FAILURE;
+       }
+
+       version = IVAL(in->data, 128);
+
+       switch (version) {
+               case 1:
+                       ZERO_STRUCT(port1);
+
+                       if (!pull_port_data_1(mem_ctx, &port1, in)) {
+                               return WERR_NOMEM;
+                       }
+
+                       portname        = port1.portname;
+                       hostaddress     = port1.hostaddress;
+                       queue           = port1.queue;
+                       protocol        = port1.protocol;
+                       port_number     = port1.port_number;
+
+                       break;
+               case 2:
+                       ZERO_STRUCT(port2);
+
+                       if (!pull_port_data_2(mem_ctx, &port2, in)) {
+                               return WERR_NOMEM;
+                       }
+
+                       portname        = port2.portname;
+                       hostaddress     = port2.hostaddress;
+                       queue           = port2.queue;
+                       protocol        = port2.protocol;
+                       port_number     = port2.port_number;
+
+                       break;
+               default:
+                       DEBUG(1,("xcvtcp_addport: "
+                               "unknown version of port_data: %d\n", version));
+                       return WERR_UNKNOWN_PORT;
        }
 
        /* create the device URI and call the add_port_hook() */
 
-       switch ( port1.protocol ) {
-       case PORT_PROTOCOL_DIRECT:
-               device_uri = talloc_asprintf(ctx,
-                               "socket://%s:%d/", port1.hostaddr, port1.port );
+       switch (protocol) {
+       case PROTOCOL_RAWTCP_TYPE:
+               device_uri = talloc_asprintf(mem_ctx,
+                               "socket://%s:%d/", hostaddress,
+                               port_number);
                break;
 
-       case PORT_PROTOCOL_LPR:
-               device_uri = talloc_asprintf(ctx,
-                       "lpr://%s/%s", port1.hostaddr, port1.queue );
+       case PROTOCOL_LPR_TYPE:
+               device_uri = talloc_asprintf(mem_ctx,
+                       "lpr://%s/%s", hostaddress, queue );
                break;
 
        default:
@@ -9845,7 +9937,7 @@ static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
                return WERR_NOMEM;
        }
 
-       return add_port_hook(ctx, token, port1.name, device_uri );
+       return add_port_hook(mem_ctx, token, portname, device_uri);
 }
 
 /*******************************************************************
@@ -9857,9 +9949,11 @@ struct xcv_api_table xcvtcp_cmds[] = {
        { NULL,         NULL }
 };
 
-static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
-                                      RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
-                                      uint32 *needed )
+static WERROR process_xcvtcp_command(TALLOC_CTX *mem_ctx,
+                                    NT_USER_TOKEN *token, const char *command,
+                                    DATA_BLOB *inbuf,
+                                    DATA_BLOB *outbuf,
+                                    uint32_t *needed )
 {
        int i;
 
@@ -9867,7 +9961,7 @@ static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
 
        for ( i=0; xcvtcp_cmds[i].name; i++ ) {
                if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
-                       return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
+                       return xcvtcp_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
        }
 
        return WERR_BADFUNC;
@@ -9877,18 +9971,19 @@ static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
 *******************************************************************/
 #if 0  /* don't support management using the "Local Port" monitor */
 
-static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
-                                  RPC_BUFFER *out, uint32 *needed )
+static WERROR xcvlocal_monitorui(TALLOC_CTX *mem_ctx,
+                                NT_USER_TOKEN *token, DATA_BLOB *in,
+                                DATA_BLOB *out, uint32_t *needed)
 {
        const char *dllname = "localui.dll";
 
        *needed = (strlen(dllname)+1) * 2;
 
-       if ( rpcbuf_get_size(out) < *needed ) {
+       if (out->length < *needed) {
                return WERR_INSUFFICIENT_BUFFER;
        }
 
-       if ( !make_monitorui_buf( out, dllname )) {
+       if (!push_monitorui_buf(mem_ctx, out, dllname)) {
                return WERR_NOMEM;
        }
 
@@ -9913,9 +10008,10 @@ struct xcv_api_table xcvlocal_cmds[] = {
 /*******************************************************************
 *******************************************************************/
 
-static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
-                                        RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
-                                       uint32 *needed )
+static WERROR process_xcvlocal_command(TALLOC_CTX *mem_ctx,
+                                      NT_USER_TOKEN *token, const char *command,
+                                      DATA_BLOB *inbuf, DATA_BLOB *outbuf,
+                                      uint32_t *needed)
 {
        int i;
 
@@ -9923,59 +10019,79 @@ static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *comman
 
        for ( i=0; xcvlocal_cmds[i].name; i++ ) {
                if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
-                       return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
+                       return xcvlocal_cmds[i].fn(mem_ctx, token, inbuf, outbuf, needed);
        }
        return WERR_BADFUNC;
 }
 
-/*******************************************************************
-*******************************************************************/
+/****************************************************************
+ _spoolss_XcvData
+****************************************************************/
 
-WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
+WERROR _spoolss_XcvData(pipes_struct *p,
+                       struct spoolss_XcvData *r)
 {
-       Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
-       fstring command;
+       Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
+       DATA_BLOB out_data;
+       WERROR werror;
 
        if (!Printer) {
-               DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
+               DEBUG(2,("_spoolss_XcvData: Invalid handle (%s:%u:%u).\n",
+                       OUR_HANDLE(r->in.handle)));
                return WERR_BADFID;
        }
 
        /* Has to be a handle to the TCP/IP port monitor */
 
        if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
-               DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
+               DEBUG(2,("_spoolss_XcvData: Call only valid for Port Monitors\n"));
                return WERR_BADFID;
        }
 
        /* requires administrative access to the server */
 
        if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
-               DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
+               DEBUG(2,("_spoolss_XcvData: denied by handle permissions.\n"));
                return WERR_ACCESS_DENIED;
        }
 
-       /* Get the command name.  There's numerous commands supported by the
-          TCPMON interface. */
-
-       rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
-               q_u->dataname.uni_str_len*2, 0);
-
        /* Allocate the outgoing buffer */
 
-       if (!rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx ))
-               return WERR_NOMEM;
+       if (r->in.out_data_size) {
+               out_data = data_blob_talloc_zero(p->mem_ctx, r->in.out_data_size);
+               if (out_data.data == NULL) {
+                       return WERR_NOMEM;
+               }
+       }
 
        switch ( Printer->printer_type ) {
        case SPLHND_PORTMON_TCP:
-               return process_xcvtcp_command( p->server_info->ptok, command,
-                       &q_u->indata, &r_u->outdata, &r_u->needed );
+               werror = process_xcvtcp_command(p->mem_ctx,
+                                               p->server_info->ptok,
+                                               r->in.function_name,
+                                               &r->in.in_data, &out_data,
+                                               r->out.needed);
+               break;
        case SPLHND_PORTMON_LOCAL:
-               return process_xcvlocal_command( p->server_info->ptok, command,
-                       &q_u->indata, &r_u->outdata, &r_u->needed );
+               werror = process_xcvlocal_command(p->mem_ctx,
+                                                 p->server_info->ptok,
+                                                 r->in.function_name,
+                                                 &r->in.in_data, &out_data,
+                                                 r->out.needed);
+               break;
+       default:
+               werror = WERR_INVALID_PRINT_MONITOR;
        }
 
-       return WERR_INVALID_PRINT_MONITOR;
+       if (!W_ERROR_IS_OK(werror)) {
+               return werror;
+       }
+
+       *r->out.status_code = 0;
+
+       memcpy(r->out.out_data, out_data.data, out_data.length);
+
+       return WERR_OK;
 }
 
 /****************************************************************
@@ -10004,28 +10120,6 @@ WERROR _spoolss_EnumPrinters(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_OpenPrinter
-****************************************************************/
-
-WERROR _spoolss_OpenPrinter(pipes_struct *p,
-                           struct spoolss_OpenPrinter *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
-/****************************************************************
- _spoolss_SetJob
-****************************************************************/
-
-WERROR _spoolss_SetJob(pipes_struct *p,
-                      struct spoolss_SetJob *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_GetJob
 ****************************************************************/
@@ -10059,17 +10153,6 @@ WERROR _spoolss_AddPrinter(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_SetPrinter
-****************************************************************/
-
-WERROR _spoolss_SetPrinter(pipes_struct *p,
-                          struct spoolss_SetPrinter *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_GetPrinter
 ****************************************************************/
@@ -10081,17 +10164,6 @@ WERROR _spoolss_GetPrinter(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_AddPrinterDriver
-****************************************************************/
-
-WERROR _spoolss_AddPrinterDriver(pipes_struct *p,
-                                struct spoolss_AddPrinterDriver *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_EnumPrinterDrivers
 ****************************************************************/
@@ -10114,17 +10186,6 @@ WERROR _spoolss_GetPrinterDriver(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_GetPrinterDriverDirectory
-****************************************************************/
-
-WERROR _spoolss_GetPrinterDriverDirectory(pipes_struct *p,
-                                         struct spoolss_GetPrinterDriverDirectory *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_EnumPrintProcessors
 ****************************************************************/
@@ -10136,28 +10197,6 @@ WERROR _spoolss_EnumPrintProcessors(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_GetPrintProcessorDirectory
-****************************************************************/
-
-WERROR _spoolss_GetPrintProcessorDirectory(pipes_struct *p,
-                                          struct spoolss_GetPrintProcessorDirectory *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
-/****************************************************************
- _spoolss_StartDocPrinter
-****************************************************************/
-
-WERROR _spoolss_StartDocPrinter(pipes_struct *p,
-                               struct spoolss_StartDocPrinter *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_ReadPrinter
 ****************************************************************/
@@ -10400,17 +10439,6 @@ WERROR _spoolss_EnumPrintProcDataTypes(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_ResetPrinter
-****************************************************************/
-
-WERROR _spoolss_ResetPrinter(pipes_struct *p,
-                            struct spoolss_ResetPrinter *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_GetPrinterDriver2
 ****************************************************************/
@@ -10544,22 +10572,22 @@ WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
 }
 
 /****************************************************************
- _spoolss_RouterRefreshPrinterChangeNotification
+ _spoolss_RouterReplyPrinterEx
 ****************************************************************/
 
-WERROR _spoolss_RouterRefreshPrinterChangeNotification(pipes_struct *p,
-                                                      struct spoolss_RouterRefreshPrinterChangeNotification *r)
+WERROR _spoolss_RouterReplyPrinterEx(pipes_struct *p,
+                                    struct spoolss_RouterReplyPrinterEx *r)
 {
        p->rng_fault_state = true;
        return WERR_NOT_SUPPORTED;
 }
 
 /****************************************************************
- _spoolss_RemoteFindNextPrinterChangeNotifyEx
+ _dcesrv_spoolss_RouterRefreshPrinterChangeNotify
 ****************************************************************/
 
-WERROR _spoolss_RemoteFindNextPrinterChangeNotifyEx(pipes_struct *p,
-                                                   struct spoolss_RemoteFindNextPrinterChangeNotifyEx *r)
+WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
+                                                struct spoolss_RouterRefreshPrinterChangeNotify *r)
 {
        p->rng_fault_state = true;
        return WERR_NOT_SUPPORTED;
@@ -10576,28 +10604,6 @@ WERROR _spoolss_44(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_OpenPrinterEx
-****************************************************************/
-
-WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
-                             struct spoolss_OpenPrinterEx *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
-/****************************************************************
- _spoolss_AddPrinterEx
-****************************************************************/
-
-WERROR _spoolss_AddPrinterEx(pipes_struct *p,
-                            struct spoolss_AddPrinterEx *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_47
 ****************************************************************/
@@ -10653,28 +10659,6 @@ WERROR _spoolss_4c(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_SetPrinterDataEx
-****************************************************************/
-
-WERROR _spoolss_SetPrinterDataEx(pipes_struct *p,
-                                struct spoolss_SetPrinterDataEx *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
-/****************************************************************
- _spoolss_GetPrinterDataEx
-****************************************************************/
-
-WERROR _spoolss_GetPrinterDataEx(pipes_struct *p,
-                                struct spoolss_GetPrinterDataEx *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_EnumPrinterDataEx
 ****************************************************************/
@@ -10741,28 +10725,6 @@ WERROR _spoolss_57(pipes_struct *p,
        return WERR_NOT_SUPPORTED;
 }
 
-/****************************************************************
- _spoolss_XcvData
-****************************************************************/
-
-WERROR _spoolss_XcvData(pipes_struct *p,
-                       struct spoolss_XcvData *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
-/****************************************************************
- _spoolss_AddPrinterDriverEx
-****************************************************************/
-
-WERROR _spoolss_AddPrinterDriverEx(pipes_struct *p,
-                                  struct spoolss_AddPrinterDriverEx *r)
-{
-       p->rng_fault_state = true;
-       return WERR_NOT_SUPPORTED;
-}
-
 /****************************************************************
  _spoolss_5a
 ****************************************************************/