s3-spoolss: use rpccli_spoolss_ClosePrinter.
[vlendec/samba-autobuild/.git] / source3 / rpcclient / cmd_spoolss.c
index b2fa802e9a38796d3f664c619e12c3811efc1169..057fc251230e56ab3a9821925c529671a27b6f83 100644 (file)
@@ -2,14 +2,14 @@
    Unix SMB/CIFS implementation.
    RPC pipe client
 
    Unix SMB/CIFS implementation.
    RPC pipe client
 
-   Copyright (C) Gerald Carter                     2001
+   Copyright (C) Gerald Carter                2001-2005
    Copyright (C) Tim Potter                        2000
    Copyright (C) Andrew Tridgell              1992-1999
    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
  
    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
    Copyright (C) Tim Potter                        2000
    Copyright (C) Andrew Tridgell              1992-1999
    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
  
    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,
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -18,8 +18,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 */
 
 #include "includes.h"
@@ -31,13 +30,23 @@ struct table_node {
        int     version;
 };
  
        int     version;
 };
  
+/* The version int is used by getdrivers.  Note that
+   all architecture strings that support mutliple
+   versions must be grouped together since enumdrivers
+   uses this property to prevent issuing multiple 
+   enumdriver calls for the same arch */
+
+
 static const struct table_node archi_table[]= {
 
        {"Windows 4.0",          "WIN40",       0 },
        {"Windows NT x86",       "W32X86",      2 },
 static const struct table_node archi_table[]= {
 
        {"Windows 4.0",          "WIN40",       0 },
        {"Windows NT x86",       "W32X86",      2 },
+       {"Windows NT x86",       "W32X86",      3 },
        {"Windows NT R4000",     "W32MIPS",     2 },
        {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
        {"Windows NT PowerPC",   "W32PPC",      2 },
        {"Windows NT R4000",     "W32MIPS",     2 },
        {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
        {"Windows NT PowerPC",   "W32PPC",      2 },
+       {"Windows IA64",         "IA64",        3 },
+       {"Windows x64",          "x64",         3 },
        {NULL,                   "",            -1 }
 };
 
        {NULL,                   "",            -1 }
 };
 
@@ -51,9 +60,10 @@ static const struct table_node archi_table[]= {
  **/
 
 /****************************************************************************
  **/
 
 /****************************************************************************
-function to do the mapping between the long architecture name and
-the short one.
+ function to do the mapping between the long architecture name and
+ the short one.
 ****************************************************************************/
 ****************************************************************************/
+
 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
 {
         int i=-1;
 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
 {
         int i=-1;
@@ -79,23 +89,10 @@ static const char *cmd_spoolss_get_short_archi(const char *long_archi)
        return archi_table[i].short_archi;
 }
 
        return archi_table[i].short_archi;
 }
 
-#if 0
-/**********************************************************************
- * dummy function  -- placeholder
-  */
-static WERROR cmd_spoolss_not_implemented(struct cli_state *cli, 
-                                            TALLOC_CTX *mem_ctx,
-                                            int argc, const char **argv)
-{
-       printf ("(*) This command is not currently implemented.\n");
-       return WERR_OK;
-}
-#endif
+/****************************************************************************
+****************************************************************************/
 
 
-/***********************************************************************
- * Get printer information
- */
-static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli, 
+static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli, 
                                             TALLOC_CTX *mem_ctx,
                                             int argc, const char **argv)
 {
                                             TALLOC_CTX *mem_ctx,
                                             int argc, const char **argv)
 {
@@ -114,18 +111,18 @@ static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli,
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
-       fstrcpy(user, cli->user_name);
+       fstrcpy(user, cli->auth->user_name);
        fstrcpy(printername, argv[1]);
 
        /* Open the printer handle */
 
        fstrcpy(printername, argv[1]);
 
        /* Open the printer handle */
 
-       werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", PRINTER_ALL_ACCESS, 
                                             servername, user, &hnd);
 
        if (W_ERROR_IS_OK(werror)) {
                printf("Printer %s opened successfully\n", printername);
                                             "", PRINTER_ALL_ACCESS, 
                                             servername, user, &hnd);
 
        if (W_ERROR_IS_OK(werror)) {
                printf("Printer %s opened successfully\n", printername);
-               werror = cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
 
                if (!W_ERROR_IS_OK(werror)) {
                        printf("Error closing printer handle! (%s)\n", 
 
                if (!W_ERROR_IS_OK(werror)) {
                        printf("Error closing printer handle! (%s)\n", 
@@ -138,8 +135,8 @@ static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli,
 
 
 /****************************************************************************
 
 
 /****************************************************************************
-printer info level 0 display function
 ****************************************************************************/
 ****************************************************************************/
+
 static void display_print_info_0(PRINTER_INFO_0 *i0)
 {
        fstring name = "";
 static void display_print_info_0(PRINTER_INFO_0 *i0)
 {
        fstring name = "";
@@ -196,8 +193,8 @@ static void display_print_info_0(PRINTER_INFO_0 *i0)
 }
 
 /****************************************************************************
 }
 
 /****************************************************************************
-printer info level 1 display function
 ****************************************************************************/
 ****************************************************************************/
+
 static void display_print_info_1(PRINTER_INFO_1 *i1)
 {
        fstring desc = "";
 static void display_print_info_1(PRINTER_INFO_1 *i1)
 {
        fstring desc = "";
@@ -219,8 +216,8 @@ static void display_print_info_1(PRINTER_INFO_1 *i1)
 }
 
 /****************************************************************************
 }
 
 /****************************************************************************
-printer info level 2 display function
 ****************************************************************************/
 ****************************************************************************/
+
 static void display_print_info_2(PRINTER_INFO_2 *i2)
 {
        fstring servername = "";
 static void display_print_info_2(PRINTER_INFO_2 *i2)
 {
        fstring servername = "";
@@ -236,25 +233,15 @@ static void display_print_info_2(PRINTER_INFO_2 *i2)
        fstring parameters = "";
        
        rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
        fstring parameters = "";
        
        rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
-
        rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
        rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
-
        rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
        rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
-
        rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
        rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
-
        rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
        rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
-
        rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
        rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
-
        rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
        rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
-
        rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
        rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
-
        rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
        rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
-
        rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
        rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
-
        rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
 
        printf("\tservername:[%s]\n", servername);
        rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
 
        printf("\tservername:[%s]\n", servername);
@@ -284,27 +271,38 @@ static void display_print_info_2(PRINTER_INFO_2 *i2)
 }
 
 /****************************************************************************
 }
 
 /****************************************************************************
-printer info level 3 display function
 ****************************************************************************/
 ****************************************************************************/
+
 static void display_print_info_3(PRINTER_INFO_3 *i3)
 {
 static void display_print_info_3(PRINTER_INFO_3 *i3)
 {
-       printf("\tflags:[0x%x]\n", i3->flags);
-
        display_sec_desc(i3->secdesc);
 
        printf("\n");
 }
 
        display_sec_desc(i3->secdesc);
 
        printf("\n");
 }
 
-/* Enumerate printers */
+/****************************************************************************
+****************************************************************************/
 
 
-static WERROR cmd_spoolss_enum_printers(struct cli_state *cli, 
+static void display_print_info_7(PRINTER_INFO_7 *i7)
+{
+       fstring guid = "";
+       rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
+       printf("\tguid:[%s]\n", guid);
+       printf("\taction:[0x%x]\n", i7->action);
+}
+
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli, 
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv)
 {
        WERROR                  result;
        uint32                  info_level = 1;
        PRINTER_INFO_CTR        ctr;
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv)
 {
        WERROR                  result;
        uint32                  info_level = 1;
        PRINTER_INFO_CTR        ctr;
-       uint32                  i = 0, num_printers, needed;
+       uint32                  i = 0, num_printers;
        fstring name;
 
        if (argc > 3) 
        fstring name;
 
        if (argc > 3) 
@@ -313,7 +311,7 @@ static WERROR cmd_spoolss_enum_printers(struct cli_state *cli,
                return WERR_OK;
        }
 
                return WERR_OK;
        }
 
-       if (argc == 2)
+       if (argc >= 2)
                info_level = atoi(argv[1]);
 
        if (argc == 3)
                info_level = atoi(argv[1]);
 
        if (argc == 3)
@@ -323,20 +321,11 @@ static WERROR cmd_spoolss_enum_printers(struct cli_state *cli,
                strupper_m(name);
        }
 
                strupper_m(name);
        }
 
-       /* Enumerate printers  -- Should we enumerate types other 
-          than PRINTER_ENUM_LOCAL?  Maybe accept as a parameter?  --jerry */
-
        ZERO_STRUCT(ctr);
 
        ZERO_STRUCT(ctr);
 
-       result = cli_spoolss_enum_printers(
-               cli, mem_ctx, 0, &needed, name, PRINTER_ENUM_LOCAL, 
+       result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL, 
                info_level, &num_printers, &ctr);
 
                info_level, &num_printers, &ctr);
 
-       if (W_ERROR_V(result) == ERRinsufficientbuffer)
-               result = cli_spoolss_enum_printers(
-                       cli, mem_ctx, needed, NULL, name, PRINTER_ENUM_LOCAL, 
-                       info_level, &num_printers, &ctr);
-
        if (W_ERROR_IS_OK(result)) {
 
                if (!num_printers) {
        if (W_ERROR_IS_OK(result)) {
 
                if (!num_printers) {
@@ -370,8 +359,8 @@ static WERROR cmd_spoolss_enum_printers(struct cli_state *cli,
 }
 
 /****************************************************************************
 }
 
 /****************************************************************************
-port info level 1 display function
 ****************************************************************************/
 ****************************************************************************/
+
 static void display_port_info_1(PORT_INFO_1 *i1)
 {
        fstring buffer;
 static void display_port_info_1(PORT_INFO_1 *i1)
 {
        fstring buffer;
@@ -381,8 +370,8 @@ static void display_port_info_1(PORT_INFO_1 *i1)
 }
 
 /****************************************************************************
 }
 
 /****************************************************************************
-port info level 2 display function
 ****************************************************************************/
 ****************************************************************************/
+
 static void display_port_info_2(PORT_INFO_2 *i2)
 {
        fstring buffer;
 static void display_port_info_2(PORT_INFO_2 *i2)
 {
        fstring buffer;
@@ -395,21 +384,46 @@ static void display_port_info_2(PORT_INFO_2 *i2)
        rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
 
        printf("\tDescription:\t[%s]\n", buffer);
        rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
 
        printf("\tDescription:\t[%s]\n", buffer);
-       printf("\tPort Type:\t[%d]\n", i2->port_type);
+       printf("\tPort Type:\t" );
+       if ( i2->port_type ) {
+               int comma = 0; /* hack */
+               printf( "[" );
+               if ( i2->port_type & PORT_TYPE_READ ) {
+                       printf( "Read" );
+                       comma = 1;
+               }
+               if ( i2->port_type & PORT_TYPE_WRITE ) {
+                       printf( "%sWrite", comma ? ", " : "" );
+                       comma = 1;
+               }
+               /* These two have slightly different interpretations
+                on 95/98/ME but I'm disregarding that for now */
+               if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
+                       printf( "%sRedirected", comma ? ", " : "" );
+                       comma = 1;
+               }
+               if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
+                       printf( "%sNet-Attached", comma ? ", " : "" );
+               }
+               printf( "]\n" );
+       } else {
+               printf( "[Unset]\n" );
+       }
        printf("\tReserved:\t[%d]\n", i2->reserved);
        printf("\n");
 }
 
        printf("\tReserved:\t[%d]\n", i2->reserved);
        printf("\n");
 }
 
-/* Enumerate ports */
+/****************************************************************************
+****************************************************************************/
 
 
-static WERROR cmd_spoolss_enum_ports(struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
        WERROR                  result;
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
        WERROR                  result;
-       uint32                  needed, info_level = 1;
+       uint32                  info_level = 1;
        PORT_INFO_CTR           ctr;
        PORT_INFO_CTR           ctr;
-       int                     returned;
+       uint32                  returned;
        
        if (argc > 2) {
                printf("Usage: %s [level]\n", argv[0]);
        
        if (argc > 2) {
                printf("Usage: %s [level]\n", argv[0]);
@@ -423,12 +437,7 @@ static WERROR cmd_spoolss_enum_ports(struct cli_state *cli,
 
        ZERO_STRUCT(ctr);
 
 
        ZERO_STRUCT(ctr);
 
-       result = cli_spoolss_enum_ports(cli, mem_ctx, 0, &needed, info_level, 
-                                       &returned, &ctr);
-
-       if (W_ERROR_V(result) == ERRinsufficientbuffer)
-               result = cli_spoolss_enum_ports(cli, mem_ctx, needed, NULL,
-                                               info_level, &returned, &ctr);
+       result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
 
        if (W_ERROR_IS_OK(result)) {
                int i;
 
        if (W_ERROR_IS_OK(result)) {
                int i;
@@ -451,18 +460,17 @@ static WERROR cmd_spoolss_enum_ports(struct cli_state *cli,
        return result;
 }
 
        return result;
 }
 
-/***********************************************************************
- * Set printer comment - use a level2 set.
- */
-static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv)
 {
        POLICY_HND      pol;
        WERROR          result;
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv)
 {
        POLICY_HND      pol;
        WERROR          result;
-       uint32          needed;
        uint32          info_level = 2;
        uint32          info_level = 2;
-       BOOL            opened_hnd = False;
+       bool            opened_hnd = False;
        PRINTER_INFO_CTR ctr;
        fstring         printername,
                        servername,
        PRINTER_INFO_CTR ctr;
        fstring         printername,
                        servername,
@@ -482,11 +490,11 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
-       fstrcpy(printername, argv[1]);
-       fstrcpy(user, cli->user_name);
+       slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
+       fstrcpy(user, cli->auth->user_name);
 
        /* get a printer handle */
 
        /* get a printer handle */
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
                                PRINTER_ALL_ACCESS, servername,
                                user, &pol);
                                
                                PRINTER_ALL_ACCESS, servername,
                                user, &pol);
                                
@@ -496,10 +504,7 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
        opened_hnd = True;
 
        /* Get printer info */
        opened_hnd = True;
 
        /* Get printer info */
-        result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, info_level, &ctr);
-
-        if (W_ERROR_V(result) == ERRinsufficientbuffer)
-                result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
+        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
 
         if (!W_ERROR_IS_OK(result))
                 goto done;
 
         if (!W_ERROR_IS_OK(result))
                 goto done;
@@ -510,33 +515,97 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli,
        ctr.printers_2->devmode = NULL;
        ctr.printers_2->secdesc = NULL;
 
        ctr.printers_2->devmode = NULL;
        ctr.printers_2->secdesc = NULL;
 
-       result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
+       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
        if (W_ERROR_IS_OK(result))
                printf("Success in setting comment.\n");
 
  done:
        if (opened_hnd)
        if (W_ERROR_IS_OK(result))
                printf("Success in setting comment.\n");
 
  done:
        if (opened_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
 }
 
 
        return result;
 }
 
-/***********************************************************************
- * Get printer information
- */
-static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc, const char **argv)
+{
+       POLICY_HND      pol;
+       WERROR          result;
+       uint32          info_level = 2;
+       bool            opened_hnd = False;
+       PRINTER_INFO_CTR ctr;
+       fstring         printername,
+                       servername,
+                       user,
+                       new_printername;
+
+       if (argc == 1 || argc > 3) {
+               printf("Usage: %s printername new_printername\n", argv[0]);
+
+               return WERR_OK;
+       }
+
+       /* Open a printer handle */
+       if (argc == 3) {
+               fstrcpy(new_printername, argv[2]);
+       }
+
+       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
+       strupper_m(servername);
+       slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
+       fstrcpy(user, cli->auth->user_name);
+
+       /* get a printer handle */
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+                               PRINTER_ALL_ACCESS, servername,
+                               user, &pol);
+                               
+       if (!W_ERROR_IS_OK(result))
+               goto done;
+
+       opened_hnd = True;
+
+       /* Get printer info */
+        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
+
+        if (!W_ERROR_IS_OK(result))
+                goto done;
+
+       /* Modify the printername. */
+       init_unistr(&ctr.printers_2->printername, new_printername);
+       ctr.printers_2->devmode = NULL;
+       ctr.printers_2->secdesc = NULL;
+
+       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
+       if (W_ERROR_IS_OK(result))
+               printf("Success in setting printername.\n");
+
+ done:
+       if (opened_hnd)
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
+
+       return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv)
 {
        POLICY_HND      pol;
        WERROR          result;
        uint32          info_level = 1;
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv)
 {
        POLICY_HND      pol;
        WERROR          result;
        uint32          info_level = 1;
-       BOOL            opened_hnd = False;
+       bool            opened_hnd = False;
        PRINTER_INFO_CTR ctr;
        fstring         printername,
                        servername,
                        user;
        PRINTER_INFO_CTR ctr;
        fstring         printername,
                        servername,
                        user;
-       uint32 needed;
 
        if (argc == 1 || argc > 3) {
                printf("Usage: %s <printername> [level]\n", argv[0]);
 
        if (argc == 1 || argc > 3) {
                printf("Usage: %s <printername> [level]\n", argv[0]);
@@ -551,11 +620,11 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
        slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
        slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
-       fstrcpy(user, cli->user_name);
+       fstrcpy(user, cli->auth->user_name);
        
        /* get a printer handle */
 
        
        /* get a printer handle */
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &pol);
 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &pol);
 
@@ -566,12 +635,7 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
 
        /* Get printer info */
 
 
        /* Get printer info */
 
-       result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
-                                       &pol, info_level, &ctr);
-
-       if (W_ERROR_V(result) == ERRinsufficientbuffer)
-               result = cli_spoolss_getprinter(
-                       cli, mem_ctx, needed, NULL, &pol, info_level, &ctr);
+       result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -591,6 +655,9 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
        case 3:
                display_print_info_3(ctr.printers_3);
                break;
        case 3:
                display_print_info_3(ctr.printers_3);
                break;
+       case 7:
+               display_print_info_7(ctr.printers_7);
+               break;
        default:
                printf("unknown info level %d\n", info_level);
                break;
        default:
                printf("unknown info level %d\n", info_level);
                break;
@@ -598,62 +665,85 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli,
 
  done: 
        if (opened_hnd) 
 
  done: 
        if (opened_hnd) 
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
 }
 
 
        return result;
 }
 
+/****************************************************************************
+****************************************************************************/
+
 static void display_reg_value(REGISTRY_VALUE value)
 {
 static void display_reg_value(REGISTRY_VALUE value)
 {
-       pstring text;
+       char *text = NULL;
 
        switch(value.type) {
        case REG_DWORD:
 
        switch(value.type) {
        case REG_DWORD:
-               printf("%s: REG_DWORD: 0x%08x\n", value.valuename, 
+               printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
                       *((uint32 *) value.data_p));
                break;
        case REG_SZ:
                       *((uint32 *) value.data_p));
                break;
        case REG_SZ:
-               rpcstr_pull(text, value.data_p, sizeof(text), value.size,
-                           STR_TERMINATE);
-               printf("%s: REG_SZ: %s\n", value.valuename, text);
+               rpcstr_pull_talloc(talloc_tos(),
+                               &text,
+                               value.data_p,
+                               value.size,
+                               STR_TERMINATE);
+               printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
                break;
                break;
-       case REG_BINARY:
-               printf("%s: REG_BINARY: unknown length value not displayed\n",
-                      value.valuename);
+       case REG_BINARY: {
+               char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
+               size_t i, len;
+               printf("%s: REG_BINARY:", value.valuename);
+               len = strlen(hex);
+               for (i=0; i<len; i++) {
+                       if (hex[i] == '\0') {
+                               break;
+                       }
+                       if (i%40 == 0) {
+                               putchar('\n');
+                       }
+                       putchar(hex[i]);
+               }
+               TALLOC_FREE(hex);
+               putchar('\n');
                break;
                break;
+       }
        case REG_MULTI_SZ: {
        case REG_MULTI_SZ: {
-               uint16 *curstr = (uint16 *) value.data_p;
-               uint8 *start = value.data_p;
-               printf("%s: REG_MULTI_SZ:\n", value.valuename);
-               while ((*curstr != 0) && 
-                      ((uint8 *) curstr < start + value.size)) {
-                       rpcstr_pull(text, curstr, sizeof(text), -1, 
-                                   STR_TERMINATE);
-                       printf("  %s\n", text);
-                       curstr += strlen(text) + 1;
+               uint32 i, num_values;
+               char **values;
+
+               if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
+                                                    value.size, &num_values,
+                                                    &values))) {
+                       d_printf("reg_pull_multi_sz failed\n");
+                       break;
+               }
+
+               for (i=0; i<num_values; i++) {
+                       d_printf("%s\n", values[i]);
                }
                }
+               TALLOC_FREE(values);
+               break;
        }
        }
-       break;
        default:
                printf("%s: unknown type %d\n", value.valuename, value.type);
        }
        
 }
 
        default:
                printf("%s: unknown type %d\n", value.valuename, value.type);
        }
        
 }
 
-/***********************************************************************
- * Get printer data
- */
-static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv)
 {
        POLICY_HND      pol;
        WERROR          result;
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv)
 {
        POLICY_HND      pol;
        WERROR          result;
-       BOOL            opened_hnd = False;
+       bool            opened_hnd = False;
        fstring         printername,
                        servername,
                        user;
        fstring         printername,
                        servername,
                        user;
-       uint32 needed;
        const char *valuename;
        REGISTRY_VALUE value;
 
        const char *valuename;
        REGISTRY_VALUE value;
 
@@ -673,11 +763,11 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
        else
                slprintf(printername, sizeof(servername)-1, "%s\\%s", 
                          servername, argv[1]);
        else
                slprintf(printername, sizeof(servername)-1, "%s\\%s", 
                          servername, argv[1]);
-       fstrcpy(user, cli->user_name);
+       fstrcpy(user, cli->auth->user_name);
        
        /* get a printer handle */
 
        
        /* get a printer handle */
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &pol);
 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &pol);
 
@@ -688,12 +778,7 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
 
        /* Get printer info */
 
 
        /* Get printer info */
 
-       result = cli_spoolss_getprinterdata(cli, mem_ctx, 0, &needed,
-                                           &pol, valuename, &value);
-
-       if (W_ERROR_V(result) == ERRmoredata)
-               result = cli_spoolss_getprinterdata(
-                       cli, mem_ctx, needed, NULL, &pol, valuename, &value);
+       result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -706,25 +791,24 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli,
 
  done: 
        if (opened_hnd) 
 
  done: 
        if (opened_hnd) 
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
 }
 
 
        return result;
 }
 
-/***********************************************************************
- * Get printer data
- */
-static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
                                             TALLOC_CTX *mem_ctx,
                                             int argc, const char **argv)
 {
        POLICY_HND      pol;
        WERROR          result;
                                             TALLOC_CTX *mem_ctx,
                                             int argc, const char **argv)
 {
        POLICY_HND      pol;
        WERROR          result;
-       BOOL            opened_hnd = False;
+       bool            opened_hnd = False;
        fstring         printername,
                        servername,
                        user;
        fstring         printername,
                        servername,
                        user;
-       uint32 needed;
        const char *valuename, *keyname;
        REGISTRY_VALUE value;
 
        const char *valuename, *keyname;
        REGISTRY_VALUE value;
 
@@ -746,11 +830,11 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
        else
                slprintf(printername, sizeof(printername)-1, "%s\\%s", 
                          servername, argv[1]);
        else
                slprintf(printername, sizeof(printername)-1, "%s\\%s", 
                          servername, argv[1]);
-       fstrcpy(user, cli->user_name);
+       fstrcpy(user, cli->auth->user_name);
        
        /* get a printer handle */
 
        
        /* get a printer handle */
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &pol);
 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &pol);
 
@@ -761,14 +845,8 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
 
        /* Get printer info */
 
 
        /* Get printer info */
 
-       result = cli_spoolss_getprinterdataex(cli, mem_ctx, 0, &needed,
-                                             &pol, keyname, valuename, 
-                                             &value);
-
-       if (W_ERROR_V(result) == ERRmoredata)
-               result = cli_spoolss_getprinterdataex(cli, mem_ctx, needed, 
-                                                     NULL, &pol, keyname,
-                                                     valuename, &value);
+       result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname, 
+               valuename, &value);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -781,14 +859,14 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli,
 
  done: 
        if (opened_hnd) 
 
  done: 
        if (opened_hnd) 
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
 }
 
 /****************************************************************************
 
        return result;
 }
 
 /****************************************************************************
-printer info level 0 display function
 ****************************************************************************/
 ****************************************************************************/
+
 static void display_print_driver_1(DRIVER_INFO_1 *i1)
 {
        fstring name;
 static void display_print_driver_1(DRIVER_INFO_1 *i1)
 {
        fstring name;
@@ -804,8 +882,8 @@ static void display_print_driver_1(DRIVER_INFO_1 *i1)
 }
 
 /****************************************************************************
 }
 
 /****************************************************************************
-printer info level 1 display function
 ****************************************************************************/
 ****************************************************************************/
+
 static void display_print_driver_2(DRIVER_INFO_2 *i1)
 {
        fstring name;
 static void display_print_driver_2(DRIVER_INFO_2 *i1)
 {
        fstring name;
@@ -834,8 +912,8 @@ static void display_print_driver_2(DRIVER_INFO_2 *i1)
 }
 
 /****************************************************************************
 }
 
 /****************************************************************************
-printer info level 2 display function
 ****************************************************************************/
 ****************************************************************************/
+
 static void display_print_driver_3(DRIVER_INFO_3 *i1)
 {
        fstring name = "";
 static void display_print_driver_3(DRIVER_INFO_3 *i1)
 {
        fstring name = "";
@@ -849,7 +927,7 @@ static void display_print_driver_3(DRIVER_INFO_3 *i1)
        fstring defaultdatatype = "";
        
        int length=0;
        fstring defaultdatatype = "";
        
        int length=0;
-       BOOL valid = True;
+       bool valid = True;
        
        if (i1 == NULL)
                return;
        
        if (i1 == NULL)
                return;
@@ -896,22 +974,23 @@ static void display_print_driver_3(DRIVER_INFO_3 *i1)
        return; 
 }
 
        return; 
 }
 
-/***********************************************************************
- * Get printer information
- */
-static WERROR cmd_spoolss_getdriver(struct cli_state *cli, 
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx,
                                       int argc, const char **argv)
 {
        POLICY_HND      pol;
        WERROR          werror;
        uint32          info_level = 3;
                                       TALLOC_CTX *mem_ctx,
                                       int argc, const char **argv)
 {
        POLICY_HND      pol;
        WERROR          werror;
        uint32          info_level = 3;
-       BOOL            opened_hnd = False;
+       bool            opened_hnd = False;
        PRINTER_DRIVER_CTR      ctr;
        fstring         printername, 
                        servername, 
                        user;
        uint32          i;
        PRINTER_DRIVER_CTR      ctr;
        fstring         printername, 
                        servername, 
                        user;
        uint32          i;
+       bool            success = False;
 
        if ((argc == 1) || (argc > 3)) 
        {
 
        if ((argc == 1) || (argc > 3)) 
        {
@@ -922,14 +1001,14 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli,
        /* get the arguments need to open the printer handle */
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
        /* get the arguments need to open the printer handle */
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
-       fstrcpy(user, cli->user_name);
-       fstrcpy(printername, argv[1]);
+       fstrcpy(user, cli->auth->user_name);
+       slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
        if (argc == 3)
                info_level = atoi(argv[2]);
 
        /* Open a printer handle */
 
        if (argc == 3)
                info_level = atoi(argv[2]);
 
        /* Open a printer handle */
 
-       werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+       werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
                                             PRINTER_ACCESS_USE,
                                             servername, user, &pol);
 
                                             PRINTER_ACCESS_USE,
                                             servername, user, &pol);
 
@@ -943,19 +1022,17 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli,
        /* loop through and print driver info level for each architecture */
 
        for (i=0; archi_table[i].long_archi!=NULL; i++) {
        /* loop through and print driver info level for each architecture */
 
        for (i=0; archi_table[i].long_archi!=NULL; i++) {
-               uint32 needed;
 
 
-               werror = cli_spoolss_getprinterdriver(
-                       cli, mem_ctx, 0, &needed, &pol, info_level, 
-                       archi_table[i].long_archi, &ctr);
-
-               if (W_ERROR_V(werror) == ERRinsufficientbuffer)
-                       werror = cli_spoolss_getprinterdriver(
-                               cli, mem_ctx, needed, NULL, &pol, info_level, 
-                               archi_table[i].long_archi, &ctr);
+               werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level, 
+                       archi_table[i].long_archi, archi_table[i].version,
+                       &ctr);
 
                if (!W_ERROR_IS_OK(werror))
                        continue;
 
                if (!W_ERROR_IS_OK(werror))
                        continue;
+               
+               /* need at least one success */
+               
+               success = True;
                        
                printf ("\n[%s]\n", archi_table[i].long_archi);
 
                        
                printf ("\n[%s]\n", archi_table[i].long_archi);
 
@@ -978,26 +1055,28 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli,
        /* Cleanup */
 
        if (opened_hnd)
        /* Cleanup */
 
        if (opened_hnd)
-               cli_spoolss_close_printer (cli, mem_ctx, &pol);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
        
        
+       if ( success )
+               werror = WERR_OK;
+               
        return werror;
 }
 
        return werror;
 }
 
-/***********************************************************************
- * Get printer information
- */
-static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli, 
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
-       WERROR werror;
+       WERROR werror = WERR_OK;
        uint32          info_level = 1;
        PRINTER_DRIVER_CTR      ctr;
        uint32          i, j,
                        returned;
 
        uint32          info_level = 1;
        PRINTER_DRIVER_CTR      ctr;
        uint32          i, j,
                        returned;
 
-       if (argc > 2) 
-       {
+       if (argc > 2) {
                printf("Usage: enumdrivers [level]\n");
                return WERR_OK;
        }
                printf("Usage: enumdrivers [level]\n");
                return WERR_OK;
        }
@@ -1007,18 +1086,22 @@ static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli,
 
 
        /* loop through and print driver info level for each architecture */
 
 
        /* loop through and print driver info level for each architecture */
-       for (i=0; archi_table[i].long_archi!=NULL; i++) 
-       {
-               uint32 needed;
+       for (i=0; archi_table[i].long_archi!=NULL; i++) {
+               /* check to see if we already asked for this architecture string */
+
+               if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
+                       continue;
 
 
-               werror = cli_spoolss_enumprinterdrivers(
-                       cli, mem_ctx, 0, &needed, info_level, 
+               werror = rpccli_spoolss_enumprinterdrivers(
+                       cli, mem_ctx, info_level, 
                        archi_table[i].long_archi, &returned, &ctr);
 
                        archi_table[i].long_archi, &returned, &ctr);
 
-               if (W_ERROR_V(werror) == ERRinsufficientbuffer)
-                       werror = cli_spoolss_enumprinterdrivers(
-                               cli, mem_ctx, needed, NULL, info_level, 
-                               archi_table[i].long_archi, &returned, &ctr);
+               if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
+                       printf ("Server does not support environment [%s]\n", 
+                               archi_table[i].long_archi);
+                       werror = WERR_OK;
+                       continue;
+               }
 
                if (returned == 0)
                        continue;
 
                if (returned == 0)
                        continue;
@@ -1035,22 +1118,22 @@ static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli,
                        
                case 1:
                        for (j=0; j < returned; j++) {
                        
                case 1:
                        for (j=0; j < returned; j++) {
-                               display_print_driver_1 (&(ctr.info1[j]));
+                               display_print_driver_1 (&ctr.info1[j]);
                        }
                        break;
                case 2:
                        for (j=0; j < returned; j++) {
                        }
                        break;
                case 2:
                        for (j=0; j < returned; j++) {
-                               display_print_driver_2 (&(ctr.info2[j]));
+                               display_print_driver_2 (&ctr.info2[j]);
                        }
                        break;
                case 3:
                        for (j=0; j < returned; j++) {
                        }
                        break;
                case 3:
                        for (j=0; j < returned; j++) {
-                               display_print_driver_3 (&(ctr.info3[j]));
+                               display_print_driver_3 (&ctr.info3[j]);
                        }
                        break;
                default:
                        printf("unknown info level %d\n", info_level);
                        }
                        break;
                default:
                        printf("unknown info level %d\n", info_level);
-                       break;
+                       return WERR_UNKNOWN_LEVEL;
                }
        }
        
                }
        }
        
@@ -1058,8 +1141,8 @@ static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli,
 }
 
 /****************************************************************************
 }
 
 /****************************************************************************
-printer info level 1 display function
 ****************************************************************************/
 ****************************************************************************/
+
 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
 {
         fstring name;
 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
 {
         fstring name;
@@ -1071,17 +1154,16 @@ static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
        printf ("\tDirectory Name:[%s]\n", name);
 }
 
        printf ("\tDirectory Name:[%s]\n", name);
 }
 
-/***********************************************************************
- * Get printer driver directory information
- */
-static WERROR cmd_spoolss_getdriverdir(struct cli_state *cli, 
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
        WERROR result;
        fstring                 env;
        DRIVER_DIRECTORY_CTR    ctr;
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
        WERROR result;
        fstring                 env;
        DRIVER_DIRECTORY_CTR    ctr;
-       uint32 needed;
 
        if (argc > 2) {
                printf("Usage: %s [environment]\n", argv[0]);
 
        if (argc > 2) {
                printf("Usage: %s [environment]\n", argv[0]);
@@ -1097,12 +1179,7 @@ static WERROR cmd_spoolss_getdriverdir(struct cli_state *cli,
 
        /* Get the directory.  Only use Info level 1 */
 
 
        /* Get the directory.  Only use Info level 1 */
 
-       result = cli_spoolss_getprinterdriverdir(
-               cli, mem_ctx, 0, &needed, 1, env, &ctr);
-
-       if (W_ERROR_V(result) == ERRinsufficientbuffer)
-               result = cli_spoolss_getprinterdriverdir(
-                       cli, mem_ctx, needed, NULL, 1, env, &ctr);
+       result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
 
        if (W_ERROR_IS_OK(result))
                display_printdriverdir_1(ctr.info1);
 
        if (W_ERROR_IS_OK(result))
                display_printdriverdir_1(ctr.info1);
@@ -1110,9 +1187,9 @@ static WERROR cmd_spoolss_getdriverdir(struct cli_state *cli,
        return result;
 }
 
        return result;
 }
 
-/*******************************************************************************
- set the version and environment fields of a DRIVER_INFO_3 struct
- ******************************************************************************/
+/****************************************************************************
+****************************************************************************/
+
 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
 {
 
 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
 {
 
@@ -1141,12 +1218,14 @@ void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
  wrapper for strtok to get the next parameter from a delimited list.
  Needed to handle the empty parameter string denoted by "NULL"
  *************************************************************************/
  wrapper for strtok to get the next parameter from a delimited list.
  Needed to handle the empty parameter string denoted by "NULL"
  *************************************************************************/
-static char* get_driver_3_param (const char* str, const char* delim, UNISTR* dest)
+static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest,
+                                char **saveptr)
 {
        char    *ptr;
 
        /* get the next token */
 {
        char    *ptr;
 
        /* get the next token */
-       ptr = strtok(str, delim);
+       ptr = strtok_r(str, delim, saveptr);
 
        /* a string of 'NULL' is used to represent an empty
           parameter because two consecutive delimiters
 
        /* a string of 'NULL' is used to represent an empty
           parameter because two consecutive delimiters
@@ -1168,49 +1247,48 @@ static char* get_driver_3_param (const char* str, const char* delim, UNISTR* des
             <Config File Name>:<Help File Name>:<Language Monitor Name>:\
             <Default Data Type>:<Comma Separated list of Files> 
  *******************************************************************************/
             <Config File Name>:<Help File Name>:<Language Monitor Name>:\
             <Default Data Type>:<Comma Separated list of Files> 
  *******************************************************************************/
-static BOOL init_drv_info_3_members (
-       TALLOC_CTX *mem_ctx, 
-       DRIVER_INFO_3 *info, 
-       const char *args
-)
+static bool init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info, 
+                                      char *args )
 {
        char    *str, *str2;
        uint32  len, i;
 {
        char    *str, *str2;
        uint32  len, i;
-       
+       char *saveptr = NULL;
+
        /* fill in the UNISTR fields */
        /* fill in the UNISTR fields */
-       str = get_driver_3_param (args, ":", &info->name);
-       str = get_driver_3_param (NULL, ":", &info->driverpath);
-       str = get_driver_3_param (NULL, ":", &info->datafile);
-       str = get_driver_3_param (NULL, ":", &info->configfile);
-       str = get_driver_3_param (NULL, ":", &info->helpfile);
-       str = get_driver_3_param (NULL, ":", &info->monitorname);
-       str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
+       str = get_driver_3_param (args, ":", &info->name, &saveptr);
+       str = get_driver_3_param (NULL, ":", &info->driverpath, &saveptr);
+       str = get_driver_3_param (NULL, ":", &info->datafile, &saveptr);
+       str = get_driver_3_param (NULL, ":", &info->configfile, &saveptr);
+       str = get_driver_3_param (NULL, ":", &info->helpfile, &saveptr);
+       str = get_driver_3_param (NULL, ":", &info->monitorname, &saveptr);
+       str = get_driver_3_param (NULL, ":", &info->defaultdatatype, &saveptr);
 
        /* <Comma Separated List of Dependent Files> */
 
        /* <Comma Separated List of Dependent Files> */
-       str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
-       str = str2;                     
+       /* save the beginning of the string */
+       str2 = get_driver_3_param (NULL, ":", NULL, &saveptr);
+       str = str2;
 
        /* begin to strip out each filename */
 
        /* begin to strip out each filename */
-       str = strtok(str, ",");         
+       str = strtok_r(str, ",", &saveptr);
        len = 0;
        while (str != NULL)
        {
                /* keep a cumlative count of the str lengths */
                len += strlen(str)+1;
        len = 0;
        while (str != NULL)
        {
                /* keep a cumlative count of the str lengths */
                len += strlen(str)+1;
-               str = strtok(NULL, ",");
+               str = strtok_r(NULL, ",", &saveptr);
        }
 
        /* allocate the space; add one extra slot for a terminating NULL.
           Each filename is NULL terminated and the end contains a double
           NULL */
        }
 
        /* allocate the space; add one extra slot for a terminating NULL.
           Each filename is NULL terminated and the end contains a double
           NULL */
-       if ((info->dependentfiles=(uint16*)talloc(mem_ctx, (len+1)*sizeof(uint16))) == NULL)
+       if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
        {
                DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
                return False;
        }
        for (i=0; i<len; i++)
        {
        {
                DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
                return False;
        }
        for (i=0; i<len; i++)
        {
-               info->dependentfiles[i] = SSVAL(&info->dependentfiles[i], 0, str2[i]);
+               SSVAL(&info->dependentfiles[i], 0, str2[i]);
        }
        info->dependentfiles[len] = '\0';
 
        }
        info->dependentfiles[len] = '\0';
 
@@ -1218,7 +1296,10 @@ static BOOL init_drv_info_3_members (
 }
 
 
 }
 
 
-static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli, 
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli, 
                                              TALLOC_CTX *mem_ctx,
                                              int argc, const char **argv)
 {
                                              TALLOC_CTX *mem_ctx,
                                              int argc, const char **argv)
 {
@@ -1228,14 +1309,16 @@ static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli,
        DRIVER_INFO_3           info3;
        const char              *arch;
        fstring                 driver_name;
        DRIVER_INFO_3           info3;
        const char              *arch;
        fstring                 driver_name;
+       char                    *driver_args;
 
 
-       /* parse the command arguements */
-       if (argc != 3)
+       /* parse the command arguments */
+       if (argc != 3 && argc != 4)
        {
        {
-               printf ("Usage: %s <Environment>\\\n", argv[0]);
+               printf ("Usage: %s <Environment> \\\n", argv[0]);
                printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
                printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
                printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
                printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
-               printf ("\t<Default Data Type>:<Comma Separated list of Files>\n");
+               printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
+               printf ("\t[version]\n");
 
             return WERR_OK;
         }
 
             return WERR_OK;
         }
@@ -1250,15 +1333,24 @@ static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli,
        else
                set_drv_info_3_env(&info3, arch);
 
        else
                set_drv_info_3_env(&info3, arch);
 
-       if (!init_drv_info_3_members(mem_ctx, &info3, argv[2]))
+       driver_args = talloc_strdup( mem_ctx, argv[2] );
+       if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
        {
                printf ("Error Invalid parameter list - %s.\n", argv[2]);
                return WERR_INVALID_PARAM;
        }
 
        {
                printf ("Error Invalid parameter list - %s.\n", argv[2]);
                return WERR_INVALID_PARAM;
        }
 
+       /* if printer driver version specified, override the default version
+        * used by the architecture.  This allows installation of Windows
+        * 2000 (version 3) printer drivers. */
+       if (argc == 4)
+       {
+               info3.version = atoi(argv[3]);
+       }
+
 
        ctr.info3 = &info3;
 
        ctr.info3 = &info3;
-       result = cli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
+       result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
 
        if (W_ERROR_IS_OK(result)) {
                rpcstr_pull(driver_name, info3.name.buffer, 
 
        if (W_ERROR_IS_OK(result)) {
                rpcstr_pull(driver_name, info3.name.buffer, 
@@ -1271,7 +1363,10 @@ static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli,
 }
 
 
 }
 
 
-static WERROR cmd_spoolss_addprinterex(struct cli_state *cli, 
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
@@ -1281,7 +1376,7 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
        PRINTER_INFO_2          info2;
        fstring                 servername;
        
        PRINTER_INFO_2          info2;
        fstring                 servername;
        
-       /* parse the command arguements */
+       /* parse the command arguments */
        if (argc != 5)
        {
                printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
        if (argc != 5)
        {
                printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
@@ -1291,11 +1386,9 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
         strupper_m(servername);
 
         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
         strupper_m(servername);
 
-       /* Fill in the DRIVER_INFO_3 struct */
+       /* Fill in the DRIVER_INFO_2 struct */
        ZERO_STRUCT(info2);
        ZERO_STRUCT(info2);
-#if 0  /* JERRY */
-       init_unistr( &info2.servername,         servername);
-#endif
+       
        init_unistr( &info2.printername,        argv[1]);
        init_unistr( &info2.sharename,          argv[2]);
        init_unistr( &info2.drivername,         argv[3]);
        init_unistr( &info2.printername,        argv[1]);
        init_unistr( &info2.sharename,          argv[2]);
        init_unistr( &info2.drivername,         argv[3]);
@@ -1320,7 +1413,7 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
        */
 
        ctr.printers_2 = &info2;
        */
 
        ctr.printers_2 = &info2;
-       result = cli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
+       result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
 
        if (W_ERROR_IS_OK(result))
                printf ("Printer %s successfully installed.\n", argv[1]);
 
        if (W_ERROR_IS_OK(result))
                printf ("Printer %s successfully installed.\n", argv[1]);
@@ -1328,22 +1421,24 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli,
        return result;
 }
 
        return result;
 }
 
-static WERROR cmd_spoolss_setdriver(struct cli_state *cli, 
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx,
                                       int argc, const char **argv)
 {
        POLICY_HND              pol;
        WERROR                  result;
        uint32                  level = 2;
                                       TALLOC_CTX *mem_ctx,
                                       int argc, const char **argv)
 {
        POLICY_HND              pol;
        WERROR                  result;
        uint32                  level = 2;
-       BOOL                    opened_hnd = False;
+       bool                    opened_hnd = False;
        PRINTER_INFO_CTR        ctr;
        PRINTER_INFO_2          info2;
        fstring                 servername,
                                printername,
                                user;
        PRINTER_INFO_CTR        ctr;
        PRINTER_INFO_2          info2;
        fstring                 servername,
                                printername,
                                user;
-       uint32 needed;
        
        
-       /* parse the command arguements */
+       /* parse the command arguments */
        if (argc != 3)
        {
                printf ("Usage: %s <printer> <driver>\n", argv[0]);
        if (argc != 3)
        {
                printf ("Usage: %s <printer> <driver>\n", argv[0]);
@@ -1353,11 +1448,11 @@ static WERROR cmd_spoolss_setdriver(struct cli_state *cli,
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
        slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
        slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
-       fstrcpy(user, cli->user_name);
+       fstrcpy(user, cli->auth->user_name);
 
        /* Get a printer handle */
 
 
        /* Get a printer handle */
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
                                             PRINTER_ALL_ACCESS,
                                             servername, user, &pol);
 
                                             PRINTER_ALL_ACCESS,
                                             servername, user, &pol);
 
@@ -1371,12 +1466,7 @@ static WERROR cmd_spoolss_setdriver(struct cli_state *cli,
        ZERO_STRUCT (info2);
        ctr.printers_2 = &info2;
 
        ZERO_STRUCT (info2);
        ctr.printers_2 = &info2;
 
-       result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
-                                       &pol, level, &ctr);
-
-       if (W_ERROR_V(result) == ERRinsufficientbuffer)
-               result = cli_spoolss_getprinter(
-                       cli, mem_ctx, needed, NULL, &pol, level, &ctr);
+       result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
 
        if (!W_ERROR_IS_OK(result)) {
                printf ("Unable to retrieve printer information!\n");
 
        if (!W_ERROR_IS_OK(result)) {
                printf ("Unable to retrieve printer information!\n");
@@ -1387,36 +1477,96 @@ static WERROR cmd_spoolss_setdriver(struct cli_state *cli,
 
        init_unistr(&ctr.printers_2->drivername, argv[2]);
 
 
        init_unistr(&ctr.printers_2->drivername, argv[2]);
 
-       result = cli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
+       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
 
        if (!W_ERROR_IS_OK(result)) {
                printf("SetPrinter call failed!\n");
                goto done;;
        }
 
 
        if (!W_ERROR_IS_OK(result)) {
                printf("SetPrinter call failed!\n");
                goto done;;
        }
 
-       printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
+       printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
 
 done:
        /* Cleanup */
 
        if (opened_hnd)
 
 done:
        /* Cleanup */
 
        if (opened_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
 }
 
 
 
        return result;
 }
 
 
-static WERROR cmd_spoolss_deletedriver(struct cli_state *cli, 
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
-       WERROR result;
+       WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
+       int   i;
+       int vers = -1;
+       const char *arch = NULL;
+       /* parse the command arguments */
+       if (argc < 2 || argc > 4) {
+               printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
+               return WERR_OK;
+       }
+
+       if (argc >= 3)
+               arch = argv[2];
+       if (argc == 4)
+               vers = atoi (argv[3]);
+       /* delete the driver for all architectures */
+       for (i=0; archi_table[i].long_archi; i++) {
+
+               if (arch &&  !strequal( archi_table[i].long_archi, arch)) 
+                       continue;
+
+               if (vers >= 0 && archi_table[i].version != vers)
+                       continue;
+
+               /* make the call to remove the driver */
+               result = rpccli_spoolss_deleteprinterdriverex(
+                       cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version); 
+
+               if ( !W_ERROR_IS_OK(result) ) 
+               {
+                       if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
+                               printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n", 
+                                       argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
+                       }
+               } 
+               else 
+               {
+                       printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1], 
+                       archi_table[i].long_archi, archi_table[i].version);
+                       ret = WERR_OK;
+               }
+       }
+  
+       return ret;
+}
+
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli, 
+                                         TALLOC_CTX *mem_ctx,
+                                         int argc, const char **argv)
+{
+       WERROR result = WERR_OK;
        fstring                 servername;
        int                     i;
        
        fstring                 servername;
        int                     i;
        
-       /* parse the command arguements */
-       if (argc != 2)
-       {
+       /* parse the command arguments */
+       if (argc != 2) {
                printf ("Usage: %s <driver>\n", argv[0]);
                return WERR_OK;
         }
                printf ("Usage: %s <driver>\n", argv[0]);
                return WERR_OK;
         }
@@ -1425,10 +1575,9 @@ static WERROR cmd_spoolss_deletedriver(struct cli_state *cli,
        strupper_m(servername);
 
        /* delete the driver for all architectures */
        strupper_m(servername);
 
        /* delete the driver for all architectures */
-       for (i=0; archi_table[i].long_archi; i++)
-       {
+       for (i=0; archi_table[i].long_archi; i++) {
                /* make the call to remove the driver */
                /* make the call to remove the driver */
-               result = cli_spoolss_deleteprinterdriver(
+               result = rpccli_spoolss_deleteprinterdriver(
                        cli, mem_ctx, archi_table[i].long_archi, argv[1]);
 
                if ( !W_ERROR_IS_OK(result) ) {
                        cli, mem_ctx, archi_table[i].long_archi, argv[1]);
 
                if ( !W_ERROR_IS_OK(result) ) {
@@ -1437,9 +1586,7 @@ static WERROR cmd_spoolss_deletedriver(struct cli_state *cli,
                                        argv[1], archi_table[i].long_archi, 
                                        W_ERROR_V(result));
                        }
                                        argv[1], archi_table[i].long_archi, 
                                        W_ERROR_V(result));
                        }
-               } 
-               else 
-               {
+               } else {
                        printf ("Driver %s removed for arch [%s].\n", argv[1], 
                                archi_table[i].long_archi);
                }
                        printf ("Driver %s removed for arch [%s].\n", argv[1], 
                                archi_table[i].long_archi);
                }
@@ -1448,16 +1595,18 @@ static WERROR cmd_spoolss_deletedriver(struct cli_state *cli,
        return result;
 }
 
        return result;
 }
 
-static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli, 
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli, 
                                            TALLOC_CTX *mem_ctx,
                                            int argc, const char **argv)
 {
        WERROR result;
        char *servername = NULL, *environment = NULL;
        fstring procdir;
                                            TALLOC_CTX *mem_ctx,
                                            int argc, const char **argv)
 {
        WERROR result;
        char *servername = NULL, *environment = NULL;
        fstring procdir;
-       uint32 needed;
        
        
-       /* parse the command arguements */
+       /* parse the command arguments */
        if (argc > 2) {
                printf ("Usage: %s [environment]\n", argv[0]);
                return WERR_OK;
        if (argc > 2) {
                printf ("Usage: %s [environment]\n", argv[0]);
                return WERR_OK;
@@ -1473,13 +1622,8 @@ static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli,
                return WERR_NOMEM;
        }
 
                return WERR_NOMEM;
        }
 
-       result = cli_spoolss_getprintprocessordirectory(
-               cli, mem_ctx, 0, &needed, servername, environment, procdir);
-
-       if (W_ERROR_V(result) == ERRinsufficientbuffer)
-               result = cli_spoolss_getprintprocessordirectory(
-                       cli, mem_ctx, needed, NULL, servername, environment, 
-                       procdir);
+       result = rpccli_spoolss_getprintprocessordirectory(
+               cli, mem_ctx, servername, environment, procdir);
 
        if (W_ERROR_IS_OK(result))
                printf("%s\n", procdir);
 
        if (W_ERROR_IS_OK(result))
                printf("%s\n", procdir);
@@ -1490,18 +1634,19 @@ static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli,
        return result;
 }
 
        return result;
 }
 
-/* Add a form */
+/****************************************************************************
+****************************************************************************/
 
 
-static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        char *servername = NULL, *printername = NULL;
        FORM form;
                                    int argc, const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        char *servername = NULL, *printername = NULL;
        FORM form;
-       BOOL got_handle = False;
+       bool got_handle = False;
        
        
-       /* Parse the command arguements */
+       /* Parse the command arguments */
 
        if (argc != 3) {
                printf ("Usage: %s <printer> <formname>\n", argv[0]);
 
        if (argc != 3) {
                printf ("Usage: %s <printer> <formname>\n", argv[0]);
@@ -1510,13 +1655,19 @@ static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        /* Get a printer handle */
 
        
        /* Get a printer handle */
 
-       asprintf(&servername, "\\\\%s", cli->desthost);
+       if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
+               return WERR_NOMEM;
+       }
        strupper_m(servername);
        strupper_m(servername);
-       asprintf(&printername, "%s\\%s", servername, argv[1]);
+       if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
+               SAFE_FREE(servername);
+               return WERR_NOMEM;
+       }
 
 
-       werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
-                                            MAXIMUM_ALLOWED_ACCESS, 
-                                            servername, cli->user_name, &handle);
+       werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+                                            PRINTER_ALL_ACCESS, 
+                                            servername, cli->auth->user_name,
+                                            &handle);
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
@@ -1532,16 +1683,16 @@ static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        form.right = 20;
        form.bottom = 30;
 
        form.right = 20;
        form.bottom = 30;
 
-       init_unistr2(&form.name, argv[2], strlen(argv[2]) + 1);
+       init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
 
        /* Add the form */
 
 
 
        /* Add the form */
 
 
-       werror = cli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
+       werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
 
  done:
        if (got_handle)
 
  done:
        if (got_handle)
-               cli_spoolss_close_printer(cli, mem_ctx, &handle);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
@@ -1549,18 +1700,19 @@ static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return werror;
 }
 
        return werror;
 }
 
-/* Set a form */
+/****************************************************************************
+****************************************************************************/
 
 
-static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        char *servername = NULL, *printername = NULL;
        FORM form;
                                    int argc, const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        char *servername = NULL, *printername = NULL;
        FORM form;
-       BOOL got_handle = False;
+       bool got_handle = False;
        
        
-       /* Parse the command arguements */
+       /* Parse the command arguments */
 
        if (argc != 3) {
                printf ("Usage: %s <printer> <formname>\n", argv[0]);
 
        if (argc != 3) {
                printf ("Usage: %s <printer> <formname>\n", argv[0]);
@@ -1569,13 +1721,18 @@ static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        /* Get a printer handle */
 
        
        /* Get a printer handle */
 
-       asprintf(&servername, "\\\\%s", cli->desthost);
+       if (asprintf(&servername, "\\\\%s", cli->desthost)) {
+               return WERR_NOMEM;
+       }
        strupper_m(servername);
        strupper_m(servername);
-       asprintf(&printername, "%s\\%s", servername, argv[1]);
+       if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
+               SAFE_FREE(servername);
+               return WERR_NOMEM;
+       }
 
 
-       werror = cli_spoolss_open_printer_ex(
+       werror = rpccli_spoolss_open_printer_ex(
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
-               servername, cli->user_name, &handle);
+               servername, cli->auth->user_name, &handle);
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
@@ -1591,15 +1748,15 @@ static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        form.right = 2000;
        form.bottom = 3000;
 
        form.right = 2000;
        form.bottom = 3000;
 
-       init_unistr2(&form.name, argv[2], strlen(argv[2]) + 1);
+       init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
 
        /* Set the form */
 
 
        /* Set the form */
 
-       werror = cli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
+       werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
 
  done:
        if (got_handle)
 
  done:
        if (got_handle)
-               cli_spoolss_close_printer(cli, mem_ctx, &handle);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
@@ -1607,19 +1764,57 @@ static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return werror;
 }
 
        return werror;
 }
 
-/* Get a form */
+/****************************************************************************
+****************************************************************************/
+
+static const char *get_form_flag(int form_flag)
+{
+       switch (form_flag) {
+       case FORM_USER:
+               return "FORM_USER";
+       case FORM_BUILTIN:
+               return "FORM_BUILTIN";
+       case FORM_PRINTER:
+               return "FORM_PRINTER";
+       default:
+               return "unknown";
+       }
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_form(FORM_1 *form)
+{
+       fstring form_name = "";
+
+       if (form->name.buffer)
+               rpcstr_pull(form_name, form->name.buffer,
+                           sizeof(form_name), -1, STR_TERMINATE);
+
+       printf("%s\n" \
+               "\tflag: %s (%d)\n" \
+               "\twidth: %d, length: %d\n" \
+               "\tleft: %d, right: %d, top: %d, bottom: %d\n\n", 
+               form_name, get_form_flag(form->flag), form->flag,
+               form->width, form->length, 
+               form->left, form->right, 
+               form->top, form->bottom);
+}
 
 
-static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        char *servername = NULL, *printername = NULL;
        FORM_1 form;
                                    int argc, const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        char *servername = NULL, *printername = NULL;
        FORM_1 form;
-       BOOL got_handle = False;
-       uint32 needed;
+       bool got_handle = False;
        
        
-       /* Parse the command arguements */
+       /* Parse the command arguments */
 
        if (argc != 3) {
                printf ("Usage: %s <printer> <formname>\n", argv[0]);
 
        if (argc != 3) {
                printf ("Usage: %s <printer> <formname>\n", argv[0]);
@@ -1628,41 +1823,36 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        
        /* Get a printer handle */
 
        
        /* Get a printer handle */
 
-       asprintf(&servername, "\\\\%s", cli->desthost);
+       if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
+               return WERR_NOMEM;
+       }
        strupper_m(servername);
        strupper_m(servername);
-       asprintf(&printername, "%s\\%s", servername, argv[1]);
+       if (asprintf(&printername, "%s\\%s", servername, argv[1])) {
+               SAFE_FREE(servername);
+               return WERR_NOMEM;
+       }
 
 
-       werror = cli_spoolss_open_printer_ex(
+       werror = rpccli_spoolss_open_printer_ex(
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
-               servername, cli->user_name, &handle);
+               servername, cli->auth->user_name, &handle);
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
        got_handle = True;
 
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
        got_handle = True;
 
-       /* Set the form */
-
-       werror = cli_spoolss_getform(cli, mem_ctx, 0, &needed,
-                                    &handle, argv[2], 1, &form);
+       /* Get the form */
 
 
-       if (W_ERROR_V(werror) == ERRinsufficientbuffer)
-               werror = cli_spoolss_getform(cli, mem_ctx, needed, NULL,
-                                            &handle, argv[2], 1, &form);
+       werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       printf("width: %d\n", form.width);
-       printf("length: %d\n", form.length);
-       printf("left: %d\n", form.left);
-       printf("top: %d\n", form.top);
-       printf("right: %d\n", form.right);
-       printf("bottom: %d\n", form.bottom);
+       display_form(&form);
 
  done:
        if (got_handle)
 
  done:
        if (got_handle)
-               cli_spoolss_close_printer(cli, mem_ctx, &handle);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
@@ -1670,18 +1860,19 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx,
        return werror;
 }
 
        return werror;
 }
 
-/* Delete a form */
+/****************************************************************************
+****************************************************************************/
 
 
-static WERROR cmd_spoolss_deleteform(struct cli_state *cli, 
+static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        char *servername = NULL, *printername = NULL;
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        char *servername = NULL, *printername = NULL;
-       BOOL got_handle = False;
+       bool got_handle = False;
        
        
-       /* Parse the command arguements */
+       /* Parse the command arguments */
 
        if (argc != 3) {
                printf ("Usage: %s <printer> <formname>\n", argv[0]);
 
        if (argc != 3) {
                printf ("Usage: %s <printer> <formname>\n", argv[0]);
@@ -1690,13 +1881,18 @@ static WERROR cmd_spoolss_deleteform(struct cli_state *cli,
        
        /* Get a printer handle */
 
        
        /* Get a printer handle */
 
-       asprintf(&servername, "\\\\%s", cli->desthost);
+       if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
+               return WERR_NOMEM;
+       }
        strupper_m(servername);
        strupper_m(servername);
-       asprintf(&printername, "%s\\%s", servername, argv[1]);
+       if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
+               SAFE_FREE(servername);
+               return WERR_NOMEM;
+       }
 
 
-       werror = cli_spoolss_open_printer_ex(
+       werror = rpccli_spoolss_open_printer_ex(
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
-               servername, cli->user_name, &handle);
+               servername, cli->auth->user_name, &handle);
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
@@ -1705,11 +1901,11 @@ static WERROR cmd_spoolss_deleteform(struct cli_state *cli,
 
        /* Delete the form */
 
 
        /* Delete the form */
 
-       werror = cli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
+       werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
 
  done:
        if (got_handle)
 
  done:
        if (got_handle)
-               cli_spoolss_close_printer(cli, mem_ctx, &handle);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
@@ -1717,20 +1913,21 @@ static WERROR cmd_spoolss_deleteform(struct cli_state *cli,
        return werror;
 }
 
        return werror;
 }
 
-/* Enumerate forms */
+/****************************************************************************
+****************************************************************************/
 
 
-static WERROR cmd_spoolss_enum_forms(struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        char *servername = NULL, *printername = NULL;
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        char *servername = NULL, *printername = NULL;
-       BOOL got_handle = False;
-       uint32 needed, num_forms, level = 1, i;
+       bool got_handle = False;
+       uint32 num_forms, level = 1, i;
        FORM_1 *forms;
        
        FORM_1 *forms;
        
-       /* Parse the command arguements */
+       /* Parse the command arguments */
 
        if (argc != 2) {
                printf ("Usage: %s <printer>\n", argv[0]);
 
        if (argc != 2) {
                printf ("Usage: %s <printer>\n", argv[0]);
@@ -1739,13 +1936,18 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
        
        /* Get a printer handle */
 
        
        /* Get a printer handle */
 
-       asprintf(&servername, "\\\\%s", cli->desthost);
+       if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
+               return WERR_NOMEM;
+       }
        strupper_m(servername);
        strupper_m(servername);
-       asprintf(&printername, "%s\\%s", servername, argv[1]);
+       if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
+               SAFE_FREE(servername);
+               return WERR_NOMEM;
+       }
 
 
-       werror = cli_spoolss_open_printer_ex(
+       werror = rpccli_spoolss_open_printer_ex(
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
-               servername, cli->user_name, &handle);
+               servername, cli->auth->user_name, &handle);
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
@@ -1754,13 +1956,7 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
 
        /* Enumerate forms */
 
 
        /* Enumerate forms */
 
-       werror = cli_spoolss_enumforms(
-               cli, mem_ctx, 0, &needed, &handle, level, &num_forms, &forms);
-
-       if (W_ERROR_V(werror) == ERRinsufficientbuffer)
-               werror = cli_spoolss_enumforms(
-                       cli, mem_ctx, needed, NULL, &handle, level, 
-                       &num_forms, &forms);
+       werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
@@ -1768,18 +1964,14 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
        /* Display output */
 
        for (i = 0; i < num_forms; i++) {
        /* Display output */
 
        for (i = 0; i < num_forms; i++) {
-               fstring form_name;
 
 
-               if (forms[i].name.buffer)
-                       rpcstr_pull(form_name, forms[i].name.buffer,
-                                   sizeof(form_name), -1, STR_TERMINATE);
+               display_form(&forms[i]);
 
 
-               printf("%s\n", form_name);
        }
 
  done:
        if (got_handle)
        }
 
  done:
        if (got_handle)
-               cli_spoolss_close_printer(cli, mem_ctx, &handle);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
 
        SAFE_FREE(servername);
        SAFE_FREE(printername);
@@ -1787,32 +1979,62 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli,
        return werror;
 }
 
        return werror;
 }
 
-static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                                            TALLOC_CTX *mem_ctx,
                                            int argc, const char **argv)
 {
        WERROR result;
                                            TALLOC_CTX *mem_ctx,
                                            int argc, const char **argv)
 {
        WERROR result;
-       uint32 needed;
        fstring servername, printername, user;
        POLICY_HND pol;
        fstring servername, printername, user;
        POLICY_HND pol;
-       BOOL opened_hnd = False;
+       bool opened_hnd = False;
        PRINTER_INFO_CTR ctr;
        PRINTER_INFO_0 info;
        REGISTRY_VALUE value;
        PRINTER_INFO_CTR ctr;
        PRINTER_INFO_0 info;
        REGISTRY_VALUE value;
-
-       /* parse the command arguements */
-       if (argc != 4) {
-               printf ("Usage: %s <printer> <value> <data>\n", argv[0]);
-               return WERR_OK;
-        }
+       TALLOC_CTX *tmp_ctx = talloc_stackframe();
+
+       /* parse the command arguments */
+       if (argc < 5) {
+               printf ("Usage: %s <printer> <string|binary|dword|multistring>"
+                       " <value> <data>\n",
+                       argv[0]);
+               result = WERR_INVALID_PARAM;
+               goto done;
+       }
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
        slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
        slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
-       fstrcpy(user, cli->user_name);
+       fstrcpy(user, cli->auth->user_name);
+
+       value.type = REG_NONE;
+
+       if (strequal(argv[2], "string")) {
+               value.type = REG_SZ;
+       }
+
+       if (strequal(argv[2], "binary")) {
+               value.type = REG_BINARY;
+       }
+
+       if (strequal(argv[2], "dword")) {
+               value.type = REG_DWORD;
+       }
+
+       if (strequal(argv[2], "multistring")) {
+               value.type = REG_MULTI_SZ;
+       }
+
+       if (value.type == REG_NONE) {
+               printf("Unknown data type: %s\n", argv[2]);
+               result =  WERR_INVALID_PARAM;
+               goto done;
+       }
 
        /* get a printer handle */
 
        /* get a printer handle */
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
                                             MAXIMUM_ALLOWED_ACCESS, servername, 
                                             user, &pol);
        if (!W_ERROR_IS_OK(result))
                                             MAXIMUM_ALLOWED_ACCESS, servername, 
                                             user, &pol);
        if (!W_ERROR_IS_OK(result))
@@ -1822,52 +2044,112 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli,
 
        ctr.printers_0 = &info;
 
 
        ctr.printers_0 = &info;
 
-        result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed,
-                                        &pol, 0, &ctr);
-
-        if (W_ERROR_V(result) == ERRinsufficientbuffer)
-                result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
+        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
 
         if (!W_ERROR_IS_OK(result))
                 goto done;
                
 
         if (!W_ERROR_IS_OK(result))
                 goto done;
                
-       printf("%s\n", timestring(True));
+       printf("%s\n", current_timestring(tmp_ctx, True));
        printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
 
        /* Set the printer data */
        
        printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
 
        /* Set the printer data */
        
-       fstrcpy(value.valuename, argv[2]);
-       value.type = REG_SZ;
-       value.size = strlen(argv[3]) + 1;
-       value.data_p = talloc_memdup(mem_ctx, argv[3], value.size);
+       fstrcpy(value.valuename, argv[3]);
+
+       switch (value.type) {
+       case REG_SZ: {
+               UNISTR2 data;
+               init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
+               value.size = data.uni_str_len * 2;
+               if (value.size) {
+                       value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
+                                                     value.size);
+               } else {
+                       value.data_p = NULL;
+               }
+               break;
+       }
+       case REG_DWORD: {
+               uint32 data = strtoul(argv[4], NULL, 10);
+               value.size = sizeof(data);
+               if (sizeof(data)) {
+                       value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
+                                                     sizeof(data));
+               } else {
+                       value.data_p = NULL;
+               }
+               break;
+       }
+       case REG_BINARY: {
+               DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
+               value.data_p = data.data;
+               value.size = data.length;
+               break;
+       }
+       case REG_MULTI_SZ: {
+               int i;
+               size_t len = 0;
+               char *p;
+
+               for (i=4; i<argc; i++) {
+                       if (strcmp(argv[i], "NULL") == 0) {
+                               argv[i] = "";
+                       }
+                       len += strlen(argv[i])+1;
+               }
+
+               value.size = len*2;
+               value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
+               if (value.data_p == NULL) {
+                       result = WERR_NOMEM;
+                       goto done;
+               }
+
+               p = (char *)value.data_p;
+               len = value.size;
+               for (i=4; i<argc; i++) {
+                       size_t l = (strlen(argv[i])+1)*2;
+                       rpcstr_push(p, argv[i], len, STR_TERMINATE);
+                       p += l;
+                       len -= l;
+               }
+               SMB_ASSERT(len == 0);
+               break;
+       }
+       default:
+               printf("Unknown data type: %s\n", argv[2]);
+               result = WERR_INVALID_PARAM;
+               goto done;
+       }
 
 
-       result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
+       result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
                
        if (!W_ERROR_IS_OK(result)) {
                
        if (!W_ERROR_IS_OK(result)) {
-               printf ("Unable to set [%s=%s]!\n", argv[2], argv[3]);
+               printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
                goto done;
        }
                goto done;
        }
-       printf("\tSetPrinterData succeeded [%s: %s]\n", argv[2], argv[3]);
-
-        result = cli_spoolss_getprinter(cli, mem_ctx, 0, &needed, &pol, 0, &ctr);
-
-        if (W_ERROR_V(result) == ERRinsufficientbuffer)
-                result = cli_spoolss_getprinter(cli, mem_ctx, needed, NULL, &pol, 0, &ctr);
+       printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
+       
+        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
 
         if (!W_ERROR_IS_OK(result))
                 goto done;
                
 
         if (!W_ERROR_IS_OK(result))
                 goto done;
                
-       printf("%s\n", timestring(True));
+       printf("%s\n", current_timestring(tmp_ctx, True));
        printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
 
 done:
        /* cleanup */
        printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
 
 done:
        /* cleanup */
+       TALLOC_FREE(tmp_ctx);
        if (opened_hnd)
        if (opened_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
 }
 
 
        return result;
 }
 
+/****************************************************************************
+****************************************************************************/
+
 static void display_job_info_1(JOB_INFO_1 *job)
 {
        fstring username = "", document = "", text_status = "";
 static void display_job_info_1(JOB_INFO_1 *job)
 {
        fstring username = "", document = "", text_status = "";
@@ -1886,6 +2168,9 @@ static void display_job_info_1(JOB_INFO_1 *job)
               job->totalpages);
 }
 
               job->totalpages);
 }
 
+/****************************************************************************
+****************************************************************************/
+
 static void display_job_info_2(JOB_INFO_2 *job)
 {
        fstring username = "", document = "", text_status = "";
 static void display_job_info_2(JOB_INFO_2 *job)
 {
        fstring username = "", document = "", text_status = "";
@@ -1904,25 +2189,26 @@ static void display_job_info_2(JOB_INFO_2 *job)
               job->totalpages, job->size);
 }
 
               job->totalpages, job->size);
 }
 
-/* Enumerate jobs */
+/****************************************************************************
+****************************************************************************/
 
 
-static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli, 
                                      TALLOC_CTX *mem_ctx, int argc, 
                                      const char **argv)
 {
        WERROR result;
                                      TALLOC_CTX *mem_ctx, int argc, 
                                      const char **argv)
 {
        WERROR result;
-       uint32 needed, level = 1, num_jobs, i;
-       BOOL got_hnd = False;
-       pstring printername;
+       uint32 level = 1, num_jobs, i;
+       bool got_hnd = False;
+       char *printername = NULL;
        fstring servername, user;
        POLICY_HND hnd;
        JOB_INFO_CTR ctr;
        fstring servername, user;
        POLICY_HND hnd;
        JOB_INFO_CTR ctr;
-       
+
        if (argc < 2 || argc > 3) {
                printf("Usage: %s printername [level]\n", argv[0]);
                return WERR_OK;
        }
        if (argc < 2 || argc > 3) {
                printf("Usage: %s printername [level]\n", argv[0]);
                return WERR_OK;
        }
-       
+
        if (argc == 3)
                level = atoi(argv[2]);
 
        if (argc == 3)
                level = atoi(argv[2]);
 
@@ -1930,31 +2216,31 @@ static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli,
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
-       fstrcpy(user, cli->user_name);
-       slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->desthost);
+       fstrcpy(user, cli->auth->user_name);
+       printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
+       if (!printername) {
+               return WERR_NOMEM;
+       }
        strupper_m(printername);
        strupper_m(printername);
-       pstrcat(printername, argv[1]);
+       printername = talloc_asprintf_append(printername, "%s", argv[1]);
+       if (!printername) {
+               return WERR_NOMEM;
+       }
 
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
-                                            "", MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+                                            "", MAXIMUM_ALLOWED_ACCESS,
                                             servername, user, &hnd);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
                                             servername, user, &hnd);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
+
        got_hnd = True;
 
        /* Enumerate ports */
 
        got_hnd = True;
 
        /* Enumerate ports */
 
-       result = cli_spoolss_enumjobs(
-               cli, mem_ctx, 0, &needed, &hnd, level, 0, 1000,
+       result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
                &num_jobs, &ctr);
 
                &num_jobs, &ctr);
 
-       if (W_ERROR_V(result) == ERRinsufficientbuffer)
-               result = cli_spoolss_enumjobs(
-                       cli, mem_ctx, needed, NULL, &hnd, level, 0,
-                       1000, &num_jobs, &ctr);
-
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        if (!W_ERROR_IS_OK(result))
                goto done;
 
@@ -1974,21 +2260,22 @@ static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli,
        
 done:
        if (got_hnd)
        
 done:
        if (got_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
 }
 
 
        return result;
 }
 
-/* enumerate data */
+/****************************************************************************
+****************************************************************************/
 
 
-static WERROR cmd_spoolss_enum_data( struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli, 
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
        WERROR result;
        uint32 i=0, val_needed, data_needed;
                                       TALLOC_CTX *mem_ctx, int argc, 
                                       const char **argv)
 {
        WERROR result;
        uint32 i=0, val_needed, data_needed;
-       BOOL got_hnd = False;
-       pstring printername;
+       bool got_hnd = False;
+       char *printername = NULL;
        fstring servername, user;
        POLICY_HND hnd;
 
        fstring servername, user;
        POLICY_HND hnd;
 
@@ -1996,18 +2283,24 @@ static WERROR cmd_spoolss_enum_data( struct cli_state *cli,
                printf("Usage: %s printername\n", argv[0]);
                return WERR_OK;
        }
                printf("Usage: %s printername\n", argv[0]);
                return WERR_OK;
        }
-       
+
        /* Open printer handle */
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
        /* Open printer handle */
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
-       fstrcpy(user, cli->user_name);
-       slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
+       fstrcpy(user, cli->auth->user_name);
+       printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
+       if (!printername) {
+               return WERR_NOMEM;
+       }
        strupper_m(printername);
        strupper_m(printername);
-       pstrcat(printername, argv[1]);
+       printername = talloc_asprintf_append(printername, "%s", argv[1]);
+       if (!printername) {
+               return WERR_NOMEM;
+       }
 
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
-                                            "", MAXIMUM_ALLOWED_ACCESS, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
+                                            "", MAXIMUM_ALLOWED_ACCESS,
                                             servername, user, &hnd);
 
        if (!W_ERROR_IS_OK(result))
                                             servername, user, &hnd);
 
        if (!W_ERROR_IS_OK(result))
@@ -2017,12 +2310,12 @@ static WERROR cmd_spoolss_enum_data( struct cli_state *cli,
 
        /* Enumerate data */
 
 
        /* Enumerate data */
 
-       result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
+       result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
                                             &val_needed, &data_needed,
                                             NULL);
        while (W_ERROR_IS_OK(result)) {
                REGISTRY_VALUE value;
                                             &val_needed, &data_needed,
                                             NULL);
        while (W_ERROR_IS_OK(result)) {
                REGISTRY_VALUE value;
-               result = cli_spoolss_enumprinterdata(
+               result = rpccli_spoolss_enumprinterdata(
                        cli, mem_ctx, &hnd, i++, val_needed,
                        data_needed, 0, 0, &value);
                if (W_ERROR_IS_OK(result))
                        cli, mem_ctx, &hnd, i++, val_needed,
                        data_needed, 0, 0, &value);
                if (W_ERROR_IS_OK(result))
@@ -2033,43 +2326,51 @@ static WERROR cmd_spoolss_enum_data( struct cli_state *cli,
 
 done:
        if (got_hnd)
 
 done:
        if (got_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
 }
 
 
        return result;
 }
 
-/* enumerate data for a given key */
+/****************************************************************************
+****************************************************************************/
 
 
-static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli, 
                                          TALLOC_CTX *mem_ctx, int argc, 
                                          const char **argv)
 {
        WERROR result;
                                          TALLOC_CTX *mem_ctx, int argc, 
                                          const char **argv)
 {
        WERROR result;
-       uint32 needed, i;
-       BOOL got_hnd = False;
-       pstring printername;
+       uint32 i;
+       bool got_hnd = False;
+       char *printername = NULL;
        fstring servername, user;
        const char *keyname = NULL;
        POLICY_HND hnd;
        fstring servername, user;
        const char *keyname = NULL;
        POLICY_HND hnd;
-       REGVAL_CTR ctr;
+       REGVAL_CTR *ctr = NULL;
 
        if (argc != 3) {
                printf("Usage: %s printername <keyname>\n", argv[0]);
                return WERR_OK;
        }
 
        if (argc != 3) {
                printf("Usage: %s printername <keyname>\n", argv[0]);
                return WERR_OK;
        }
-       
+
        keyname = argv[2];
 
        /* Open printer handle */
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
        keyname = argv[2];
 
        /* Open printer handle */
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
-       fstrcpy(user, cli->user_name);
-       slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
+       fstrcpy(user, cli->auth->user_name);
+
+       printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
+       if (!printername) {
+               return WERR_NOMEM;
+       }
        strupper_m(printername);
        strupper_m(printername);
-       pstrcat(printername, argv[1]);
+       printername = talloc_asprintf_append(printername, "%s", argv[1]);
+       if (!printername) {
+               return WERR_NOMEM;
+       }
 
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &hnd);
 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &hnd);
 
@@ -2080,39 +2381,37 @@ static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli,
 
        /* Enumerate subkeys */
 
 
        /* Enumerate subkeys */
 
-       result = cli_spoolss_enumprinterdataex(
-               cli, mem_ctx, 0, &needed, &hnd, keyname, NULL);
+       if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) 
+               return WERR_NOMEM;
 
 
-       if (W_ERROR_V(result) == ERRmoredata)
-               result = cli_spoolss_enumprinterdataex(
-                       cli, mem_ctx, needed, NULL, &hnd, keyname, &ctr);
+       result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
 
 
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       for (i=0; i < ctr.num_values; i++) {
-               display_reg_value(*(ctr.values[i]));
+       for (i=0; i < ctr->num_values; i++) {
+               display_reg_value(*(ctr->values[i]));
        }
 
        }
 
-       regval_ctr_destroy(&ctr);
+       TALLOC_FREE( ctr );
 
 done:
        if (got_hnd)
 
 done:
        if (got_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
 }
 
 
        return result;
 }
 
-/* enumerate subkeys */
+/****************************************************************************
+****************************************************************************/
 
 
-static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli, 
+static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli, 
                                             TALLOC_CTX *mem_ctx, int argc, 
                                             const char **argv)
 {
        WERROR result;
                                             TALLOC_CTX *mem_ctx, int argc, 
                                             const char **argv)
 {
        WERROR result;
-       uint32 needed, returned;
-       BOOL got_hnd = False;
-       pstring printername;
+       bool got_hnd = False;
+       char *printername = NULL;
        fstring servername, user;
        const char *keyname = NULL;
        POLICY_HND hnd;
        fstring servername, user;
        const char *keyname = NULL;
        POLICY_HND hnd;
@@ -2122,7 +2421,7 @@ static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli,
                printf("Usage: %s printername [keyname]\n", argv[0]);
                return WERR_OK;
        }
                printf("Usage: %s printername [keyname]\n", argv[0]);
                return WERR_OK;
        }
-       
+
        if (argc == 3)
                keyname = argv[2];
        else
        if (argc == 3)
                keyname = argv[2];
        else
@@ -2132,58 +2431,67 @@ static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli,
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
 
        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
        strupper_m(servername);
-       fstrcpy(user, cli->user_name);
-       slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost);
+       fstrcpy(user, cli->auth->user_name);
+
+       printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
+       if (!printername) {
+               return WERR_NOMEM;
+       }
        strupper_m(printername);
        strupper_m(printername);
-       pstrcat(printername, argv[1]);
+       printername = talloc_asprintf_append(printername, "%s", argv[1]);
+       if (!printername) {
+               return WERR_NOMEM;
+       }
 
 
-       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+
+       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &hnd);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
                                             "", MAXIMUM_ALLOWED_ACCESS, 
                                             servername, user, &hnd);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
+        
        got_hnd = True;
 
        /* Enumerate subkeys */
 
        got_hnd = True;
 
        /* Enumerate subkeys */
 
-       result = cli_spoolss_enumprinterkey(
-               cli, mem_ctx, 0, &needed, &hnd, keyname, NULL, NULL);
-
-       if (W_ERROR_V(result) == ERRmoredata)
-               result = cli_spoolss_enumprinterkey(
-                       cli, mem_ctx, needed, NULL, &hnd, keyname, &keylist,
-                       &returned);
+       result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
 
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        curkey = keylist;
        while (*curkey != 0) {
 
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        curkey = keylist;
        while (*curkey != 0) {
-               pstring subkey;
-               rpcstr_pull(subkey, curkey, sizeof(subkey), -1, 
+               char *subkey = NULL;
+               rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
                            STR_TERMINATE);
                            STR_TERMINATE);
+               if (!subkey) {
+                       break;
+               }
                printf("%s\n", subkey);
                curkey += strlen(subkey) + 1;
        }
 
                printf("%s\n", subkey);
                curkey += strlen(subkey) + 1;
        }
 
-       safe_free(keylist);
-
 done:
 done:
+
+       SAFE_FREE(keylist);
+
        if (got_hnd)
        if (got_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
 }
 
 
        return result;
 }
 
-static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli, 
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli, 
                                     TALLOC_CTX *mem_ctx, int argc, 
                                     const char **argv)
 {
        fstring servername, printername;
        POLICY_HND hnd;
                                     TALLOC_CTX *mem_ctx, int argc, 
                                     const char **argv)
 {
        fstring servername, printername;
        POLICY_HND hnd;
-       BOOL got_hnd = False;
+       bool got_hnd = False;
        WERROR result;
        SPOOL_NOTIFY_OPTION option;
 
        WERROR result;
        SPOOL_NOTIFY_OPTION option;
 
@@ -2198,13 +2506,13 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
        slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
        strupper_m(servername);
 
        slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
        strupper_m(servername);
 
-       slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->desthost,
-                argv[1]);
+       slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s",
+                cli->desthost, argv[1]);
        strupper_m(printername);
 
        strupper_m(printername);
 
-       result = cli_spoolss_open_printer_ex(
+       result = rpccli_spoolss_open_printer_ex(
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
                cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
-               servername, cli->user_name, &hnd);
+               servername, cli->auth->user_name, &hnd);
 
        if (!W_ERROR_IS_OK(result)) {
                printf("Error opening %s\n", argv[1]);
 
        if (!W_ERROR_IS_OK(result)) {
                printf("Error opening %s\n", argv[1]);
@@ -2221,8 +2529,11 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
        option.option_type_ptr = 1;
        option.count = option.ctr.count = 2;
 
        option.option_type_ptr = 1;
        option.count = option.ctr.count = 2;
 
-       option.ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)talloc(
-               mem_ctx, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * 2);
+       option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
+       if (option.ctr.type == NULL) {
+               result = WERR_NOMEM;
+               goto done;
+       }
 
        ZERO_STRUCT(option.ctr.type[0]);
        option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
 
        ZERO_STRUCT(option.ctr.type[0]);
        option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
@@ -2241,7 +2552,7 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
        slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
        strupper_m(servername);
 
        slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
        strupper_m(servername);
 
-       result = cli_spoolss_rffpcnex(
+       result = rpccli_spoolss_rffpcnex(
                cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
 
        if (!W_ERROR_IS_OK(result)) {
                cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
 
        if (!W_ERROR_IS_OK(result)) {
@@ -2251,43 +2562,248 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli,
 
 done:          
        if (got_hnd)
 
 done:          
        if (got_hnd)
-               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+
+       return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
+                             struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
+{
+       PRINTER_INFO_CTR ctr1, ctr2;
+       WERROR werror;
+       TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
+
+       printf("Retrieving printer propertiesfor %s...", cli1->desthost);
+       werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
+       if ( !W_ERROR_IS_OK(werror) ) {
+               printf("failed (%s)\n", win_errstr(werror));
+               talloc_destroy(mem_ctx);
+               return False;
+       }
+       printf("ok\n");
+
+       printf("Retrieving printer properties for %s...", cli2->desthost);
+       werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
+       if ( !W_ERROR_IS_OK(werror) ) {
+               printf("failed (%s)\n", win_errstr(werror));
+               talloc_destroy(mem_ctx);
+               return False;
+       }
+       printf("ok\n");
+
+       talloc_destroy(mem_ctx);
+
+       return True;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
+                                     struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
+{
+       PRINTER_INFO_CTR ctr1, ctr2;
+       WERROR werror;
+       TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
+       SEC_DESC *sd1, *sd2;
+       bool result = True;
+
+
+       printf("Retrieving printer security for %s...", cli1->desthost);
+       werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
+       if ( !W_ERROR_IS_OK(werror) ) {
+               printf("failed (%s)\n", win_errstr(werror));
+               result = False;
+               goto done;
+       }
+       printf("ok\n");
 
 
+       printf("Retrieving printer security for %s...", cli2->desthost);
+       werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
+       if ( !W_ERROR_IS_OK(werror) ) {
+               printf("failed (%s)\n", win_errstr(werror));
+               result = False;
+               goto done;
+       }
+       printf("ok\n");
+       
+
+       printf("++ ");
+
+       if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
+               printf("NULL PRINTER_INFO_3!\n");
+               result = False;
+               goto done;
+       }
+       
+       sd1 = ctr1.printers_3->secdesc;
+       sd2 = ctr2.printers_3->secdesc;
+       
+       if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
+               printf("NULL secdesc!\n");
+               result = False;
+               goto done;
+       }
+       
+       if (!sec_desc_equal( sd1, sd2 ) ) {
+               printf("Security Descriptors *not* equal!\n");
+               result = False;
+               goto done;
+       }
+       
+       printf("Security descriptors match\n");
+       
+done:
+       talloc_destroy(mem_ctx);
        return result;
 }
 
        return result;
 }
 
+
+/****************************************************************************
+****************************************************************************/
+
+extern struct user_auth_info *rpcclient_auth_info;
+
+static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli, 
+                                    TALLOC_CTX *mem_ctx, int argc, 
+                                    const char **argv)
+{
+       fstring printername, servername1, servername2;
+       char *printername_path = NULL;
+       struct cli_state *cli_server1 = rpc_pipe_np_smb_conn(cli);
+       struct cli_state *cli_server2 = NULL;
+       struct rpc_pipe_client *cli2 = NULL;
+       POLICY_HND hPrinter1, hPrinter2;
+       NTSTATUS nt_status;
+       WERROR werror;
+
+       if ( argc != 3 )  {
+               printf("Usage: %s <printer> <server>\n", argv[0]);
+               return WERR_OK;
+       }
+
+       fstrcpy( printername, argv[1] );
+
+       fstrcpy( servername1, cli->desthost );
+       fstrcpy( servername2, argv[2] );
+       strupper_m( servername1 );
+       strupper_m( servername2 );
+
+       /* first get the connection to the remote server */
+
+       nt_status = cli_full_connection(&cli_server2, global_myname(), servername2, 
+                                       NULL, 0,
+                                       "IPC$", "IPC",
+                                       get_cmdline_auth_info_username(rpcclient_auth_info),
+                                       lp_workgroup(),
+                                       get_cmdline_auth_info_password(rpcclient_auth_info),
+                                       get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
+                                       get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
+
+       if ( !NT_STATUS_IS_OK(nt_status) )
+               return WERR_GENERAL_FAILURE;
+
+       nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
+                                            &cli2);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               printf("failed to open spoolss pipe on server %s (%s)\n",
+                       servername2, nt_errstr(nt_status));
+               return WERR_GENERAL_FAILURE;
+       }
+
+       /* now open up both printers */
+
+       printername_path = talloc_asprintf(mem_ctx,
+                               "\\\\%s\\%s",
+                               servername1,
+                               printername);
+       if (!printername_path) {
+               return WERR_NOMEM;
+       }
+       printf("Opening %s...", printername_path);
+       werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path, 
+               "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
+       if ( !W_ERROR_IS_OK(werror) ) {
+               printf("failed (%s)\n", win_errstr(werror));
+               goto done;
+       }
+       printf("ok\n");
+
+       printername_path = talloc_asprintf(mem_ctx,
+                                       "\\\\%s\\%s",
+                                       servername2,
+                                       printername);
+       if (!printername_path) {
+               return WERR_NOMEM;
+       }
+       printf("Opening %s...", printername_path);
+       werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,  
+               "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
+       if ( !W_ERROR_IS_OK(werror) ) {
+                printf("failed (%s)\n", win_errstr(werror));
+               goto done;
+       }
+       printf("ok\n");
+
+       compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
+       compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
+#if 0
+       compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
+#endif
+
+
+done:
+       /* cleanup */
+
+       printf("Closing printers...");
+       rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
+       rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
+       printf("ok\n");
+
+       /* close the second remote connection */
+
+       cli_shutdown( cli_server2 );
+       return WERR_OK;
+}
+
 /* List of commands exported by this module */
 struct cmd_set spoolss_commands[] = {
 
        { "SPOOLSS"  },
 
 /* List of commands exported by this module */
 struct cmd_set spoolss_commands[] = {
 
        { "SPOOLSS"  },
 
-       { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   PI_SPOOLSS, "Add a print driver",                  "" },
-       { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       PI_SPOOLSS, "Add a printer",                       "" },
-       { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       PI_SPOOLSS, "Delete a printer driver",             "" },
-       { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          PI_SPOOLSS, "Enumerate printer data",              "" },
-       { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       PI_SPOOLSS, "Enumerate printer data for a key",    "" },
-       { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    PI_SPOOLSS, "Enumerate printer keys",              "" },
-       { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          PI_SPOOLSS, "Enumerate print jobs",                "" },
-       { "enumports",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         PI_SPOOLSS, "Enumerate printer ports",             "" },
-       { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       PI_SPOOLSS, "Enumerate installed printer drivers", "" },
-       { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      PI_SPOOLSS, "Enumerate printers",                  "" },
-       { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     PI_SPOOLSS, "Get print driver data",               "" },
-       { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   PI_SPOOLSS, "Get printer driver data with keyname", ""},
-       { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          PI_SPOOLSS, "Get print driver information",        "" },
-       { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       PI_SPOOLSS, "Get print driver upload directory",   "" },
-       { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         PI_SPOOLSS, "Get printer info",                    "" },
-       { "getprintprocdir",RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    PI_SPOOLSS, "Get print processor directory",       "" },
-       { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    PI_SPOOLSS, "Open printer handle",                 "" },
-       { "setdriver",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          PI_SPOOLSS, "Set printer driver",                  "" },
-       { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    PI_SPOOLSS, "Get print processor directory",       "" },
-       { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            PI_SPOOLSS, "Add form",                            "" },
-       { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            PI_SPOOLSS, "Set form",                            "" },
-       { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            PI_SPOOLSS, "Get form",                            "" },
-       { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         PI_SPOOLSS, "Delete form",                         "" },
-       { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         PI_SPOOLSS, "Enumerate forms",                     "" },
-       { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         PI_SPOOLSS, "Set printer comment",                 "" },
-       { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     PI_SPOOLSS, "Set REG_SZ printer data",             "" },
-       { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           PI_SPOOLSS, "Rffpcnex test", "" },
+       { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   &syntax_spoolss, NULL, "Add a print driver",                  "" },
+       { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       &syntax_spoolss, NULL, "Add a printer",                       "" },
+       { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       &syntax_spoolss, NULL, "Delete a printer driver",             "" },
+       { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     &syntax_spoolss, NULL, "Delete a printer driver with files",  "" },
+       { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          &syntax_spoolss, NULL, "Enumerate printer data",              "" },
+       { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       &syntax_spoolss, NULL, "Enumerate printer data for a key",    "" },
+       { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    &syntax_spoolss, NULL, "Enumerate printer keys",              "" },
+       { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          &syntax_spoolss, NULL, "Enumerate print jobs",                "" },
+       { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &syntax_spoolss, NULL, "Enumerate printer ports",             "" },
+       { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
+       { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &syntax_spoolss, NULL, "Enumerate printers",                  "" },
+       { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     &syntax_spoolss, NULL, "Get print driver data",               "" },
+       { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
+       { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          &syntax_spoolss, NULL, "Get print driver information",        "" },
+       { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       &syntax_spoolss, NULL, "Get print driver upload directory",   "" },
+       { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         &syntax_spoolss, NULL, "Get printer info",                    "" },
+       { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    &syntax_spoolss, NULL, "Open printer handle",                 "" },
+       { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          &syntax_spoolss, NULL, "Set printer driver",                  "" },
+       { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    &syntax_spoolss, NULL, "Get print processor directory",       "" },
+       { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            &syntax_spoolss, NULL, "Add form",                            "" },
+       { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            &syntax_spoolss, NULL, "Set form",                            "" },
+       { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            &syntax_spoolss, NULL, "Get form",                            "" },
+       { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         &syntax_spoolss, NULL, "Delete form",                         "" },
+       { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         &syntax_spoolss, NULL, "Enumerate forms",                     "" },
+       { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         &syntax_spoolss, NULL, "Set printer comment",                 "" },
+       { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     &syntax_spoolss, NULL, "Set printername",                 "" },
+       { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     &syntax_spoolss, NULL, "Set REG_SZ printer data",             "" },
+       { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           &syntax_spoolss, NULL, "Rffpcnex test", "" },
+       { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         &syntax_spoolss, NULL, "Printer comparison test", "" },
 
        { NULL }
 };
 
        { NULL }
 };