r23779: Change from v2 or later to v3 or later.
[gd/samba/.git] / source3 / rpc_parse / parse_spoolss.c
index 503a9454fc0a5b73943b4f3b5977c99cc85341fe..a2291e020b80a9eb87667487f0f4e9a3eb2d084d 100644 (file)
@@ -9,7 +9,7 @@
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
+ *  the Free Software Foundation; either version 3 of the License, or
  *  (at your option) any later version.
  *  
  *  This program is distributed in the hope that it will be useful,
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_PARSE
 
-/*******************************************************************
-return the length of a UNISTR string.
-********************************************************************/  
-
-static uint32 str_len_uni(UNISTR *source)
-{
-       uint32 i=0;
-
-       if (!source->buffer)
-               return 0;
-
-       while (source->buffer[i])
-               i++;
-
-       return i;
-}
 
 /*******************************************************************
 This should be moved in a more generic lib.
@@ -246,6 +230,10 @@ static BOOL smb_io_notify_option_type_data(const char *desc, SPOOL_NOTIFY_OPTION
        if (type->count2 != type->count)
                DEBUG(4,("What a mess, count was %x now is %x !\n", type->count, type->count2));
 
+       if (type->count2 > MAX_NOTIFY_TYPE_FOR_NOW) {
+               return False;
+       }
+
        /* parse the option type data */
        for(i=0;i<type->count2;i++)
                if(!prs_uint16("fields",ps,depth,&type->fields[i]))
@@ -268,8 +256,8 @@ static BOOL smb_io_notify_option_type_ctr(const char *desc, SPOOL_NOTIFY_OPTION_
                return False;
 
        /* reading */
-       if (UNMARSHALLING(ps))
-               if((ctr->type=(SPOOL_NOTIFY_OPTION_TYPE *)prs_alloc_mem(ps,ctr->count*sizeof(SPOOL_NOTIFY_OPTION_TYPE))) == NULL)
+       if (UNMARSHALLING(ps) && ctr->count)
+               if((ctr->type=PRS_ALLOC_MEM(ps,SPOOL_NOTIFY_OPTION_TYPE,ctr->count)) == NULL)
                        return False;
                
        /* the option type struct */
@@ -421,20 +409,20 @@ BOOL smb_io_notify_info_data_strings(const char *desc,SPOOL_NOTIFY_INFO_DATA *da
 
        case NOTIFY_STRING:
 
-               if (UNMARSHALLING(ps)) {
-                       data->notify_data.data.string = 
-                               (uint16 *)prs_alloc_mem(ps, data->notify_data.data.length);
-
-                       if (!data->notify_data.data.string) 
-                               return False;
-               }
-
                if (MARSHALLING(ps))
                        data->notify_data.data.length /= 2;
 
                if(!prs_uint32("string length", ps, depth, &data->notify_data.data.length))
                        return False;
 
+               if (UNMARSHALLING(ps) && data->notify_data.data.length) {
+                       data->notify_data.data.string = PRS_ALLOC_MEM(ps, uint16,
+                                                               data->notify_data.data.length);
+
+                       if (!data->notify_data.data.string) 
+                               return False;
+               }
+
                if (!prs_uint16uni(True, "string", ps, depth, data->notify_data.data.string,
                                   data->notify_data.data.length))
                        return False;
@@ -446,9 +434,9 @@ BOOL smb_io_notify_info_data_strings(const char *desc,SPOOL_NOTIFY_INFO_DATA *da
 
        case NOTIFY_POINTER:
 
-               if (UNMARSHALLING(ps)) {
-                       data->notify_data.data.string = 
-                               (uint16 *)prs_alloc_mem(ps, data->notify_data.data.length);
+               if (UNMARSHALLING(ps) && data->notify_data.data.length) {
+                       data->notify_data.data.string = PRS_ALLOC_MEM(ps, uint16,
+                                                               data->notify_data.data.length);
 
                        if (!data->notify_data.data.string) 
                                return False;
@@ -506,9 +494,13 @@ BOOL smb_io_notify_info_data_strings(const char *desc,SPOOL_NOTIFY_INFO_DATA *da
 
                        /* Tallocate memory for string */
 
-                       data->notify_data.data.string = (uint16 *)prs_alloc_mem(ps, x * 2);
-                       if (!data->notify_data.data.string) 
-                               return False;
+                       if (x) {
+                               data->notify_data.data.string = PRS_ALLOC_MEM(ps, uint16, x * 2);
+                               if (!data->notify_data.data.string) 
+                                       return False;
+                       } else {
+                               data->notify_data.data.string = NULL;
+                       }
 
                        if(!prs_uint16uni(True,"string",ps,depth,data->notify_data.data.string,x))
                                return False;
@@ -566,23 +558,22 @@ static BOOL smb_io_notify_info(const char *desc, SPOOL_NOTIFY_INFO *info, prs_st
 /*******************************************************************
 ********************************************************************/  
 
-static BOOL spool_io_user_level_1(const char *desc, SPOOL_USER_1 *q_u, prs_struct *ps, int depth)
+BOOL spool_io_user_level_1( const char *desc, prs_struct *ps, int depth, SPOOL_USER_1 *q_u )
 {
        prs_debug(ps, depth, desc, "");
        depth++;
 
-       /* reading */
-       if (UNMARSHALLING(ps))
-               ZERO_STRUCTP(q_u);
-
        if (!prs_align(ps))
                return False;
+
        if (!prs_uint32("size", ps, depth, &q_u->size))
                return False;
-       if (!prs_uint32("client_name_ptr", ps, depth, &q_u->client_name_ptr))
+
+       if (!prs_io_unistr2_p("", ps, depth, &q_u->client_name))
                return False;
-       if (!prs_uint32("user_name_ptr", ps, depth, &q_u->user_name_ptr))
+       if (!prs_io_unistr2_p("", ps, depth, &q_u->user_name))
                return False;
+
        if (!prs_uint32("build", ps, depth, &q_u->build))
                return False;
        if (!prs_uint32("major", ps, depth, &q_u->major))
@@ -592,11 +583,12 @@ static BOOL spool_io_user_level_1(const char *desc, SPOOL_USER_1 *q_u, prs_struc
        if (!prs_uint32("processor", ps, depth, &q_u->processor))
                return False;
 
-       if (!smb_io_unistr2("", &q_u->client_name, q_u->client_name_ptr, ps, depth))
+       if (!prs_io_unistr2("", ps, depth, q_u->client_name))
                return False;
        if (!prs_align(ps))
                return False;
-       if (!smb_io_unistr2("", &q_u->user_name,   q_u->user_name_ptr,   ps, depth))
+
+       if (!prs_io_unistr2("", ps, depth, q_u->user_name))
                return False;
 
        return True;
@@ -616,21 +608,20 @@ static BOOL spool_io_user_level(const char *desc, SPOOL_USER_CTR *q_u, prs_struc
        if (!prs_align(ps))
                return False;
 
-       /* From looking at many captures in ethereal, it looks like
-          the level and ptr fields should be transposed.  -tpot */
-
        if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
-       if (!prs_uint32("ptr", ps, depth, &q_u->ptr))
-               return False;
        
-       switch (q_u->level) {   
-       case 1:
-               if (!spool_io_user_level_1("", &q_u->user1, ps, depth))
-                       return False;
-               break;
-       default:
-               return False;   
+       switch ( q_u->level ) 
+       {       
+               case 1:
+                       if ( !prs_pointer( "" , ps, depth, (void*)&q_u->user.user1, 
+                               sizeof(SPOOL_USER_1), (PRS_POINTER_CAST)spool_io_user_level_1 )) 
+                       {
+                               return False;
+                       }
+                       break;
+               default:
+                       return False;   
        }       
 
        return True;
@@ -648,6 +639,8 @@ BOOL spoolss_io_devmode(const char *desc, prs_struct *ps, int depth, DEVICEMODE
        int available_space;            /* size of the device mode left to parse */
                                        /* only important on unmarshalling       */
        int i = 0;
+       uint16 *unistr_buffer;
+       int j;
                                        
        struct optional_fields {
                fstring         name;
@@ -679,36 +672,25 @@ BOOL spoolss_io_devmode(const char *desc, prs_struct *ps, int depth, DEVICEMODE
        depth++;
 
        if (UNMARSHALLING(ps)) {
-               devmode->devicename.buffer = (uint16 *)prs_alloc_mem(ps, 32 * sizeof(uint16) );
+               devmode->devicename.buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
                if (devmode->devicename.buffer == NULL)
                        return False;
+               unistr_buffer = devmode->devicename.buffer;
        }
-
-       if (!prs_uint16uni(True,"devicename", ps, depth, devmode->devicename.buffer, MAXDEVICENAME))
+       else {
+               /* devicename is a static sized string but the buffer we set is not */
+               unistr_buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
+               memset( unistr_buffer, 0x0, MAXDEVICENAME );
+               for ( j=0; devmode->devicename.buffer[j]; j++ )
+                       unistr_buffer[j] = devmode->devicename.buffer[j];
+       }
+               
+       if (!prs_uint16uni(True,"devicename", ps, depth, unistr_buffer, MAXDEVICENAME))
                return False;
        
        if (!prs_uint16("specversion",      ps, depth, &devmode->specversion))
                return False;
                
-       /* Sanity Check - look for unknown specversions, but don't fail if we see one.
-          Let the size determine that */
-          
-       switch (devmode->specversion) {
-               /* list of observed spec version's */
-               case 0x0320:
-               case 0x0400:
-               case 0x0401:
-               case 0x040d:
-                       break;
-                       
-               default:
-                       DEBUG(0,("spoolss_io_devmode: Unknown specversion in devicemode [0x%x]\n",
-                               devmode->specversion));
-                       DEBUG(0,("spoolss_io_devmode: please report to samba-technical@samba.org!\n"));
-                       break;
-       }
-                       
-       
        if (!prs_uint16("driverversion",    ps, depth, &devmode->driverversion))
                return False;
        if (!prs_uint16("size",             ps, depth, &devmode->size))
@@ -745,12 +727,20 @@ BOOL spoolss_io_devmode(const char *desc, prs_struct *ps, int depth, DEVICEMODE
                return False;
 
        if (UNMARSHALLING(ps)) {
-               devmode->formname.buffer = (uint16 *)prs_alloc_mem(ps, 32 * sizeof(uint16) );
+               devmode->formname.buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
                if (devmode->formname.buffer == NULL)
                        return False;
+               unistr_buffer = devmode->formname.buffer;
        }
-
-       if (!prs_uint16uni(True, "formname",  ps, depth, devmode->formname.buffer, 32))
+       else {
+               /* devicename is a static sized string but the buffer we set is not */
+               unistr_buffer = PRS_ALLOC_MEM(ps, uint16, MAXDEVICENAME);
+               memset( unistr_buffer, 0x0, MAXDEVICENAME );
+               for ( j=0; devmode->formname.buffer[j]; j++ )
+                       unistr_buffer[j] = devmode->formname.buffer[j];
+       }
+       
+       if (!prs_uint16uni(True, "formname",  ps, depth, unistr_buffer, MAXDEVICENAME))
                return False;
        if (!prs_uint16("logpixels",        ps, depth, &devmode->logpixels))
                return False;
@@ -810,15 +800,15 @@ BOOL spoolss_io_devmode(const char *desc, prs_struct *ps, int depth, DEVICEMODE
 
        if (devmode->driverextra!=0) {
                if (UNMARSHALLING(ps)) {
-                       devmode->private=(uint8 *)prs_alloc_mem(ps, devmode->driverextra*sizeof(uint8));
-                       if(devmode->private == NULL)
+                       devmode->dev_private=PRS_ALLOC_MEM(ps, uint8, devmode->driverextra);
+                       if(devmode->dev_private == NULL)
                                return False;
-                       DEBUG(7,("spoolss_io_devmode: allocated memory [%d] for private\n",devmode->driverextra)); 
+                       DEBUG(7,("spoolss_io_devmode: allocated memory [%d] for dev_private\n",devmode->driverextra)); 
                }
                        
-               DEBUG(7,("spoolss_io_devmode: parsing [%d] bytes of private\n",devmode->driverextra));
-               if (!prs_uint8s(False, "private",  ps, depth,
-                               devmode->private, devmode->driverextra))
+               DEBUG(7,("spoolss_io_devmode: parsing [%d] bytes of dev_private\n",devmode->driverextra));
+               if (!prs_uint8s(False, "dev_private",  ps, depth,
+                               devmode->dev_private, devmode->driverextra))
                        return False;
        }
 
@@ -856,7 +846,7 @@ static BOOL spoolss_io_devmode_cont(const char *desc, DEVMODE_CTR *dm_c, prs_str
        /* so we have a DEVICEMODE to follow */         
        if (UNMARSHALLING(ps)) {
                DEBUG(9,("Allocating memory for spoolss_io_devmode\n"));
-               dm_c->devmode=(DEVICEMODE *)prs_alloc_mem(ps,sizeof(DEVICEMODE));
+               dm_c->devmode=PRS_ALLOC_MEM(ps,DEVICEMODE,1);
                if(dm_c->devmode == NULL)
                        return False;
        }
@@ -915,30 +905,44 @@ BOOL make_spoolss_q_open_printer_ex(SPOOL_Q_OPEN_PRINTER_EX *q_u,
                const fstring user_name)
 {
        DEBUG(5,("make_spoolss_q_open_printer_ex\n"));
-       q_u->printername_ptr = (printername!=NULL)?1:0;
-       init_unistr2(&q_u->printername, printername, UNI_STR_TERMINATE);
+
+       q_u->printername = TALLOC_P( get_talloc_ctx(), UNISTR2 );
+       if (!q_u->printername) {
+               return False;
+       }
+       init_unistr2(q_u->printername, printername, UNI_STR_TERMINATE);
 
        q_u->printer_default.datatype_ptr = 0;
-/*
-       q_u->printer_default.datatype_ptr = (datatype!=NULL)?1:0;
-       init_unistr2(&q_u->printer_default.datatype, datatype, UNI_FLAGS_NONE);
-*/
+
        q_u->printer_default.devmode_cont.size=0;
        q_u->printer_default.devmode_cont.devmode_ptr=0;
        q_u->printer_default.devmode_cont.devmode=NULL;
        q_u->printer_default.access_required=access_required;
-       q_u->user_switch=1;
-       q_u->user_ctr.level=1;
-       q_u->user_ctr.ptr=1;
-       q_u->user_ctr.user1.size=strlen(clientname)+strlen(user_name)+10;
-       q_u->user_ctr.user1.client_name_ptr = (clientname!=NULL)?1:0;
-       q_u->user_ctr.user1.user_name_ptr = (user_name!=NULL)?1:0;
-       q_u->user_ctr.user1.build=1381;
-       q_u->user_ctr.user1.major=2;
-       q_u->user_ctr.user1.minor=0;
-       q_u->user_ctr.user1.processor=0;
-       init_unistr2(&q_u->user_ctr.user1.client_name, clientname, UNI_STR_TERMINATE);
-       init_unistr2(&q_u->user_ctr.user1.user_name, user_name, UNI_STR_TERMINATE);
+
+       q_u->user_switch = 1;
+       
+       q_u->user_ctr.level                 = 1;
+       q_u->user_ctr.user.user1            = TALLOC_P( get_talloc_ctx(), SPOOL_USER_1 );
+       if (!q_u->user_ctr.user.user1) {
+               return False;
+       }
+       q_u->user_ctr.user.user1->size      = strlen(clientname) + strlen(user_name) + 10;
+       q_u->user_ctr.user.user1->build     = 1381;
+       q_u->user_ctr.user.user1->major     = 2;
+       q_u->user_ctr.user.user1->minor     = 0;
+       q_u->user_ctr.user.user1->processor = 0;
+
+       q_u->user_ctr.user.user1->client_name = TALLOC_P( get_talloc_ctx(), UNISTR2 );
+       if (!q_u->user_ctr.user.user1->client_name) {
+               return False;
+       }
+       q_u->user_ctr.user.user1->user_name   = TALLOC_P( get_talloc_ctx(), UNISTR2 );
+       if (!q_u->user_ctr.user.user1->user_name) {
+               return False;
+       }
+
+       init_unistr2(q_u->user_ctr.user.user1->client_name, clientname, UNI_STR_TERMINATE);
+       init_unistr2(q_u->user_ctr.user.user1->user_name, user_name, UNI_STR_TERMINATE);
        
        return True;
 }
@@ -947,23 +951,22 @@ BOOL make_spoolss_q_open_printer_ex(SPOOL_Q_OPEN_PRINTER_EX *q_u,
  * init a structure.
  ********************************************************************/
 
-BOOL make_spoolss_q_addprinterex(
-       TALLOC_CTX *mem_ctx,
-       SPOOL_Q_ADDPRINTEREX *q_u, 
-       const char *srv_name,
-       const char* clientname, 
-       const char* user_name,
-       uint32 level, 
-       PRINTER_INFO_CTR *ctr)
+BOOL make_spoolss_q_addprinterex( TALLOC_CTX *mem_ctx, SPOOL_Q_ADDPRINTEREX *q_u, 
+       const char *srv_name, const char* clientname, const char* user_name,
+       uint32 level, PRINTER_INFO_CTR *ctr)
 {
        DEBUG(5,("make_spoolss_q_addprinterex\n"));
        
-       if (!ctr) return False;
+       if (!ctr || !ctr->printers_2) 
+               return False;
 
        ZERO_STRUCTP(q_u);
 
-       q_u->server_name_ptr = (srv_name!=NULL)?1:0;
-       init_unistr2(&q_u->server_name, srv_name, UNI_FLAGS_NONE);
+       q_u->server_name = TALLOC_P( mem_ctx, UNISTR2 );
+       if (!q_u->server_name) {
+               return False;
+       }
+       init_unistr2(q_u->server_name, srv_name, UNI_FLAGS_NONE);
 
        q_u->level = level;
        
@@ -983,18 +986,29 @@ BOOL make_spoolss_q_addprinterex(
 
        q_u->user_switch=1;
 
-       q_u->user_ctr.level=1;
-       q_u->user_ctr.ptr=1;
-       q_u->user_ctr.user1.client_name_ptr = (clientname!=NULL)?1:0;
-       q_u->user_ctr.user1.user_name_ptr = (user_name!=NULL)?1:0;
-       q_u->user_ctr.user1.build=1381;
-       q_u->user_ctr.user1.major=2;
-       q_u->user_ctr.user1.minor=0;
-       q_u->user_ctr.user1.processor=0;
-       init_unistr2(&q_u->user_ctr.user1.client_name, clientname, UNI_STR_TERMINATE);
-       init_unistr2(&q_u->user_ctr.user1.user_name, user_name, UNI_STR_TERMINATE);
-       q_u->user_ctr.user1.size=q_u->user_ctr.user1.user_name.uni_str_len +
-                                q_u->user_ctr.user1.client_name.uni_str_len + 2;
+       q_u->user_ctr.level                 = 1;
+       q_u->user_ctr.user.user1            = TALLOC_P( get_talloc_ctx(), SPOOL_USER_1 );
+       if (!q_u->user_ctr.user.user1) {
+               return False;
+       }
+       q_u->user_ctr.user.user1->build     = 1381;
+       q_u->user_ctr.user.user1->major     = 2; 
+       q_u->user_ctr.user.user1->minor     = 0;
+       q_u->user_ctr.user.user1->processor = 0;
+
+       q_u->user_ctr.user.user1->client_name = TALLOC_P( mem_ctx, UNISTR2 );
+       if (!q_u->user_ctr.user.user1->client_name) {
+               return False;
+       }
+       q_u->user_ctr.user.user1->user_name   = TALLOC_P( mem_ctx, UNISTR2 );
+       if (!q_u->user_ctr.user.user1->user_name) {
+               return False;
+       }
+       init_unistr2(q_u->user_ctr.user.user1->client_name, clientname, UNI_STR_TERMINATE);
+       init_unistr2(q_u->user_ctr.user.user1->user_name, user_name, UNI_STR_TERMINATE);
+
+       q_u->user_ctr.user.user1->size = q_u->user_ctr.user.user1->user_name->uni_str_len +
+                                  q_u->user_ctr.user.user1->client_name->uni_str_len + 2;
        
        return True;
 }
@@ -1010,7 +1024,7 @@ BOOL make_spoolss_printer_info_2(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_2
        SPOOL_PRINTER_INFO_LEVEL_2 *inf;
 
        /* allocate the necessary memory */
-       if (!(inf=(SPOOL_PRINTER_INFO_LEVEL_2*)talloc(mem_ctx, sizeof(SPOOL_PRINTER_INFO_LEVEL_2)))) {
+       if (!(inf=TALLOC_P(mem_ctx, SPOOL_PRINTER_INFO_LEVEL_2))) {
                DEBUG(0,("make_spoolss_printer_info_2: Unable to allocate SPOOL_PRINTER_INFO_LEVEL_2 sruct!\n"));
                return False;
        }
@@ -1064,7 +1078,7 @@ BOOL make_spoolss_printer_info_3(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_3
        SPOOL_PRINTER_INFO_LEVEL_3 *inf;
 
        /* allocate the necessary memory */
-       if (!(inf=(SPOOL_PRINTER_INFO_LEVEL_3*)talloc(mem_ctx, sizeof(SPOOL_PRINTER_INFO_LEVEL_3)))) {
+       if (!(inf=TALLOC_P(mem_ctx, SPOOL_PRINTER_INFO_LEVEL_3))) {
                DEBUG(0,("make_spoolss_printer_info_3: Unable to allocate SPOOL_PRINTER_INFO_LEVEL_3 sruct!\n"));
                return False;
        }
@@ -1087,7 +1101,7 @@ BOOL make_spoolss_printer_info_7(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_7
        SPOOL_PRINTER_INFO_LEVEL_7 *inf;
 
        /* allocate the necessary memory */
-       if (!(inf=(SPOOL_PRINTER_INFO_LEVEL_7*)talloc(mem_ctx, sizeof(SPOOL_PRINTER_INFO_LEVEL_7)))) {
+       if (!(inf=TALLOC_P(mem_ctx, SPOOL_PRINTER_INFO_LEVEL_7))) {
                DEBUG(0,("make_spoolss_printer_info_7: Unable to allocate SPOOL_PRINTER_INFO_LEVEL_7 struct!\n"));
                return False;
        }
@@ -1118,9 +1132,9 @@ BOOL spoolss_io_q_open_printer(const char *desc, SPOOL_Q_OPEN_PRINTER *q_u, prs_
        if (!prs_align(ps))
                return False;
 
-       if (!prs_uint32("printername_ptr", ps, depth, &q_u->printername_ptr))
+       if (!prs_io_unistr2_p("ptr", ps, depth, &q_u->printername))
                return False;
-       if (!smb_io_unistr2("", &q_u->printername, q_u->printername_ptr, ps,depth))
+       if (!prs_io_unistr2("printername", ps, depth, q_u->printername))
                return False;
        
        if (!prs_align(ps))
@@ -1174,9 +1188,9 @@ BOOL spoolss_io_q_open_printer_ex(const char *desc, SPOOL_Q_OPEN_PRINTER_EX *q_u
        if (!prs_align(ps))
                return False;
 
-       if (!prs_uint32("printername_ptr", ps, depth, &q_u->printername_ptr))
+       if (!prs_io_unistr2_p("ptr", ps, depth, &q_u->printername))
                return False;
-       if (!smb_io_unistr2("", &q_u->printername, q_u->printername_ptr, ps,depth))
+       if (!prs_io_unistr2("printername", ps, depth, q_u->printername))
                return False;
        
        if (!prs_align(ps))
@@ -1225,7 +1239,8 @@ BOOL make_spoolss_q_deleteprinterdriverex( TALLOC_CTX *mem_ctx,
                                            SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, 
                                            const char *server,
                                            const char* arch, 
-                                           const char* driver )
+                                           const char* driver,
+                                           int version)
 {
        DEBUG(5,("make_spoolss_q_deleteprinterdriverex\n"));
  
@@ -1237,7 +1252,12 @@ BOOL make_spoolss_q_deleteprinterdriverex( TALLOC_CTX *mem_ctx,
        init_unistr2(&q_u->server, server, UNI_STR_TERMINATE);
        init_unistr2(&q_u->arch, arch, UNI_STR_TERMINATE);
        init_unistr2(&q_u->driver, driver, UNI_STR_TERMINATE);
+
+       if (version >= 0) { 
+               q_u->delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
+               q_u->version = version;
+       }
+
        return True;
 }
 
@@ -1438,7 +1458,7 @@ BOOL spoolss_io_r_getprinterdata(const char *desc, SPOOL_R_GETPRINTERDATA *r_u,
                return False;
        
        if (UNMARSHALLING(ps) && r_u->size) {
-               r_u->data = (unsigned char *)prs_alloc_mem(ps, r_u->size);
+               r_u->data = PRS_ALLOC_MEM(ps, unsigned char, r_u->size);
                if(!r_u->data)
                        return False;
        }
@@ -1879,7 +1899,7 @@ BOOL spoolss_io_q_writeprinter(const char *desc, SPOOL_Q_WRITEPRINTER *q_u, prs_
        if (q_u->buffer_size!=0)
        {
                if (UNMARSHALLING(ps))
-                       q_u->buffer=(uint8 *)prs_alloc_mem(ps,q_u->buffer_size*sizeof(uint8));
+                       q_u->buffer=PRS_ALLOC_MEM(ps, uint8, q_u->buffer_size);
                if(q_u->buffer == NULL)
                        return False;   
                if(!prs_uint8s(True, "buffer", ps, depth, q_u->buffer, q_u->buffer_size))
@@ -1946,7 +1966,7 @@ BOOL spoolss_io_q_rffpcnex(const char *desc, SPOOL_Q_RFFPCNEX *q_u, prs_struct *
        if (q_u->option_ptr!=0) {
        
                if (UNMARSHALLING(ps))
-                       if((q_u->option=(SPOOL_NOTIFY_OPTION *)prs_alloc_mem(ps,sizeof(SPOOL_NOTIFY_OPTION))) == NULL)
+                       if((q_u->option=PRS_ALLOC_MEM(ps,SPOOL_NOTIFY_OPTION,1)) == NULL)
                                return False;
        
                if(!smb_io_notify_option("notify option", q_u->option, ps, depth))
@@ -1997,7 +2017,7 @@ BOOL spoolss_io_q_rfnpcnex(const char *desc, SPOOL_Q_RFNPCNEX *q_u, prs_struct *
        if (q_u->option_ptr!=0) {
        
                if (UNMARSHALLING(ps))
-                       if((q_u->option=(SPOOL_NOTIFY_OPTION *)prs_alloc_mem(ps,sizeof(SPOOL_NOTIFY_OPTION))) == NULL)
+                       if((q_u->option=PRS_ALLOC_MEM(ps,SPOOL_NOTIFY_OPTION,1)) == NULL)
                                return False;
        
                if(!smb_io_notify_option("notify option", q_u->option, ps, depth))
@@ -2061,33 +2081,6 @@ static uint32 size_of_nttime(NTTIME *value)
        return (sizeof(*value));
 }
 
-/*******************************************************************
- * return the length of a UNICODE string in number of char, includes:
- * - the leading zero
- * - the relative pointer size
- ********************************************************************/
-
-static uint32 size_of_relative_string(UNISTR *string)
-{
-       uint32 size=0;
-       
-       size=str_len_uni(string);       /* the string length       */
-       size=size+1;                    /* add the trailing zero   */
-       size=size*2;                    /* convert in char         */
-       size=size+4;                    /* add the size of the ptr */   
-
-#if 0  /* JERRY */
-       /* 
-        * Do not include alignment as Win2k does not align relative
-        * strings within a buffer   --jerry 
-        */
-       /* Ensure size is 4 byte multiple (prs_align is being called...). */
-       /* size += ((4 - (size & 3)) & 3); */
-#endif 
-
-       return size;
-}
-
 /*******************************************************************
  * return the length of a uint32 (obvious, but the code is clean)
  ********************************************************************/
@@ -2112,278 +2105,11 @@ static uint32 size_of_systemtime(SYSTEMTIME *systime)
                return (sizeof(SYSTEMTIME) +4);
 }
 
-/*******************************************************************
- * write a UNICODE string and its relative pointer.
- * used by all the RPC structs passing a buffer
- *
- * As I'm a nice guy, I'm forcing myself to explain this code.
- * MS did a good job in the overall spoolss code except in some
- * functions where they are passing the API buffer directly in the
- * RPC request/reply. That's to maintain compatiility at the API level.
- * They could have done it the good way the first time.
- *
- * So what happen is: the strings are written at the buffer's end, 
- * in the reverse order of the original structure. Some pointers to
- * the strings are also in the buffer. Those are relative to the
- * buffer's start.
- *
- * If you don't understand or want to change that function,
- * first get in touch with me: jfm@samba.org
- *
- ********************************************************************/
-
-static BOOL smb_io_relstr(const char *desc, NEW_BUFFER *buffer, int depth, UNISTR *string)
-{
-       prs_struct *ps=&buffer->prs;
-       
-       if (MARSHALLING(ps)) {
-               uint32 struct_offset = prs_offset(ps);
-               uint32 relative_offset;
-               
-               buffer->string_at_end -= (size_of_relative_string(string) - 4);
-               if(!prs_set_offset(ps, buffer->string_at_end))
-                       return False;
-#if 0  /* JERRY */
-               /*
-                * Win2k does not align strings in a buffer
-                * Tested against WinNT 4.0 SP 6a & 2k SP2  --jerry
-                */
-               if (!prs_align(ps))
-                       return False;
-#endif
-               buffer->string_at_end = prs_offset(ps);
-               
-               /* write the string */
-               if (!smb_io_unistr(desc, string, ps, depth))
-                       return False;
-
-               if(!prs_set_offset(ps, struct_offset))
-                       return False;
-               
-               relative_offset=buffer->string_at_end - buffer->struct_start;
-               /* write its offset */
-               if (!prs_uint32("offset", ps, depth, &relative_offset))
-                       return False;
-       }
-       else {
-               uint32 old_offset;
-               
-               /* read the offset */
-               if (!prs_uint32("offset", ps, depth, &(buffer->string_at_end)))
-                       return False;
-
-               if (buffer->string_at_end == 0)
-                       return True;
-
-               old_offset = prs_offset(ps);
-               if(!prs_set_offset(ps, buffer->string_at_end+buffer->struct_start))
-                       return False;
-
-               /* read the string */
-               if (!smb_io_unistr(desc, string, ps, depth))
-                       return False;
-
-               if(!prs_set_offset(ps, old_offset))
-                       return False;
-       }
-       return True;
-}
-
-/*******************************************************************
- * write a array of UNICODE strings and its relative pointer.
- * used by 2 RPC structs
- ********************************************************************/
-
-static BOOL smb_io_relarraystr(const char *desc, NEW_BUFFER *buffer, int depth, uint16 **string)
-{
-       UNISTR chaine;
-       
-       prs_struct *ps=&buffer->prs;
-       
-       if (MARSHALLING(ps)) {
-               uint32 struct_offset = prs_offset(ps);
-               uint32 relative_offset;
-               uint16 *p;
-               uint16 *q;
-               uint16 zero=0;
-               p=*string;
-               q=*string;
-
-               /* first write the last 0 */
-               buffer->string_at_end -= 2;
-               if(!prs_set_offset(ps, buffer->string_at_end))
-                       return False;
-
-               if(!prs_uint16("leading zero", ps, depth, &zero))
-                       return False;
-
-               while (p && (*p!=0)) {  
-                       while (*q!=0)
-                               q++;
-
-                       /* Yes this should be malloc not talloc. Don't change. */
-
-                       chaine.buffer = malloc((q-p+1)*sizeof(uint16));
-                       if (chaine.buffer == NULL)
-                               return False;
-
-                       memcpy(chaine.buffer, p, (q-p+1)*sizeof(uint16));
-
-                       buffer->string_at_end -= (q-p+1)*sizeof(uint16);
-
-                       if(!prs_set_offset(ps, buffer->string_at_end)) {
-                               SAFE_FREE(chaine.buffer);
-                               return False;
-                       }
-
-                       /* write the string */
-                       if (!smb_io_unistr(desc, &chaine, ps, depth)) {
-                               SAFE_FREE(chaine.buffer);
-                               return False;
-                       }
-                       q++;
-                       p=q;
-
-                       SAFE_FREE(chaine.buffer);
-               }
-               
-               if(!prs_set_offset(ps, struct_offset))
-                       return False;
-               
-               relative_offset=buffer->string_at_end - buffer->struct_start;
-               /* write its offset */
-               if (!prs_uint32("offset", ps, depth, &relative_offset))
-                       return False;
-
-       } else {
-
-               /* UNMARSHALLING */
-
-               uint32 old_offset;
-               uint16 *chaine2=NULL;
-               int l_chaine=0;
-               int l_chaine2=0;
-               size_t realloc_size = 0;
-
-               *string=NULL;
-                               
-               /* read the offset */
-               if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
-                       return False;
-
-               old_offset = prs_offset(ps);
-               if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
-                       return False;
-       
-               do {
-                       if (!smb_io_unistr(desc, &chaine, ps, depth))
-                               return False;
-                       
-                       l_chaine=str_len_uni(&chaine);
-                       
-                       /* we're going to add two more bytes here in case this
-                          is the last string in the array and we need to add 
-                          an extra NULL for termination */
-                       if (l_chaine > 0)
-                       {
-                               uint16 *tc2;
-                       
-                               realloc_size = (l_chaine2+l_chaine+2)*sizeof(uint16);
-
-                               /* Yes this should be realloc - it's freed below. JRA */
-
-                               if((tc2=(uint16 *)Realloc(chaine2, realloc_size)) == NULL) {
-                                       SAFE_FREE(chaine2);
-                                       return False;
-                               }
-                               else chaine2 = tc2;
-                               memcpy(chaine2+l_chaine2, chaine.buffer, (l_chaine+1)*sizeof(uint16));
-                               l_chaine2+=l_chaine+1;
-                       }
-               
-               } while(l_chaine!=0);
-               
-               /* the end should be bould NULL terminated so add 
-                  the second one here */
-               if (chaine2)
-               {
-                       chaine2[l_chaine2] = '\0';
-                       *string=(uint16 *)talloc_memdup(prs_get_mem_context(ps),chaine2,realloc_size);
-                       SAFE_FREE(chaine2);
-               }
-
-               if(!prs_set_offset(ps, old_offset))
-                       return False;
-       }
-       return True;
-}
-
-/*******************************************************************
- Parse a DEVMODE structure and its relative pointer.
-********************************************************************/
-
-static BOOL smb_io_relsecdesc(const char *desc, NEW_BUFFER *buffer, int depth, SEC_DESC **secdesc)
-{
-       prs_struct *ps= &buffer->prs;
-
-       prs_debug(ps, depth, desc, "smb_io_relsecdesc");
-       depth++;
-
-       if (MARSHALLING(ps)) {
-               uint32 struct_offset = prs_offset(ps);
-               uint32 relative_offset;
-
-               if (! *secdesc) {
-                       relative_offset = 0;
-                       if (!prs_uint32("offset", ps, depth, &relative_offset))
-                               return False;
-                       return True;
-               }
-               
-               if (*secdesc != NULL) {
-                       buffer->string_at_end -= sec_desc_size(*secdesc);
-
-                       if(!prs_set_offset(ps, buffer->string_at_end))
-                               return False;
-                       /* write the secdesc */
-                       if (!sec_io_desc(desc, secdesc, ps, depth))
-                               return False;
-
-                       if(!prs_set_offset(ps, struct_offset))
-                               return False;
-               }
-
-               relative_offset=buffer->string_at_end - buffer->struct_start;
-               /* write its offset */
-
-               if (!prs_uint32("offset", ps, depth, &relative_offset))
-                       return False;
-       } else {
-               uint32 old_offset;
-               
-               /* read the offset */
-               if (!prs_uint32("offset", ps, depth, &buffer->string_at_end))
-                       return False;
-
-               old_offset = prs_offset(ps);
-               if(!prs_set_offset(ps, buffer->string_at_end + buffer->struct_start))
-                       return False;
-
-               /* read the sd */
-               if (!sec_io_desc(desc, secdesc, ps, depth))
-                       return False;
-
-               if(!prs_set_offset(ps, old_offset))
-                       return False;
-       }
-       return True;
-}
-
 /*******************************************************************
  Parse a DEVMODE structure and its relative pointer.
 ********************************************************************/
 
-static BOOL smb_io_reldevmode(const char *desc, NEW_BUFFER *buffer, int depth, DEVICEMODE **devmode)
+static BOOL smb_io_reldevmode(const char *desc, RPC_BUFFER *buffer, int depth, DEVICEMODE **devmode)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2436,7 +2162,7 @@ static BOOL smb_io_reldevmode(const char *desc, NEW_BUFFER *buffer, int depth, D
                        return False;
 
                /* read the string */
-               if((*devmode=(DEVICEMODE *)prs_alloc_mem(ps,sizeof(DEVICEMODE))) == NULL)
+               if((*devmode=PRS_ALLOC_MEM(ps,DEVICEMODE,1)) == NULL)
                        return False;
                if (!spoolss_io_devmode(desc, ps, depth, *devmode))
                        return False;
@@ -2451,7 +2177,7 @@ static BOOL smb_io_reldevmode(const char *desc, NEW_BUFFER *buffer, int depth, D
  Parse a PRINTER_INFO_0 structure.
 ********************************************************************/  
 
-BOOL smb_io_printer_info_0(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_0 *info, int depth)
+BOOL smb_io_printer_info_0(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_0 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2552,7 +2278,7 @@ BOOL smb_io_printer_info_0(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_0
  Parse a PRINTER_INFO_1 structure.
 ********************************************************************/  
 
-BOOL smb_io_printer_info_1(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_1 *info, int depth)
+BOOL smb_io_printer_info_1(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2577,7 +2303,7 @@ BOOL smb_io_printer_info_1(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_1
  Parse a PRINTER_INFO_2 structure.
 ********************************************************************/  
 
-BOOL smb_io_printer_info_2(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_2 *info, int depth)
+BOOL smb_io_printer_info_2(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_2 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
        uint32 dm_offset, sd_offset, current_offset;
@@ -2668,8 +2394,9 @@ BOOL smb_io_printer_info_2(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_2
  Parse a PRINTER_INFO_3 structure.
 ********************************************************************/  
 
-BOOL smb_io_printer_info_3(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_3 *info, int depth)
+BOOL smb_io_printer_info_3(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_3 *info, int depth)
 {
+       uint32 offset = 0;
        prs_struct *ps=&buffer->prs;
 
        prs_debug(ps, depth, desc, "smb_io_printer_info_3");
@@ -2677,8 +2404,41 @@ BOOL smb_io_printer_info_3(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_3
        
        buffer->struct_start=prs_offset(ps);
        
-       if (!prs_uint32("flags", ps, depth, &info->flags))
-               return False;
+       if (MARSHALLING(ps)) {
+               /* Ensure the SD is 8 byte aligned in the buffer. */
+               uint start = prs_offset(ps); /* Remember the start position. */
+               uint off_val = 0;
+
+               /* Write a dummy value. */
+               if (!prs_uint32("offset", ps, depth, &off_val))
+                       return False;
+
+               /* 8 byte align. */
+               if (!prs_align_uint64(ps))
+                       return False;
+
+               /* Remember where we must seek back to write the SD. */
+               offset = prs_offset(ps);
+
+               /* Calculate the real offset for the SD. */
+
+               off_val = offset - start;
+
+               /* Seek back to where we store the SD offset & store. */
+               prs_set_offset(ps, start);
+               if (!prs_uint32("offset", ps, depth, &off_val))
+                       return False;
+
+               /* Return to after the 8 byte align. */
+               prs_set_offset(ps, offset);
+
+       } else {
+               if (!prs_uint32("offset", ps, depth, &offset))
+                       return False;
+               /* Seek within the buffer. */
+               if (!prs_set_offset(ps, offset))
+                       return False;
+       }
        if (!sec_io_desc("sec_desc", &info->secdesc, ps, depth))
                return False;
 
@@ -2689,7 +2449,7 @@ BOOL smb_io_printer_info_3(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_3
  Parse a PRINTER_INFO_4 structure.
 ********************************************************************/  
 
-BOOL smb_io_printer_info_4(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_4 *info, int depth)
+BOOL smb_io_printer_info_4(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_4 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2711,7 +2471,7 @@ BOOL smb_io_printer_info_4(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_4
  Parse a PRINTER_INFO_5 structure.
 ********************************************************************/  
 
-BOOL smb_io_printer_info_5(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_5 *info, int depth)
+BOOL smb_io_printer_info_5(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_5 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2733,11 +2493,29 @@ BOOL smb_io_printer_info_5(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_5
        return True;
 }
 
+/*******************************************************************
+ Parse a PRINTER_INFO_6 structure.
+********************************************************************/  
+
+BOOL smb_io_printer_info_6(const char *desc, RPC_BUFFER *buffer,
+                          PRINTER_INFO_6 *info, int depth)
+{
+       prs_struct *ps=&buffer->prs;
+
+       prs_debug(ps, depth, desc, "smb_io_printer_info_6");
+       depth++;        
+       
+       if (!prs_uint32("status", ps, depth, &info->status))
+               return False;
+
+       return True;
+}
+
 /*******************************************************************
  Parse a PRINTER_INFO_7 structure.
 ********************************************************************/  
 
-BOOL smb_io_printer_info_7(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_7 *info, int depth)
+BOOL smb_io_printer_info_7(const char *desc, RPC_BUFFER *buffer, PRINTER_INFO_7 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2757,7 +2535,7 @@ BOOL smb_io_printer_info_7(const char *desc, NEW_BUFFER *buffer, PRINTER_INFO_7
  Parse a PORT_INFO_1 structure.
 ********************************************************************/  
 
-BOOL smb_io_port_info_1(const char *desc, NEW_BUFFER *buffer, PORT_INFO_1 *info, int depth)
+BOOL smb_io_port_info_1(const char *desc, RPC_BUFFER *buffer, PORT_INFO_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2776,7 +2554,7 @@ BOOL smb_io_port_info_1(const char *desc, NEW_BUFFER *buffer, PORT_INFO_1 *info,
  Parse a PORT_INFO_2 structure.
 ********************************************************************/  
 
-BOOL smb_io_port_info_2(const char *desc, NEW_BUFFER *buffer, PORT_INFO_2 *info, int depth)
+BOOL smb_io_port_info_2(const char *desc, RPC_BUFFER *buffer, PORT_INFO_2 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2803,7 +2581,7 @@ BOOL smb_io_port_info_2(const char *desc, NEW_BUFFER *buffer, PORT_INFO_2 *info,
  Parse a DRIVER_INFO_1 structure.
 ********************************************************************/
 
-BOOL smb_io_printer_driver_info_1(const char *desc, NEW_BUFFER *buffer, DRIVER_INFO_1 *info, int depth) 
+BOOL smb_io_printer_driver_info_1(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_1 *info, int depth) 
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2822,7 +2600,7 @@ BOOL smb_io_printer_driver_info_1(const char *desc, NEW_BUFFER *buffer, DRIVER_I
  Parse a DRIVER_INFO_2 structure.
 ********************************************************************/
 
-BOOL smb_io_printer_driver_info_2(const char *desc, NEW_BUFFER *buffer, DRIVER_INFO_2 *info, int depth) 
+BOOL smb_io_printer_driver_info_2(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_2 *info, int depth) 
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2851,7 +2629,7 @@ BOOL smb_io_printer_driver_info_2(const char *desc, NEW_BUFFER *buffer, DRIVER_I
  Parse a DRIVER_INFO_3 structure.
 ********************************************************************/
 
-BOOL smb_io_printer_driver_info_3(const char *desc, NEW_BUFFER *buffer, DRIVER_INFO_3 *info, int depth)
+BOOL smb_io_printer_driver_info_3(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_3 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2890,7 +2668,7 @@ BOOL smb_io_printer_driver_info_3(const char *desc, NEW_BUFFER *buffer, DRIVER_I
  Parse a DRIVER_INFO_6 structure.
 ********************************************************************/
 
-BOOL smb_io_printer_driver_info_6(const char *desc, NEW_BUFFER *buffer, DRIVER_INFO_6 *info, int depth)
+BOOL smb_io_printer_driver_info_6(const char *desc, RPC_BUFFER *buffer, DRIVER_INFO_6 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2925,9 +2703,7 @@ BOOL smb_io_printer_driver_info_6(const char *desc, NEW_BUFFER *buffer, DRIVER_I
        if (!smb_io_relarraystr("previousdrivernames", buffer, depth, &info->previousdrivernames))
                return False;
 
-       if (!prs_uint32("date.low", ps, depth, &info->driver_date.low))
-               return False;
-       if (!prs_uint32("date.high", ps, depth, &info->driver_date.high))
+       if (!prs_uint64("date", ps, depth, &info->driver_date))
                return False;
 
        if (!prs_uint32("padding", ps, depth, &info->padding))
@@ -2955,7 +2731,7 @@ BOOL smb_io_printer_driver_info_6(const char *desc, NEW_BUFFER *buffer, DRIVER_I
  Parse a JOB_INFO_1 structure.
 ********************************************************************/  
 
-BOOL smb_io_job_info_1(const char *desc, NEW_BUFFER *buffer, JOB_INFO_1 *info, int depth)
+BOOL smb_io_job_info_1(const char *desc, RPC_BUFFER *buffer, JOB_INFO_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -2998,7 +2774,7 @@ BOOL smb_io_job_info_1(const char *desc, NEW_BUFFER *buffer, JOB_INFO_1 *info, i
  Parse a JOB_INFO_2 structure.
 ********************************************************************/  
 
-BOOL smb_io_job_info_2(const char *desc, NEW_BUFFER *buffer, JOB_INFO_2 *info, int depth)
+BOOL smb_io_job_info_2(const char *desc, RPC_BUFFER *buffer, JOB_INFO_2 *info, int depth)
 {      
        uint32 pipo=0;
        prs_struct *ps=&buffer->prs;
@@ -3065,7 +2841,7 @@ BOOL smb_io_job_info_2(const char *desc, NEW_BUFFER *buffer, JOB_INFO_2 *info, i
 /*******************************************************************
 ********************************************************************/  
 
-BOOL smb_io_form_1(const char *desc, NEW_BUFFER *buffer, FORM_1 *info, int depth)
+BOOL smb_io_form_1(const char *desc, RPC_BUFFER *buffer, FORM_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
        
@@ -3083,136 +2859,26 @@ BOOL smb_io_form_1(const char *desc, NEW_BUFFER *buffer, FORM_1 *info, int depth
        if (!prs_uint32("width", ps, depth, &info->width))
                return False;
        if (!prs_uint32("length", ps, depth, &info->length))
-               return False;
-       if (!prs_uint32("left", ps, depth, &info->left))
-               return False;
-       if (!prs_uint32("top", ps, depth, &info->top))
-               return False;
-       if (!prs_uint32("right", ps, depth, &info->right))
-               return False;
-       if (!prs_uint32("bottom", ps, depth, &info->bottom))
-               return False;
-
-       return True;
-}
-
-/*******************************************************************
- Read/write a BUFFER struct.
-********************************************************************/  
-
-static BOOL spoolss_io_buffer(const char *desc, prs_struct *ps, int depth, NEW_BUFFER **pp_buffer)
-{
-       NEW_BUFFER *buffer = *pp_buffer;
-
-       prs_debug(ps, depth, desc, "spoolss_io_buffer");
-       depth++;
-       
-       if (UNMARSHALLING(ps))
-               buffer = *pp_buffer = (NEW_BUFFER *)prs_alloc_mem(ps, sizeof(NEW_BUFFER));
-
-       if (buffer == NULL)
-               return False;
-
-       if (!prs_uint32("ptr", ps, depth, &buffer->ptr))
-               return False;
-       
-       /* reading */
-       if (UNMARSHALLING(ps)) {
-               buffer->size=0;
-               buffer->string_at_end=0;
-               
-               if (buffer->ptr==0) {
-                       /*
-                        * JRA. I'm not sure if the data in here is in big-endian format if
-                        * the client is big-endian. Leave as default (little endian) for now.
-                        */
-
-                       if (!prs_init(&buffer->prs, 0, prs_get_mem_context(ps), UNMARSHALL))
-                               return False;
-                       return True;
-               }
-               
-               if (!prs_uint32("size", ps, depth, &buffer->size))
-                       return False;
-                                       
-               /*
-                * JRA. I'm not sure if the data in here is in big-endian format if
-                * the client is big-endian. Leave as default (little endian) for now.
-                */
-
-               if (!prs_init(&buffer->prs, buffer->size, prs_get_mem_context(ps), UNMARSHALL))
-                       return False;
-
-               if (!prs_append_some_prs_data(&buffer->prs, ps, prs_offset(ps), buffer->size))
-                       return False;
-
-               if (!prs_set_offset(&buffer->prs, 0))
-                       return False;
-
-               if (!prs_set_offset(ps, buffer->size+prs_offset(ps)))
-                       return False;
-
-               buffer->string_at_end=buffer->size;
-               
-               return True;
-       }
-       else {
-               BOOL ret = False;
-
-               /* writing */
-               if (buffer->ptr==0) {
-                       /* We have finished with the data in buffer->prs - free it. */
-                       prs_mem_free(&buffer->prs);
-                       return True;
-               }
-       
-               if (!prs_uint32("size", ps, depth, &buffer->size))
-                       goto out;
-
-               if (!prs_append_some_prs_data(ps, &buffer->prs, 0, buffer->size))
-                       goto out;
-
-               ret = True;
-       out:
-
-               /* We have finished with the data in buffer->prs - free it. */
-               prs_mem_free(&buffer->prs);
-
-               return ret;
-       }
-}
-
-/*******************************************************************
- move a BUFFER from the query to the reply.
- As the data pointers in NEW_BUFFER are malloc'ed, not talloc'ed,
- this is ok. This is an OPTIMIZATION and is not strictly neccessary.
- Clears the memory to zero also.
-********************************************************************/  
+               return False;
+       if (!prs_uint32("left", ps, depth, &info->left))
+               return False;
+       if (!prs_uint32("top", ps, depth, &info->top))
+               return False;
+       if (!prs_uint32("right", ps, depth, &info->right))
+               return False;
+       if (!prs_uint32("bottom", ps, depth, &info->bottom))
+               return False;
 
-void spoolss_move_buffer(NEW_BUFFER *src, NEW_BUFFER **dest)
-{
-       prs_switch_type(&src->prs, MARSHALL);
-       if(!prs_set_offset(&src->prs, 0))
-               return;
-       prs_force_dynamic(&src->prs);
-       prs_mem_clear(&src->prs);
-       *dest=src;
+       return True;
 }
 
-/*******************************************************************
- Get the size of a BUFFER struct.
-********************************************************************/  
 
-uint32 new_get_buffer_size(NEW_BUFFER *buffer)
-{
-       return (buffer->size);
-}
 
 /*******************************************************************
  Parse a DRIVER_DIRECTORY_1 structure.
 ********************************************************************/  
 
-BOOL smb_io_driverdir_1(const char *desc, NEW_BUFFER *buffer, DRIVER_DIRECTORY_1 *info, int depth)
+BOOL smb_io_driverdir_1(const char *desc, RPC_BUFFER *buffer, DRIVER_DIRECTORY_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -3231,7 +2897,7 @@ BOOL smb_io_driverdir_1(const char *desc, NEW_BUFFER *buffer, DRIVER_DIRECTORY_1
  Parse a PORT_INFO_1 structure.
 ********************************************************************/  
 
-BOOL smb_io_port_1(const char *desc, NEW_BUFFER *buffer, PORT_INFO_1 *info, int depth)
+BOOL smb_io_port_1(const char *desc, RPC_BUFFER *buffer, PORT_INFO_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -3250,7 +2916,7 @@ BOOL smb_io_port_1(const char *desc, NEW_BUFFER *buffer, PORT_INFO_1 *info, int
  Parse a PORT_INFO_2 structure.
 ********************************************************************/  
 
-BOOL smb_io_port_2(const char *desc, NEW_BUFFER *buffer, PORT_INFO_2 *info, int depth)
+BOOL smb_io_port_2(const char *desc, RPC_BUFFER *buffer, PORT_INFO_2 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -3276,7 +2942,7 @@ BOOL smb_io_port_2(const char *desc, NEW_BUFFER *buffer, PORT_INFO_2 *info, int
 /*******************************************************************
 ********************************************************************/  
 
-BOOL smb_io_printprocessor_info_1(const char *desc, NEW_BUFFER *buffer, PRINTPROCESSOR_1 *info, int depth)
+BOOL smb_io_printprocessor_info_1(const char *desc, RPC_BUFFER *buffer, PRINTPROCESSOR_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -3294,7 +2960,7 @@ BOOL smb_io_printprocessor_info_1(const char *desc, NEW_BUFFER *buffer, PRINTPRO
 /*******************************************************************
 ********************************************************************/  
 
-BOOL smb_io_printprocdatatype_info_1(const char *desc, NEW_BUFFER *buffer, PRINTPROCDATATYPE_1 *info, int depth)
+BOOL smb_io_printprocdatatype_info_1(const char *desc, RPC_BUFFER *buffer, PRINTPROCDATATYPE_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -3312,7 +2978,7 @@ BOOL smb_io_printprocdatatype_info_1(const char *desc, NEW_BUFFER *buffer, PRINT
 /*******************************************************************
 ********************************************************************/  
 
-BOOL smb_io_printmonitor_info_1(const char *desc, NEW_BUFFER *buffer, PRINTMONITOR_1 *info, int depth)
+BOOL smb_io_printmonitor_info_1(const char *desc, RPC_BUFFER *buffer, PRINTMONITOR_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -3330,7 +2996,7 @@ BOOL smb_io_printmonitor_info_1(const char *desc, NEW_BUFFER *buffer, PRINTMONIT
 /*******************************************************************
 ********************************************************************/  
 
-BOOL smb_io_printmonitor_info_2(const char *desc, NEW_BUFFER *buffer, PRINTMONITOR_2 *info, int depth)
+BOOL smb_io_printmonitor_info_2(const char *desc, RPC_BUFFER *buffer, PRINTMONITOR_2 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -3504,6 +3170,14 @@ uint32 spoolss_size_printer_info_5(PRINTER_INFO_5 *info)
        return size;
 }
 
+/*******************************************************************
+return the size required by a struct in the stream
+********************************************************************/
+
+uint32 spoolss_size_printer_info_6(PRINTER_INFO_6 *info)
+{
+       return sizeof(uint32);
+}
 
 /*******************************************************************
 return the size required by a struct in the stream
@@ -3511,9 +3185,8 @@ return the size required by a struct in the stream
 
 uint32 spoolss_size_printer_info_3(PRINTER_INFO_3 *info)
 {
-       /* The 4 is for the self relative pointer.. */
-       /* JRA !!!! TESTME - WHAT ABOUT prs_align.... !!! */
-       return 4 + (uint32)sec_desc_size( info->secdesc );
+       /* The 8 is for the self relative pointer - 8 byte aligned.. */
+       return 8 + (uint32)sec_desc_size( info->secdesc );
 }
 
 /*******************************************************************
@@ -3853,7 +3526,7 @@ BOOL make_spoolss_q_getprinterdriver2(SPOOL_Q_GETPRINTERDRIVER2 *q_u,
                               const POLICY_HND *hnd,
                               const fstring architecture,
                               uint32 level, uint32 clientmajor, uint32 clientminor,
-                              NEW_BUFFER *buffer, uint32 offered)
+                              RPC_BUFFER *buffer, uint32 offered)
 {      
        if (q_u == NULL)
                return False;
@@ -3897,7 +3570,7 @@ BOOL spoolss_io_q_getprinterdriver2(const char *desc, SPOOL_Q_GETPRINTERDRIVER2
        if(!prs_uint32("level", ps, depth, &q_u->level))
                return False;
                
-       if(!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
        if(!prs_align(ps))
@@ -3927,7 +3600,7 @@ BOOL spoolss_io_r_getprinterdriver2(const char *desc, SPOOL_R_GETPRINTERDRIVER2
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -3953,7 +3626,7 @@ BOOL make_spoolss_q_enumprinters(
        uint32 flags, 
        char *servername, 
        uint32 level, 
-       NEW_BUFFER *buffer, 
+       RPC_BUFFER *buffer, 
        uint32 offered
 )
 {
@@ -3975,7 +3648,7 @@ BOOL make_spoolss_q_enumprinters(
 
 BOOL make_spoolss_q_enumports(SPOOL_Q_ENUMPORTS *q_u, 
                                fstring servername, uint32 level, 
-                               NEW_BUFFER *buffer, uint32 offered)
+                               RPC_BUFFER *buffer, uint32 offered)
 {
        q_u->name_ptr = (servername != NULL) ? 1 : 0;
        init_buf_unistr2(&q_u->name, &q_u->name_ptr, servername);
@@ -4013,7 +3686,7 @@ BOOL spoolss_io_q_enumprinters(const char *desc, SPOOL_Q_ENUMPRINTERS *q_u, prs_
        if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
 
-       if (!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4036,7 +3709,7 @@ BOOL spoolss_io_r_enumprinters(const char *desc, SPOOL_R_ENUMPRINTERS *r_u, prs_
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4068,7 +3741,7 @@ BOOL spoolss_io_r_getprinter(const char *desc, SPOOL_R_GETPRINTER *r_u, prs_stru
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4101,7 +3774,7 @@ BOOL spoolss_io_q_getprinter(const char *desc, SPOOL_Q_GETPRINTER *q_u, prs_stru
        if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
 
-       if (!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4121,7 +3794,7 @@ BOOL make_spoolss_q_getprinter(
        SPOOL_Q_GETPRINTER *q_u, 
        const POLICY_HND *hnd, 
        uint32 level, 
-       NEW_BUFFER *buffer, 
+       RPC_BUFFER *buffer, 
        uint32 offered
 )
 {
@@ -4148,14 +3821,14 @@ BOOL make_spoolss_q_setprinter(TALLOC_CTX *mem_ctx, SPOOL_Q_SETPRINTER *q_u,
        SEC_DESC *secdesc;
        DEVICEMODE *devmode;
 
-       if (q_u == NULL)
+       if (!q_u || !info)
                return False;
        
        memcpy(&q_u->handle, hnd, sizeof(q_u->handle));
 
        q_u->level = level;
        q_u->info.level = level;
-       q_u->info.info_ptr = (info != NULL) ? 1 : 0;
+       q_u->info.info_ptr = 1; /* Info is != NULL, see above */
        switch (level) {
 
          /* There's no such thing as a setprinter level 1 */
@@ -4166,13 +3839,11 @@ BOOL make_spoolss_q_setprinter(TALLOC_CTX *mem_ctx, SPOOL_Q_SETPRINTER *q_u,
                
                make_spoolss_printer_info_2 (mem_ctx, &q_u->info.info_2, info->printers_2);
 #if 1  /* JERRY TEST */
-               q_u->secdesc_ctr = (SEC_DESC_BUF*)malloc(sizeof(SEC_DESC_BUF));
+               q_u->secdesc_ctr = SMB_MALLOC_P(SEC_DESC_BUF);
                if (!q_u->secdesc_ctr)
                        return False;
-               q_u->secdesc_ctr->ptr = (secdesc != NULL) ? 1: 0;
-               q_u->secdesc_ctr->max_len = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
-               q_u->secdesc_ctr->len = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
-               q_u->secdesc_ctr->sec = secdesc;
+               q_u->secdesc_ctr->sd = secdesc;
+               q_u->secdesc_ctr->sd_size = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
 
                q_u->devmode_ctr.devmode_ptr = (devmode != NULL) ? 1 : 0;
                q_u->devmode_ctr.size = (devmode != NULL) ? sizeof(DEVICEMODE) + (3*sizeof(uint32)) : 0;
@@ -4190,13 +3861,11 @@ BOOL make_spoolss_q_setprinter(TALLOC_CTX *mem_ctx, SPOOL_Q_SETPRINTER *q_u,
                
                make_spoolss_printer_info_3 (mem_ctx, &q_u->info.info_3, info->printers_3);
                
-               q_u->secdesc_ctr = (SEC_DESC_BUF*)malloc(sizeof(SEC_DESC_BUF));
+               q_u->secdesc_ctr = SMB_MALLOC_P(SEC_DESC_BUF);
                if (!q_u->secdesc_ctr)
                        return False;
-               q_u->secdesc_ctr->ptr = (secdesc != NULL) ? 1: 0;
-               q_u->secdesc_ctr->max_len = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
-               q_u->secdesc_ctr->len = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
-               q_u->secdesc_ctr->sec = secdesc;
+               q_u->secdesc_ctr->sd_size = (secdesc) ? sizeof(SEC_DESC) + (2*sizeof(uint32)) : 0;
+               q_u->secdesc_ctr->sd = secdesc;
 
                break;
        case 7:
@@ -4250,6 +3919,22 @@ BOOL spoolss_io_q_setprinter(const char *desc, SPOOL_Q_SETPRINTER *q_u, prs_stru
                return False;
        if(!prs_uint32("level", ps, depth, &q_u->level))
                return False;
+       
+       /* check for supported levels and structures we know about */
+               
+       switch ( q_u->level ) {
+               case 0:
+               case 2:
+               case 3:
+               case 7:
+                       /* supported levels */
+                       break;
+               default:
+                       DEBUG(0,("spoolss_io_q_setprinter: unsupported printer info level [%d]\n", 
+                               q_u->level));
+                       return True;
+       }
+                       
 
        if(!spool_io_printer_info_level("", &q_u->info, ps, depth))
                return False;
@@ -4269,7 +3954,16 @@ BOOL spoolss_io_q_setprinter(const char *desc, SPOOL_Q_SETPRINTER *q_u, prs_stru
                }
                case 3:
                {
-                       ptr_sec_desc = q_u->info.info_3->secdesc_ptr;
+                       /* FIXME ! Our parsing here is wrong I think,
+                        * but for a level3 it makes no sense for
+                        * ptr_sec_desc to be NULL. JRA. Based on
+                        * a Vista sniff from Martin Zielinski <mz@seh.de>.
+                        */
+                       if (UNMARSHALLING(ps)) {
+                               ptr_sec_desc = 1;
+                       } else {
+                               ptr_sec_desc = q_u->info.info_3->secdesc_ptr;
+                       }
                        break;
                }
        }
@@ -4286,8 +3980,8 @@ BOOL spoolss_io_q_setprinter(const char *desc, SPOOL_Q_SETPRINTER *q_u, prs_stru
                prs_debug(ps, depth, "", "sec_io_desc_buf");
                if (!prs_uint32("size", ps, depth + 1, &dummy))
                        return False;
-               if (!prs_uint32("ptr", ps, depth + 1, &dummy)) return
-                                                                      False;
+               if (!prs_uint32("ptr", ps, depth + 1, &dummy))
+                       return False;
        }
        
        if(!prs_uint32("command", ps, depth, &q_u->command))
@@ -4343,7 +4037,7 @@ BOOL spoolss_io_r_addjob(const char *desc, SPOOL_R_ADDJOB *r_u, prs_struct *ps,
        if(!prs_align(ps))
                return False;
        
-       if(!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if(!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if(!prs_align(ps))
@@ -4374,7 +4068,7 @@ BOOL spoolss_io_q_addjob(const char *desc, SPOOL_Q_ADDJOB *q_u, prs_struct *ps,
        if(!prs_uint32("level", ps, depth, &q_u->level))
                return False;
        
-       if(!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
        if(!prs_align(ps))
@@ -4397,7 +4091,7 @@ BOOL spoolss_io_r_enumjobs(const char *desc, SPOOL_R_ENUMJOBS *r_u, prs_struct *
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4422,7 +4116,7 @@ BOOL make_spoolss_q_enumjobs(SPOOL_Q_ENUMJOBS *q_u, const POLICY_HND *hnd,
                                uint32 firstjob,
                                uint32 numofjobs,
                                uint32 level,
-                               NEW_BUFFER *buffer,
+                               RPC_BUFFER *buffer,
                                uint32 offered)
 {
        if (q_u == NULL)
@@ -4459,7 +4153,7 @@ BOOL spoolss_io_q_enumjobs(const char *desc, SPOOL_Q_ENUMJOBS *q_u, prs_struct *
        if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
 
-       if (!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;   
 
        if(!prs_align(ps))
@@ -4563,7 +4257,7 @@ BOOL spoolss_io_r_enumprinterdrivers(const char *desc, SPOOL_R_ENUMPRINTERDRIVER
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4589,7 +4283,7 @@ BOOL make_spoolss_q_enumprinterdrivers(SPOOL_Q_ENUMPRINTERDRIVERS *q_u,
                                 const char *name,
                                 const char *environment,
                                 uint32 level,
-                                NEW_BUFFER *buffer, uint32 offered)
+                                RPC_BUFFER *buffer, uint32 offered)
 {
         init_buf_unistr2(&q_u->name, &q_u->name_ptr, name);
         init_buf_unistr2(&q_u->environment, &q_u->environment_ptr, environment);
@@ -4631,7 +4325,7 @@ BOOL spoolss_io_q_enumprinterdrivers(const char *desc, SPOOL_Q_ENUMPRINTERDRIVER
        if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4659,7 +4353,7 @@ BOOL spoolss_io_q_enumforms(const char *desc, SPOOL_Q_ENUMFORMS *q_u, prs_struct
        if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;   
        
-       if (!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4681,7 +4375,7 @@ BOOL spoolss_io_r_enumforms(const char *desc, SPOOL_R_ENUMFORMS *r_u, prs_struct
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4721,7 +4415,7 @@ BOOL spoolss_io_q_getform(const char *desc, SPOOL_Q_GETFORM *q_u, prs_struct *ps
        if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;   
        
-       if (!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4743,7 +4437,7 @@ BOOL spoolss_io_r_getform(const char *desc, SPOOL_R_GETFORM *r_u, prs_struct *ps
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4770,7 +4464,7 @@ BOOL spoolss_io_r_enumports(const char *desc, SPOOL_R_ENUMPORTS *r_u, prs_struct
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -4809,7 +4503,7 @@ BOOL spoolss_io_q_enumports(const char *desc, SPOOL_Q_ENUMPORTS *q_u, prs_struct
        if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -5005,7 +4699,7 @@ BOOL spool_io_printer_info_level(const char *desc, SPOOL_PRINTER_INFO_LEVEL *il,
                case 1:
                {
                        if (UNMARSHALLING(ps)) {
-                               if ((il->info_1=(SPOOL_PRINTER_INFO_LEVEL_1 *)prs_alloc_mem(ps,sizeof(SPOOL_PRINTER_INFO_LEVEL_1))) == NULL)
+                               if ((il->info_1=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_INFO_LEVEL_1,1)) == NULL)
                                        return False;
                        }
                        if (!spool_io_printer_info_level_1("", il->info_1, ps, depth))
@@ -5018,7 +4712,7 @@ BOOL spool_io_printer_info_level(const char *desc, SPOOL_PRINTER_INFO_LEVEL *il,
                 */     
                case 2:
                        if (UNMARSHALLING(ps)) {
-                               if ((il->info_2=(SPOOL_PRINTER_INFO_LEVEL_2 *)prs_alloc_mem(ps,sizeof(SPOOL_PRINTER_INFO_LEVEL_2))) == NULL)
+                               if ((il->info_2=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_INFO_LEVEL_2,1)) == NULL)
                                        return False;
                        }
                        if (!spool_io_printer_info_level_2("", il->info_2, ps, depth))
@@ -5028,7 +4722,7 @@ BOOL spool_io_printer_info_level(const char *desc, SPOOL_PRINTER_INFO_LEVEL *il,
                case 3:
                {
                        if (UNMARSHALLING(ps)) {
-                               if ((il->info_3=(SPOOL_PRINTER_INFO_LEVEL_3 *)prs_alloc_mem(ps,sizeof(SPOOL_PRINTER_INFO_LEVEL_3))) == NULL)
+                               if ((il->info_3=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_INFO_LEVEL_3,1)) == NULL)
                                        return False;
                        }
                        if (!spool_io_printer_info_level_3("", il->info_3, ps, depth))
@@ -5037,7 +4731,7 @@ BOOL spool_io_printer_info_level(const char *desc, SPOOL_PRINTER_INFO_LEVEL *il,
                }
                case 7:
                        if (UNMARSHALLING(ps))
-                               if ((il->info_7=(SPOOL_PRINTER_INFO_LEVEL_7 *)prs_alloc_mem(ps,sizeof(SPOOL_PRINTER_INFO_LEVEL_7))) == NULL)
+                               if ((il->info_7=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_INFO_LEVEL_7,1)) == NULL)
                                        return False;
                        if (!spool_io_printer_info_level_7("", il->info_7, ps, depth))
                                return False;
@@ -5059,9 +4753,10 @@ BOOL spoolss_io_q_addprinterex(const char *desc, SPOOL_Q_ADDPRINTEREX *q_u, prs_
 
        if(!prs_align(ps))
                return False;
-       if(!prs_uint32("", ps, depth, &q_u->server_name_ptr))
+
+       if (!prs_io_unistr2_p("ptr", ps, depth, &q_u->server_name))
                return False;
-       if(!smb_io_unistr2("", &q_u->server_name, q_u->server_name_ptr, ps, depth))
+       if (!prs_io_unistr2("servername", ps, depth, q_u->server_name))
                return False;
 
        if(!prs_align(ps))
@@ -5142,7 +4837,7 @@ BOOL spool_io_printer_driver_info_level_3(const char *desc, SPOOL_PRINTER_DRIVER
                
        /* reading */
        if (UNMARSHALLING(ps)) {
-               il=(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *)prs_alloc_mem(ps,sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3));
+               il=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_DRIVER_INFO_LEVEL_3,1);
                if(il == NULL)
                        return False;
                *q_u=il;
@@ -5220,7 +4915,7 @@ BOOL spool_io_printer_driver_info_level_6(const char *desc, SPOOL_PRINTER_DRIVER
                
        /* reading */
        if (UNMARSHALLING(ps)) {
-               il=(SPOOL_PRINTER_DRIVER_INFO_LEVEL_6 *)prs_alloc_mem(ps,sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL_6));
+               il=PRS_ALLOC_MEM(ps,SPOOL_PRINTER_DRIVER_INFO_LEVEL_6,1);
                if(il == NULL)
                        return False;
                *q_u=il;
@@ -5364,9 +5059,10 @@ BOOL spool_io_printer_driver_info_level_6(const char *desc, SPOOL_PRINTER_DRIVER
  dynamically allocate memory
  
 ********************************************************************/  
+
 static BOOL uniarray_2_dosarray(BUFFER5 *buf5, fstring **ar)
 {
-       fstring f, *tar;
+       fstring f;
        int n = 0;
        char *src;
 
@@ -5374,27 +5070,27 @@ static BOOL uniarray_2_dosarray(BUFFER5 *buf5, fstring **ar)
                return False;
 
        src = (char *)buf5->buffer;
-       *ar = NULL;
+       *ar = SMB_MALLOC_ARRAY(fstring, 1);
+       if (!*ar) {
+               return False;
+       }
 
        while (src < ((char *)buf5->buffer) + buf5->buf_len*2) {
                rpcstr_pull(f, src, sizeof(f)-1, -1, STR_TERMINATE);
                src = skip_unibuf(src, 2*buf5->buf_len - PTR_DIFF(src,buf5->buffer));
-               tar = (fstring *)Realloc(*ar, sizeof(fstring)*(n+2));
-               if (!tar)
+               *ar = SMB_REALLOC_ARRAY(*ar, fstring, n+2);
+               if (!*ar) {
                        return False;
-               else
-                       *ar = tar;
+               }
                fstrcpy((*ar)[n], f);
                n++;
        }
+
        fstrcpy((*ar)[n], "");
  
        return True;
 }
 
-
-
-
 /*******************************************************************
  read a UNICODE array with null terminated strings 
  and null terminated array 
@@ -5461,13 +5157,17 @@ BOOL make_spoolss_q_addprinterdriver(TALLOC_CTX *mem_ctx,
 {
        DEBUG(5,("make_spoolss_q_addprinterdriver\n"));
        
-       q_u->server_name_ptr = (srv_name!=NULL)?1:0;
+       if (!srv_name || !info) {
+               return False;
+       }
+
+       q_u->server_name_ptr = 1; /* srv_name is != NULL, see above */
        init_unistr2(&q_u->server_name, srv_name, UNI_STR_TERMINATE);
        
        q_u->level = level;
        
        q_u->info.level = level;
-       q_u->info.ptr = (info!=NULL)?1:0;
+       q_u->info.ptr = 1;      /* Info is != NULL, see above */
        switch (level)
        {
        /* info level 3 is supported by Windows 95/98, WinNT and Win2k */
@@ -5488,12 +5188,9 @@ BOOL make_spoolss_driver_info_3(TALLOC_CTX *mem_ctx,
                                DRIVER_INFO_3 *info3)
 {
        uint32          len = 0;
-       uint16          *ptr = info3->dependentfiles;
-       BOOL            done = False;
-       BOOL            null_char = False;
        SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *inf;
 
-       if (!(inf=(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3*)talloc_zero(mem_ctx, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3))))
+       if (!(inf=TALLOC_ZERO_P(mem_ctx, SPOOL_PRINTER_DRIVER_INFO_LEVEL_3)))
                return False;
        
        inf->cversion   = info3->version;
@@ -5515,31 +5212,35 @@ BOOL make_spoolss_driver_info_3(TALLOC_CTX *mem_ctx,
        init_unistr2_from_unistr(&inf->monitorname, &info3->monitorname);
        init_unistr2_from_unistr(&inf->defaultdatatype, &info3->defaultdatatype);
 
-       while (!done)
-       {
-               switch (*ptr)
-               {
-                       case 0:
-                               /* the null_char BOOL is used to help locate
-                                  two '\0's back to back */
-                               if (null_char)
-                                       done = True;
-                               else
-                                       null_char = True;
-                               break;
+       if (info3->dependentfiles) {
+               BOOL done = False;
+               BOOL null_char = False;
+               uint16 *ptr = info3->dependentfiles;
+
+               while (!done) {
+                       switch (*ptr) {
+                               case 0:
+                                       /* the null_char BOOL is used to help locate
+                                          two '\0's back to back */
+                                       if (null_char) {
+                                               done = True;
+                                       } else {
+                                               null_char = True;
+                                       }
+                                       break;
                                        
-                       default:
-                               null_char = False;
-                               ;;
-                               break;                          
+                               default:
+                                       null_char = False;
+                                       break;                          
+                       }
+                       len++;
+                       ptr++;
                }
-               len++;
-               ptr++;
        }
+
        inf->dependentfiles_ptr = (info3->dependentfiles != NULL) ? 1 : 0;
-       inf->dependentfilessize = len;
-       if(!make_spoolss_buffer5(mem_ctx, &inf->dependentfiles, len, info3->dependentfiles))
-       {
+       inf->dependentfilessize = (info3->dependentfiles != NULL) ? len : 0;
+       if(!make_spoolss_buffer5(mem_ctx, &inf->dependentfiles, len, info3->dependentfiles)) {
                SAFE_FREE(inf);
                return False;
        }
@@ -5552,14 +5253,22 @@ BOOL make_spoolss_driver_info_3(TALLOC_CTX *mem_ctx,
 /*******************************************************************
  make a BUFFER5 struct from a uint16*
  ******************************************************************/
+
 BOOL make_spoolss_buffer5(TALLOC_CTX *mem_ctx, BUFFER5 *buf5, uint32 len, uint16 *src)
 {
 
        buf5->buf_len = len;
-       if((buf5->buffer=(uint16*)talloc_memdup(mem_ctx, src, sizeof(uint16)*len)) == NULL)
-       {
-               DEBUG(0,("make_spoolss_buffer5: Unable to malloc memory for buffer!\n"));
-               return False;
+       if (src) {
+               if (len) {
+                       if((buf5->buffer=(uint16*)TALLOC_MEMDUP(mem_ctx, src, sizeof(uint16)*len)) == NULL) {
+                               DEBUG(0,("make_spoolss_buffer5: Unable to malloc memory for buffer!\n"));
+                               return False;
+                       }
+               } else {
+                       buf5->buffer = NULL;
+               }
+       } else {
+               buf5->buffer=NULL;
        }
        
        return True;
@@ -5666,7 +5375,7 @@ BOOL uni_2_asc_printer_driver_3(SPOOL_PRINTER_DRIVER_INFO_LEVEL_3 *uni,
        
        if (*asc==NULL)
        {
-               *asc=(NT_PRINTER_DRIVER_INFO_LEVEL_3 *)malloc(sizeof(NT_PRINTER_DRIVER_INFO_LEVEL_3));
+               *asc=SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_3);
                if(*asc == NULL)
                        return False;
                ZERO_STRUCTP(*asc);
@@ -5713,7 +5422,7 @@ BOOL uni_2_asc_printer_driver_6(SPOOL_PRINTER_DRIVER_INFO_LEVEL_6 *uni,
        
        if (*asc==NULL)
        {
-               *asc=(NT_PRINTER_DRIVER_INFO_LEVEL_6 *)malloc(sizeof(NT_PRINTER_DRIVER_INFO_LEVEL_6));
+               *asc=SMB_MALLOC_P(NT_PRINTER_DRIVER_INFO_LEVEL_6);
                if(*asc == NULL)
                        return False;
                ZERO_STRUCTP(*asc);
@@ -5755,32 +5464,10 @@ error:
 }
 
 BOOL uni_2_asc_printer_info_2(const SPOOL_PRINTER_INFO_LEVEL_2 *uni,
-                              NT_PRINTER_INFO_LEVEL_2  **asc)
+                              NT_PRINTER_INFO_LEVEL_2  *d)
 {
-       NT_PRINTER_INFO_LEVEL_2 *d;
-       time_t time_unix;
-       
        DEBUG(7,("Converting from UNICODE to ASCII\n"));
-       time_unix=time(NULL);
        
-       if (*asc==NULL) {
-               DEBUGADD(8,("allocating memory\n"));
-
-               *asc=(NT_PRINTER_INFO_LEVEL_2 *)malloc(sizeof(NT_PRINTER_INFO_LEVEL_2));
-               if(*asc == NULL)
-                       return False;
-               ZERO_STRUCTP(*asc);
-               
-               /* we allocate memory iff called from 
-                * addprinter(ex) so we can do one time stuff here.
-                */
-               (*asc)->setuptime=time_unix;
-
-       }       
-       DEBUGADD(8,("start converting\n"));
-
-       d=*asc;
-               
        d->attributes=uni->attributes;
        d->priority=uni->priority;
        d->default_priority=uni->default_priority;
@@ -5810,7 +5497,7 @@ BOOL uni_2_asc_printer_info_2(const SPOOL_PRINTER_INFO_LEVEL_2 *uni,
 
 BOOL make_spoolss_q_getprinterdriverdir(SPOOL_Q_GETPRINTERDRIVERDIR *q_u,
                                 fstring servername, fstring env_name, uint32 level,
-                                NEW_BUFFER *buffer, uint32 offered)
+                                RPC_BUFFER *buffer, uint32 offered)
 {
        init_buf_unistr2(&q_u->name, &q_u->name_ptr, servername);
        init_buf_unistr2(&q_u->environment, &q_u->environment_ptr, env_name);
@@ -5852,7 +5539,7 @@ BOOL spoolss_io_q_getprinterdriverdir(const char *desc, SPOOL_Q_GETPRINTERDRIVER
        if(!prs_uint32("level", ps, depth, &q_u->level))
                return False;
                
-       if(!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
                
        if(!prs_align(ps))
@@ -5876,7 +5563,7 @@ BOOL spoolss_io_r_getprinterdriverdir(const char *desc, SPOOL_R_GETPRINTERDRIVER
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -5902,7 +5589,7 @@ BOOL spoolss_io_r_enumprintprocessors(const char *desc, SPOOL_R_ENUMPRINTPROCESS
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -5950,7 +5637,7 @@ BOOL spoolss_io_q_enumprintprocessors(const char *desc, SPOOL_Q_ENUMPRINTPROCESS
        if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
                
-       if(!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -6024,7 +5711,7 @@ BOOL spoolss_io_r_enumprintprocdatatypes(const char *desc, SPOOL_R_ENUMPRINTPROC
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -6072,7 +5759,7 @@ BOOL spoolss_io_q_enumprintprocdatatypes(const char *desc, SPOOL_Q_ENUMPRINTPROC
        if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
                
-       if(!spoolss_io_buffer("buffer", ps, depth, &q_u->buffer))
+       if(!prs_rpcbuffer_p("buffer", ps, depth, &q_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -6107,7 +5794,7 @@ BOOL spoolss_io_q_enumprintmonitors(const char *desc, SPOOL_Q_ENUMPRINTMONITORS
        if (!prs_uint32("level", ps, depth, &q_u->level))
                return False;
                
-       if(!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -6130,7 +5817,7 @@ BOOL spoolss_io_r_enumprintmonitors(const char *desc, SPOOL_R_ENUMPRINTMONITORS
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -6162,7 +5849,7 @@ BOOL spoolss_io_r_enumprinterdata(const char *desc, SPOOL_R_ENUMPRINTERDATA *r_u
                return False;
 
        if (UNMARSHALLING(ps) && r_u->valuesize) {
-               r_u->value = (uint16 *)prs_alloc_mem(ps, r_u->valuesize * 2);
+               r_u->value = PRS_ALLOC_MEM(ps, uint16, r_u->valuesize);
                if (!r_u->value) {
                        DEBUG(0, ("spoolss_io_r_enumprinterdata: out of memory for printerdata value\n"));
                        return False;
@@ -6185,7 +5872,7 @@ BOOL spoolss_io_r_enumprinterdata(const char *desc, SPOOL_R_ENUMPRINTERDATA *r_u
                return False;
 
        if (UNMARSHALLING(ps) && r_u->datasize) {
-               r_u->data = (uint8 *)prs_alloc_mem(ps, r_u->datasize);
+               r_u->data = PRS_ALLOC_MEM(ps, uint8, r_u->datasize);
                if (!r_u->data) {
                        DEBUG(0, ("spoolss_io_r_enumprinterdata: out of memory for printerdata data\n"));
                        return False;
@@ -6318,14 +6005,14 @@ BOOL spoolss_io_q_setprinterdata(const char *desc, SPOOL_Q_SETPRINTERDATA *q_u,
                case REG_BINARY:
                case REG_DWORD:
                case REG_MULTI_SZ:
-            if (q_u->max_len) {
-                if (UNMARSHALLING(ps))
-                               q_u->data=(uint8 *)prs_alloc_mem(ps, q_u->max_len * sizeof(uint8));
-                       if(q_u->data == NULL)
-                               return False;
-                       if(!prs_uint8s(False,"data", ps, depth, q_u->data, q_u->max_len))
-                               return False;
-            }
+                       if (q_u->max_len) {
+                               if (UNMARSHALLING(ps))
+                                       q_u->data=PRS_ALLOC_MEM(ps, uint8, q_u->max_len);
+                               if(q_u->data == NULL)
+                                       return False;
+                               if(!prs_uint8s(False,"data", ps, depth, q_u->data, q_u->max_len))
+                                       return False;
+                       }
                        if(!prs_align(ps))
                                return False;
                        break;
@@ -6573,7 +6260,7 @@ BOOL spoolss_io_r_getjob(const char *desc, SPOOL_R_GETJOB *r_u, prs_struct *ps,
        if (!prs_align(ps))
                return False;
                
-       if (!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if (!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
 
        if (!prs_align(ps))
@@ -6607,7 +6294,7 @@ BOOL spoolss_io_q_getjob(const char *desc, SPOOL_Q_GETJOB *q_u, prs_struct *ps,
        if(!prs_uint32("level", ps, depth, &q_u->level))
                return False;
        
-       if(!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
 
        if(!prs_align(ps))
@@ -6622,7 +6309,7 @@ BOOL spoolss_io_q_getjob(const char *desc, SPOOL_Q_GETJOB *q_u, prs_struct *ps,
 void free_devmode(DEVICEMODE *devmode)
 {
        if (devmode!=NULL) {
-               SAFE_FREE(devmode->private);
+               SAFE_FREE(devmode->dev_private);
                SAFE_FREE(devmode);
        }
 }
@@ -6656,6 +6343,11 @@ void free_printer_info_5(PRINTER_INFO_5 *printer)
        SAFE_FREE(printer);
 }
 
+void free_printer_info_6(PRINTER_INFO_6 *printer)
+{
+       SAFE_FREE(printer);
+}
+
 void free_printer_info_7(PRINTER_INFO_7 *printer)
 {
        SAFE_FREE(printer);
@@ -6784,7 +6476,7 @@ BOOL spoolss_io_q_routerreplyprinter (const char *desc, SPOOL_Q_ROUTERREPLYPRINT
        if (!prs_uint32("change_id", ps, depth, &q_u->change_id))
                return False;
 
-       if (!prs_uint8s(False, "private",  ps, depth, q_u->unknown2, 5))
+       if (!prs_uint8s(False, "dev_private",  ps, depth, q_u->unknown2, 5))
                return False;
 
        return True;
@@ -6879,7 +6571,7 @@ static BOOL copy_spool_notify_info_data(SPOOL_NOTIFY_INFO_DATA *dst,
                if (src->size != POINTER) 
                        continue;
                len = src->notify_data.data.length;
-               s = malloc(sizeof(uint16)*len);
+               s = SMB_MALLOC_ARRAY(uint16, len);
                if (s == NULL) {
                        DEBUG(0,("copy_spool_notify_info_data: malloc() failed!\n"));
                        return False;
@@ -6908,7 +6600,7 @@ static BOOL copy_spool_notify_info(SPOOL_NOTIFY_INFO *dst, SPOOL_NOTIFY_INFO *sr
        
        if (dst->count) 
        {
-               dst->data = malloc(dst->count * sizeof(SPOOL_NOTIFY_INFO_DATA));
+               dst->data = SMB_MALLOC_ARRAY(SPOOL_NOTIFY_INFO_DATA, dst->count);
                
                DEBUG(10,("copy_spool_notify_info: allocating space for [%d] PRINTER_NOTIFY_INFO_DATA entries\n",
                        dst->count));
@@ -7078,7 +6770,7 @@ BOOL spoolss_io_r_getprinterdataex(const char *desc, SPOOL_R_GETPRINTERDATAEX *r
                return False;
        
        if (UNMARSHALLING(ps) && r_u->size) {
-               r_u->data = (unsigned char *)prs_alloc_mem(ps, r_u->size);
+               r_u->data = PRS_ALLOC_MEM(ps, unsigned char, r_u->size);
                if(!r_u->data)
                        return False;
        }
@@ -7136,7 +6828,7 @@ BOOL spoolss_io_q_setprinterdataex(const char *desc, SPOOL_Q_SETPRINTERDATAEX *q
                case 0x7:
                        if (q_u->max_len) {
                                if (UNMARSHALLING(ps))
-                                       q_u->data=(uint8 *)prs_alloc_mem(ps, q_u->max_len * sizeof(uint8));
+                                       q_u->data=PRS_ALLOC_MEM(ps, uint8, q_u->max_len);
                                if(q_u->data == NULL)
                                        return False;
                                if(!prs_uint8s(False,"data", ps, depth, q_u->data, q_u->max_len))
@@ -7330,10 +7022,10 @@ static BOOL spoolss_io_printer_enum_values_ctr(const char *desc, prs_struct *ps,
                data_offset,
                current_offset;
        const uint32 basic_unit = 20; /* size of static portion of enum_values */
-       
+
        prs_debug(ps, depth, desc, "spoolss_io_printer_enum_values_ctr");
        depth++;        
-       
+
        /* 
         * offset data begins at 20 bytes per structure * size_of_array.
         * Don't forget the uint32 at the beginning 
@@ -7343,18 +7035,36 @@ static BOOL spoolss_io_printer_enum_values_ctr(const char *desc, prs_struct *ps,
        
        /* first loop to write basic enum_value information */
        
-       if (UNMARSHALLING(ps)) {
-               ctr->values = (PRINTER_ENUM_VALUES *)prs_alloc_mem(
-                       ps, ctr->size_of_array * sizeof(PRINTER_ENUM_VALUES));
+       if (UNMARSHALLING(ps) && ctr->size_of_array) {
+               ctr->values = PRS_ALLOC_MEM(ps, PRINTER_ENUM_VALUES, ctr->size_of_array);
                if (!ctr->values)
                        return False;
        }
 
        for (i=0; i<ctr->size_of_array; i++) {
+               uint32 base_offset, return_offset;
+
+               base_offset = prs_offset(ps);
+
                valuename_offset = current_offset;
                if (!prs_uint32("valuename_offset", ps, depth, &valuename_offset))
                        return False;
 
+               /* Read or write the value. */
+
+               return_offset = prs_offset(ps);
+
+               if (!prs_set_offset(ps, base_offset + valuename_offset)) {
+                       return False;
+               }
+
+               if (!prs_unistr("valuename", ps, depth, &ctr->values[i].valuename))
+                       return False;
+
+               /* And go back. */
+               if (!prs_set_offset(ps, return_offset))
+                       return False;
+
                if (!prs_uint32("value_len", ps, depth, &ctr->values[i].value_len))
                        return False;
        
@@ -7369,36 +7079,47 @@ static BOOL spoolss_io_printer_enum_values_ctr(const char *desc, prs_struct *ps,
                if (!prs_uint32("data_len", ps, depth, &ctr->values[i].data_len))
                        return False;
                        
-               current_offset  = data_offset + ctr->values[i].data_len - basic_unit;
-               /* account for 2 byte alignment */
-               current_offset += (current_offset % 2);
-       }
+               /* Read or write the data. */
 
-       /* 
-        * loop #2 for writing the dynamically size objects; pay 
-        * attention to 2-byte alignment here....
-        */
-       
-       for (i=0; i<ctr->size_of_array; i++) {
-       
-               if (!prs_unistr("valuename", ps, depth, &ctr->values[i].valuename))
+               return_offset = prs_offset(ps);
+
+               if (!prs_set_offset(ps, base_offset + data_offset)) {
                        return False;
-               
+               }
+
                if ( ctr->values[i].data_len ) {
                        if ( UNMARSHALLING(ps) ) {
-                               ctr->values[i].data = (uint8 *)prs_alloc_mem(
-                                       ps, ctr->values[i].data_len);
+                               ctr->values[i].data = PRS_ALLOC_MEM(ps, uint8, ctr->values[i].data_len);
                                if (!ctr->values[i].data)
                                        return False;
                        }
                        if (!prs_uint8s(False, "data", ps, depth, ctr->values[i].data, ctr->values[i].data_len))
                                return False;
                }
-                       
-               if ( !prs_align_uint16(ps) )
+
+               current_offset  = data_offset + ctr->values[i].data_len - basic_unit;
+               /* account for 2 byte alignment */
+               current_offset += (current_offset % 2);
+
+               /* Remember how far we got. */
+               data_offset = prs_offset(ps);
+
+               /* And go back. */
+               if (!prs_set_offset(ps, return_offset))
                        return False;
+
        }
 
+       /* Go to the last data offset we got to. */
+
+       if (!prs_set_offset(ps, data_offset))
+               return False;
+
+       /* And ensure we're 2 byte aligned. */
+
+       if ( !prs_align_uint16(ps) )
+               return False;
+
        return True;    
 }
 
@@ -7460,7 +7181,7 @@ BOOL spoolss_io_r_enumprinterdataex(const char *desc, SPOOL_R_ENUMPRINTERDATAEX
        [in] unistr2 *name,
        [in] unistr2 *environment,
        [in] uint32 level,
-       [in,out] NEW_BUFFER buffer,
+       [in,out] RPC_BUFFER buffer,
        [in] uint32 offered,
        [out] uint32 needed,
        [out] uint32 returned
@@ -7468,7 +7189,7 @@ BOOL spoolss_io_r_enumprinterdataex(const char *desc, SPOOL_R_ENUMPRINTERDATAEX
 
 */
 
-BOOL make_spoolss_q_getprintprocessordirectory(SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, const char *name, char *environment, int level, NEW_BUFFER *buffer, uint32 offered)
+BOOL make_spoolss_q_getprintprocessordirectory(SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, const char *name, char *environment, int level, RPC_BUFFER *buffer, uint32 offered)
 {
        DEBUG(5,("make_spoolss_q_getprintprocessordirectory\n"));
 
@@ -7519,7 +7240,7 @@ BOOL spoolss_io_q_getprintprocessordirectory(const char *desc, SPOOL_Q_GETPRINTP
        if(!prs_uint32("level",   ps, depth, &q_u->level))
                return False;
 
-       if(!spoolss_io_buffer("", ps, depth, &q_u->buffer))
+       if(!prs_rpcbuffer_p("", ps, depth, &q_u->buffer))
                return False;
        
        if(!prs_align(ps))
@@ -7543,7 +7264,7 @@ BOOL spoolss_io_r_getprintprocessordirectory(const char *desc, SPOOL_R_GETPRINTP
        if(!prs_align(ps))
                return False;
 
-       if(!spoolss_io_buffer("", ps, depth, &r_u->buffer))
+       if(!prs_rpcbuffer_p("", ps, depth, &r_u->buffer))
                return False;
        
        if(!prs_align(ps))
@@ -7558,7 +7279,7 @@ BOOL spoolss_io_r_getprintprocessordirectory(const char *desc, SPOOL_R_GETPRINTP
        return True;
 }
 
-BOOL smb_io_printprocessordirectory_1(const char *desc, NEW_BUFFER *buffer, PRINTPROCESSOR_DIRECTORY_1 *info, int depth)
+BOOL smb_io_printprocessordirectory_1(const char *desc, RPC_BUFFER *buffer, PRINTPROCESSOR_DIRECTORY_1 *info, int depth)
 {
        prs_struct *ps=&buffer->prs;
 
@@ -7622,7 +7343,7 @@ BOOL make_spoolss_q_deleteform(SPOOL_Q_DELETEFORM *q_u, POLICY_HND *handle,
 
 BOOL make_spoolss_q_getform(SPOOL_Q_GETFORM *q_u, POLICY_HND *handle, 
                             const char *formname, uint32 level, 
-                           NEW_BUFFER *buffer, uint32 offered)
+                           RPC_BUFFER *buffer, uint32 offered)
 {
         memcpy(&q_u->handle, handle, sizeof(POLICY_HND));
         q_u->level = level;
@@ -7638,7 +7359,7 @@ BOOL make_spoolss_q_getform(SPOOL_Q_GETFORM *q_u, POLICY_HND *handle,
  ********************************************************************/
 
 BOOL make_spoolss_q_enumforms(SPOOL_Q_ENUMFORMS *q_u, POLICY_HND *handle, 
-                             uint32 level, NEW_BUFFER *buffer,
+                             uint32 level, RPC_BUFFER *buffer,
                              uint32 offered)
 {
         memcpy(&q_u->handle, handle, sizeof(POLICY_HND));
@@ -7673,7 +7394,7 @@ BOOL make_spoolss_q_setjob(SPOOL_Q_SETJOB *q_u, POLICY_HND *handle,
  ********************************************************************/
 
 BOOL make_spoolss_q_getjob(SPOOL_Q_GETJOB *q_u, POLICY_HND *handle, 
-                          uint32 jobid, uint32 level, NEW_BUFFER *buffer,
+                          uint32 jobid, uint32 level, RPC_BUFFER *buffer,
                           uint32 offered)
 {
         memcpy(&q_u->handle, handle, sizeof(POLICY_HND));
@@ -7829,3 +7550,174 @@ BOOL make_spoolss_q_rffpcnex(SPOOL_Q_RFFPCNEX *q_u, POLICY_HND *handle,
 
        return True;
 }
+
+
+/*******************************************************************
+ ********************************************************************/  
+
+BOOL spoolss_io_q_xcvdataport(const char *desc, SPOOL_Q_XCVDATAPORT *q_u, prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "spoolss_io_q_xcvdataport");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;   
+
+       if(!smb_io_pol_hnd("printer handle", &q_u->handle, ps, depth))
+               return False;
+               
+       if(!smb_io_unistr2("", &q_u->dataname, True, ps, depth))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if(!prs_rpcbuffer("", ps, depth, &q_u->indata))
+               return False;
+               
+       if (!prs_align(ps))
+               return False;
+
+       if (!prs_uint32("indata_len", ps, depth, &q_u->indata_len))
+               return False;
+       if (!prs_uint32("offered", ps, depth, &q_u->offered))
+               return False;
+       if (!prs_uint32("unknown", ps, depth, &q_u->unknown))
+               return False;
+       
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/  
+
+BOOL spoolss_io_r_xcvdataport(const char *desc, SPOOL_R_XCVDATAPORT *r_u, prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "spoolss_io_r_xcvdataport");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+       if(!prs_rpcbuffer("", ps, depth, &r_u->outdata))
+               return False;
+               
+       if (!prs_align(ps))
+               return False;
+
+       if (!prs_uint32("needed", ps, depth, &r_u->needed))
+               return False;
+       if (!prs_uint32("unknown", ps, depth, &r_u->unknown))
+               return False;
+
+       if(!prs_werror("status", ps, depth, &r_u->status))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/  
+
+BOOL make_monitorui_buf( RPC_BUFFER *buf, const char *dllname )
+{
+       UNISTR string;
+       
+       if ( !buf )
+               return False;
+
+       init_unistr( &string, dllname );
+
+       if ( !prs_unistr( "ui_dll", &buf->prs, 0, &string ) )
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/  
+#define PORT_DATA_1_PAD    540
+
+static BOOL smb_io_port_data_1( const char *desc, RPC_BUFFER *buf, int depth, SPOOL_PORT_DATA_1 *p1 )
+{
+       prs_struct *ps = &buf->prs;
+       uint8 padding[PORT_DATA_1_PAD];
+
+       prs_debug(ps, depth, desc, "smb_io_port_data_1");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;   
+
+       if( !prs_uint16s(True, "portname", ps, depth, p1->portname, MAX_PORTNAME))
+               return False;
+
+       if (!prs_uint32("version", ps, depth, &p1->version))
+               return False;
+       if (!prs_uint32("protocol", ps, depth, &p1->protocol))
+               return False;
+       if (!prs_uint32("size", ps, depth, &p1->size))
+               return False;
+       if (!prs_uint32("reserved", ps, depth, &p1->reserved))
+               return False;
+
+       if( !prs_uint16s(True, "hostaddress", ps, depth, p1->hostaddress, MAX_NETWORK_NAME))
+               return False;
+       if( !prs_uint16s(True, "snmpcommunity", ps, depth, p1->snmpcommunity, MAX_SNMP_COMM_NAME))
+               return False;
+
+       if (!prs_uint32("dblspool", ps, depth, &p1->dblspool))
+               return False;
+               
+       if( !prs_uint16s(True, "queue", ps, depth, p1->queue, MAX_QUEUE_NAME))
+               return False;
+       if( !prs_uint16s(True, "ipaddress", ps, depth, p1->ipaddress, MAX_IPADDR_STRING))
+               return False;
+
+       if( !prs_uint8s(False, "", ps, depth, padding, PORT_DATA_1_PAD))
+               return False;
+               
+       if (!prs_uint32("port", ps, depth, &p1->port))
+               return False;
+       if (!prs_uint32("snmpenabled", ps, depth, &p1->snmpenabled))
+               return False;
+       if (!prs_uint32("snmpdevindex", ps, depth, &p1->snmpdevindex))
+               return False;
+               
+       return True;
+}
+
+/*******************************************************************
+ ********************************************************************/  
+
+BOOL convert_port_data_1( NT_PORT_DATA_1 *port1, RPC_BUFFER *buf ) 
+{
+       SPOOL_PORT_DATA_1 spdata_1;
+       
+       ZERO_STRUCT( spdata_1 );
+       
+       if ( !smb_io_port_data_1( "port_data_1", buf, 0, &spdata_1 ) )
+               return False;
+               
+       rpcstr_pull(port1->name, spdata_1.portname, sizeof(port1->name), -1, 0);
+       rpcstr_pull(port1->queue, spdata_1.queue, sizeof(port1->queue), -1, 0);
+       rpcstr_pull(port1->hostaddr, spdata_1.hostaddress, sizeof(port1->hostaddr), -1, 0);
+       
+       port1->port = spdata_1.port;
+       
+       switch ( spdata_1.protocol ) {
+       case 1:
+               port1->protocol = PORT_PROTOCOL_DIRECT;
+               break;
+       case 2:
+               port1->protocol = PORT_PROTOCOL_LPR;
+               break;
+       default:
+               DEBUG(3,("convert_port_data_1: unknown protocol [%d]!\n", 
+                       spdata_1.protocol));
+               return False;
+       }
+
+       return True;
+}
+