Merge branch 'master' of git://git.samba.org/samba into teventfix
[ira/wip.git] / source3 / rpcclient / cmd_spoolss.c
index 7138e8b9e3854ef6f68435821db520da3ee04f71..c68cf00530de09ffa2c0e9d00d124ceaa792a335 100644 (file)
@@ -6,17 +6,17 @@
    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 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    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, see <http://www.gnu.org/licenses/>.
 */
 #include "includes.h"
 #include "rpcclient.h"
 
+#define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
+{ \
+       _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
+               _cli->srv_name_slash, _arg); \
+       W_ERROR_HAVE_NO_MEMORY(_printername); \
+}
+
 struct table_node {
        const char      *long_archi;
        const char      *short_archi;
        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 
+   uses this property to prevent issuing multiple
    enumdriver calls for the same arch */
 
 
@@ -92,40 +99,33 @@ static const char *cmd_spoolss_get_short_archi(const char *long_archi)
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli, 
+static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
                                             TALLOC_CTX *mem_ctx,
                                             int argc, const char **argv)
 {
        WERROR          werror;
-       fstring         printername;
-       fstring         servername, user;
        POLICY_HND      hnd;
-       
+
        if (argc != 2) {
                printf("Usage: %s <printername>\n", argv[0]);
                return WERR_OK;
        }
-       
+
        if (!cli)
             return WERR_GENERAL_FAILURE;
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
-       fstrcpy(user, cli->auth->user_name);
-       fstrcpy(printername, argv[1]);
-
        /* Open the printer handle */
 
-       werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
-                                            "", PRINTER_ALL_ACCESS, 
-                                            servername, user, &hnd);
-
+       werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              argv[1],
+                                              PRINTER_ALL_ACCESS,
+                                              &hnd);
        if (W_ERROR_IS_OK(werror)) {
-               printf("Printer %s opened successfully\n", printername);
+               printf("Printer %s opened successfully\n", argv[1]);
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
 
                if (!W_ERROR_IS_OK(werror)) {
-                       printf("Error closing printer handle! (%s)\n", 
+                       printf("Error closing printer handle! (%s)\n",
                                get_dos_error_msg(werror));
                }
        }
@@ -148,23 +148,23 @@ static void display_print_info_0(PRINTER_INFO_0 *i0)
        rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
 
        rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
-  
+
        printf("\tprintername:[%s]\n", name);
        printf("\tservername:[%s]\n", servername);
        printf("\tcjobs:[0x%x]\n", i0->cjobs);
        printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
-       
-       printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month, 
+
+       printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month,
               i0->day, i0->dayofweek);
-       printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute, 
+       printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute,
               i0->second, i0->milliseconds);
-       
+
        printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
        printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
-       
+
        printf("\tmajorversion:[0x%x]\n", i0->major_version);
        printf("\tbuildversion:[0x%x]\n", i0->build_version);
-       
+
        printf("\tunknown7:[0x%x]\n", i0->unknown7);
        printf("\tunknown8:[0x%x]\n", i0->unknown8);
        printf("\tunknown9:[0x%x]\n", i0->unknown9);
@@ -231,7 +231,7 @@ static void display_print_info_2(PRINTER_INFO_2 *i2)
        fstring printprocessor = "";
        fstring datatype = "";
        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(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
@@ -264,7 +264,7 @@ static void display_print_info_2(PRINTER_INFO_2 *i2)
        printf("\tcjobs:[0x%x]\n", i2->cjobs);
        printf("\taverageppm:[0x%x]\n", i2->averageppm);
 
-       if (i2->secdesc) 
+       if (i2->secdesc)
                display_sec_desc(i2->secdesc);
 
        printf("\n");
@@ -283,19 +283,17 @@ static void display_print_info_3(PRINTER_INFO_3 *i3)
 /****************************************************************************
 ****************************************************************************/
 
-static void display_print_info_7(PRINTER_INFO_7 *i7)
+static void display_print_info7(struct spoolss_PrinterInfo7 *r)
 {
-       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);
+       printf("\tguid:[%s]\n", r->guid);
+       printf("\taction:[0x%x]\n", r->action);
 }
 
 
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli, 
+static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv)
 {
@@ -305,7 +303,7 @@ static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
        uint32                  i = 0, num_printers;
        fstring name;
 
-       if (argc > 3) 
+       if (argc > 3)
        {
                printf("Usage: %s [level] [name]\n", argv[0]);
                return WERR_OK;
@@ -323,7 +321,7 @@ static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
 
        ZERO_STRUCT(ctr);
 
-       result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL, 
+       result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
                info_level, &num_printers, &ctr);
 
        if (W_ERROR_IS_OK(result)) {
@@ -332,7 +330,7 @@ static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
                        printf ("No printers returned.\n");
                        goto done;
                }
-       
+
                for (i = 0; i < num_printers; i++) {
                        switch(info_level) {
                        case 0:
@@ -364,7 +362,7 @@ static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
 static void display_port_info_1(PORT_INFO_1 *i1)
 {
        fstring buffer;
-       
+
        rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
        printf("\tPort Name:\t[%s]\n", buffer);
 }
@@ -375,7 +373,7 @@ static void display_port_info_1(PORT_INFO_1 *i1)
 static void display_port_info_2(PORT_INFO_2 *i2)
 {
        fstring buffer;
-       
+
        rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
        printf("\tPort Name:\t[%s]\n", buffer);
        rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
@@ -416,20 +414,20 @@ static void display_port_info_2(PORT_INFO_2 *i2)
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli, 
-                                      TALLOC_CTX *mem_ctx, int argc, 
+static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
+                                      TALLOC_CTX *mem_ctx, int argc,
                                       const char **argv)
 {
        WERROR                  result;
        uint32                  info_level = 1;
        PORT_INFO_CTR           ctr;
        uint32                  returned;
-       
+
        if (argc > 2) {
                printf("Usage: %s [level]\n", argv[0]);
                return WERR_OK;
        }
-       
+
        if (argc == 2)
                info_level = atoi(argv[1]);
 
@@ -456,7 +454,7 @@ static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
                        }
                }
        }
-       
+
        return result;
 }
 
@@ -469,13 +467,13 @@ static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
 {
        POLICY_HND      pol;
        WERROR          result;
+       NTSTATUS        status;
        uint32          info_level = 2;
-       bool            opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
-       fstring         printername,
-                       servername,
-                       user,
-                       comment;
+       union spoolss_PrinterInfo info;
+       struct spoolss_SetPrinterInfoCtr info_ctr;
+       const char      *printername, *comment = NULL;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct sec_desc_buf secdesc_ctr;
 
        if (argc == 1 || argc > 3) {
                printf("Usage: %s printername comment\n", argv[0]);
@@ -485,42 +483,50 @@ static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
 
        /* Open a printer handle */
        if (argc == 3) {
-               fstrcpy(comment, argv[2]);
+               comment = argv[2];
        }
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
-       slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
-       fstrcpy(user, cli->auth->user_name);
+       ZERO_STRUCT(devmode_ctr);
+       ZERO_STRUCT(secdesc_ctr);
+
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
        /* get a printer handle */
-       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
-                               PRINTER_ALL_ACCESS, servername,
-                               user, &pol);
-                               
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              PRINTER_ALL_ACCESS,
+                                              &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);
-
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          info_level,
+                                          0,
+                                          &info);
         if (!W_ERROR_IS_OK(result))
                 goto done;
 
 
        /* Modify the comment. */
-       init_unistr(&ctr.printers_2->comment, comment);
-       ctr.printers_2->devmode = NULL;
-       ctr.printers_2->secdesc = NULL;
-
-       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
+       info.info2.comment = comment;
+
+       info_ctr.level = 2;
+       info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
+
+       status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
+                                          &pol,
+                                          &info_ctr,
+                                          &devmode_ctr,
+                                          &secdesc_ctr,
+                                          0, /* command */
+                                          &result);
        if (W_ERROR_IS_OK(result))
                printf("Success in setting comment.\n");
 
  done:
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -535,13 +541,17 @@ static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
 {
        POLICY_HND      pol;
        WERROR          result;
+       NTSTATUS        status;
        uint32          info_level = 2;
-       bool            opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
-       fstring         printername,
-                       servername,
-                       user,
-                       new_printername;
+       union spoolss_PrinterInfo info;
+       const char      *printername,
+                       *new_printername = NULL;
+       struct spoolss_SetPrinterInfoCtr info_ctr;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct sec_desc_buf secdesc_ctr;
+
+       ZERO_STRUCT(devmode_ctr);
+       ZERO_STRUCT(secdesc_ctr);
 
        if (argc == 1 || argc > 3) {
                printf("Usage: %s printername new_printername\n", argv[0]);
@@ -551,41 +561,48 @@ static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
 
        /* Open a printer handle */
        if (argc == 3) {
-               fstrcpy(new_printername, argv[2]);
+               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);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
        /* get a printer handle */
-       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
-                               PRINTER_ALL_ACCESS, servername,
-                               user, &pol);
-                               
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              PRINTER_ALL_ACCESS,
+                                              &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);
-
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          info_level,
+                                          0,
+                                          &info);
         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);
+       info.info2.printername = new_printername;
+       info.info2.devmode = NULL;
+       info.info2.secdesc = NULL;
+
+       info_ctr.level = info_level;
+       info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
+
+       status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
+                                          &pol,
+                                          &info_ctr,
+                                          &devmode_ctr,
+                                          &secdesc_ctr,
+                                          0, /* command */
+                                          &result);
        if (W_ERROR_IS_OK(result))
                printf("Success in setting printername.\n");
 
  done:
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -601,11 +618,8 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
        POLICY_HND      pol;
        WERROR          result;
        uint32          info_level = 1;
-       bool            opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
-       fstring         printername,
-                       servername,
-                       user;
+       const char      *printername;
+       union spoolss_PrinterInfo info;
 
        if (argc == 1 || argc > 3) {
                printf("Usage: %s <printername> [level]\n", argv[0]);
@@ -617,33 +631,31 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
                info_level = atoi(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 */
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
-       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
-                                            "", MAXIMUM_ALLOWED_ACCESS, 
-                                            servername, user, &pol);
+       /* get a printer handle */
 
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &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);
-
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          info_level,
+                                          0,
+                                          &info);
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        /* Display printer info */
-
        switch (info_level) {
-       case 0: 
+#if 0 /* FIXME GD */
+       case 0:
                display_print_info_0(ctr.printers_0);
                break;
        case 1:
@@ -655,16 +667,16 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
        case 3:
                display_print_info_3(ctr.printers_3);
                break;
+#endif
        case 7:
-               display_print_info_7(ctr.printers_7);
+               display_print_info7(&info.info7);
                break;
        default:
                printf("unknown info level %d\n", info_level);
                break;
        }
-
- done: 
-       if (opened_hnd) 
+ done:
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -728,7 +740,7 @@ static void display_reg_value(REGISTRY_VALUE value)
        default:
                printf("%s: unknown type %d\n", value.valuename, value.type);
        }
-       
+
 }
 
 /****************************************************************************
@@ -740,10 +752,7 @@ static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
 {
        POLICY_HND      pol;
        WERROR          result;
-       bool            opened_hnd = False;
-       fstring         printername,
-                       servername,
-                       user;
+       fstring         printername;
        const char *valuename;
        REGISTRY_VALUE value;
 
@@ -756,25 +765,20 @@ static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
 
        /* Open a printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
        if (strncmp(argv[1], ".", sizeof(".")) == 0)
-               fstrcpy(printername, servername);
+               fstrcpy(printername, cli->srv_name_slash);
        else
-               slprintf(printername, sizeof(servername)-1, "%s\\%s", 
-                         servername, argv[1]);
-       fstrcpy(user, cli->auth->user_name);
-       
-       /* get a printer handle */
+               slprintf(printername, sizeof(printername)-1, "%s\\%s",
+                         cli->srv_name_slash, argv[1]);
 
-       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
-                                            "", MAXIMUM_ALLOWED_ACCESS, 
-                                            servername, user, &pol);
+       /* get a printer handle */
 
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &pol);
        if (!W_ERROR_IS_OK(result))
                goto done;
-       opened_hnd = True;
 
        /* Get printer info */
 
@@ -787,10 +791,10 @@ static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
 
        fstrcpy(value.valuename, valuename);
        display_reg_value(value);
-       
 
- done: 
-       if (opened_hnd) 
+
+ done:
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -805,15 +809,18 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
 {
        POLICY_HND      pol;
        WERROR          result;
-       bool            opened_hnd = False;
-       fstring         printername,
-                       servername,
-                       user;
+       NTSTATUS        status;
+       fstring         printername;
        const char *valuename, *keyname;
        REGISTRY_VALUE value;
 
+       uint32_t type;
+       uint8_t *buffer = NULL;
+       uint32_t offered = 0;
+       uint32_t needed;
+
        if (argc != 4) {
-               printf("Usage: %s <printername> <keyname> <valuename>\n", 
+               printf("Usage: %s <printername> <keyname> <valuename>\n",
                       argv[0]);
                printf("<printername> of . queries print server\n");
                return WERR_OK;
@@ -823,30 +830,54 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
 
        /* Open a printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
        if (strncmp(argv[1], ".", sizeof(".")) == 0)
-               fstrcpy(printername, servername);
+               fstrcpy(printername, cli->srv_name_slash);
        else
-               slprintf(printername, sizeof(printername)-1, "%s\\%s", 
-                         servername, argv[1]);
-       fstrcpy(user, cli->auth->user_name);
-       
-       /* get a printer handle */
+               slprintf(printername, sizeof(printername)-1, "%s\\%s",
+                         cli->srv_name_slash, argv[1]);
 
-       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
-                                            "", MAXIMUM_ALLOWED_ACCESS, 
-                                            servername, user, &pol);
+       /* get a printer handle */
 
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &pol);
        if (!W_ERROR_IS_OK(result))
                goto done;
-       opened_hnd = True;
 
        /* Get printer info */
 
-       result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname, 
-               valuename, &value);
+       status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
+                                                &pol,
+                                                keyname,
+                                                valuename,
+                                                &type,
+                                                buffer,
+                                                offered,
+                                                &needed,
+                                                &result);
+       if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
+               offered = needed;
+               buffer = talloc_array(mem_ctx, uint8_t, needed);
+               status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
+                                                        &pol,
+                                                        keyname,
+                                                        valuename,
+                                                        &type,
+                                                        buffer,
+                                                        offered,
+                                                        &needed,
+                                                        &result);
+       }
+
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
 
        if (!W_ERROR_IS_OK(result))
                goto done;
@@ -854,11 +885,14 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
        /* Display printer data */
 
        fstrcpy(value.valuename, valuename);
+       value.type = type;
+       value.size = needed;
+       value.data_p = buffer;
+
        display_reg_value(value);
-       
 
- done: 
-       if (opened_hnd) 
+ done:
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -877,7 +911,7 @@ static void display_print_driver_1(DRIVER_INFO_1 *i1)
 
        printf ("Printer Driver Info 1:\n");
        printf ("\tDriver Name: [%s]\n\n", name);
-       
+
        return;
 }
 
@@ -925,10 +959,10 @@ static void display_print_driver_3(DRIVER_INFO_3 *i1)
        fstring dependentfiles = "";
        fstring monitorname = "";
        fstring defaultdatatype = "";
-       
+
        int length=0;
        bool valid = True;
-       
+
        if (i1 == NULL)
                return;
 
@@ -953,9 +987,9 @@ static void display_print_driver_3(DRIVER_INFO_3 *i1)
        while (valid)
        {
                rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
-               
+
                length+=strlen(dependentfiles)+1;
-               
+
                if (strlen(dependentfiles) > 0)
                {
                        printf ("\tDependentfiles: [%s]\n", dependentfiles);
@@ -965,108 +999,172 @@ static void display_print_driver_3(DRIVER_INFO_3 *i1)
                        valid = False;
                }
        }
-       
+
        printf ("\n");
 
        printf ("\tMonitorname: [%s]\n", monitorname);
        printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
 
-       return; 
+       return;
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli, 
+static void display_print_driver1(struct spoolss_DriverInfo1 *r)
+{
+       if (!r) {
+               return;
+       }
+
+       printf("Printer Driver Info 1:\n");
+       printf("\tDriver Name: [%s]\n\n", r->driver_name);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_print_driver2(struct spoolss_DriverInfo2 *r)
+{
+       if (!r) {
+               return;
+       }
+
+       printf("Printer Driver Info 2:\n");
+       printf("\tVersion: [%x]\n", r->version);
+       printf("\tDriver Name: [%s]\n", r->driver_name);
+       printf("\tArchitecture: [%s]\n", r->architecture);
+       printf("\tDriver Path: [%s]\n", r->driver_path);
+       printf("\tDatafile: [%s]\n", r->data_file);
+       printf("\tConfigfile: [%s]\n\n", r->config_file);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_print_driver3(struct spoolss_DriverInfo3 *r)
+{
+       int i;
+
+       if (!r) {
+               return;
+       }
+
+       printf("Printer Driver Info 3:\n");
+       printf("\tVersion: [%x]\n", r->version);
+       printf("\tDriver Name: [%s]\n", r->driver_name);
+       printf("\tArchitecture: [%s]\n", r->architecture);
+       printf("\tDriver Path: [%s]\n", r->driver_path);
+       printf("\tDatafile: [%s]\n", r->data_file);
+       printf("\tConfigfile: [%s]\n\n", r->config_file);
+       printf("\tHelpfile: [%s]\n\n", r->help_file);
+
+       for (i=0; r->dependent_files[i] != NULL; i++) {
+               printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
+       }
+
+       printf("\n");
+
+       printf("\tMonitorname: [%s]\n", r->monitor_name);
+       printf("\tDefaultdatatype: [%s]\n\n", r->default_datatype);
+}
+
+
+/****************************************************************************
+****************************************************************************/
+
+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;
-       bool            opened_hnd = False;
-       PRINTER_DRIVER_CTR      ctr;
-       fstring         printername, 
-                       servername, 
-                       user;
+       const char      *printername;
        uint32          i;
        bool            success = False;
+       union spoolss_DriverInfo info;
+       uint32_t server_major_version;
+       uint32_t server_minor_version;
 
-       if ((argc == 1) || (argc > 3)) 
+       if ((argc == 1) || (argc > 3))
        {
                printf("Usage: %s <printername> [level]\n", argv[0]);
                return WERR_OK;
        }
 
        /* get the arguments need to open the printer handle */
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
-       fstrcpy(user, cli->auth->user_name);
-       slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
+
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
+
        if (argc == 3)
                info_level = atoi(argv[2]);
 
        /* Open a printer handle */
 
-       werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
-                                            PRINTER_ACCESS_USE,
-                                            servername, user, &pol);
-
+       werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              PRINTER_ACCESS_USE,
+                                              &pol);
        if (!W_ERROR_IS_OK(werror)) {
                printf("Error opening printer handle for %s!\n", printername);
                return werror;
        }
 
-       opened_hnd = True;
-
        /* loop through and print driver info level for each architecture */
 
        for (i=0; archi_table[i].long_archi!=NULL; i++) {
 
-               werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level, 
-                       archi_table[i].long_archi, archi_table[i].version,
-                       &ctr);
-
+               werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
+                                                         &pol,
+                                                         archi_table[i].long_archi,
+                                                         info_level,
+                                                         0, /* offered */
+                                                         archi_table[i].version,
+                                                         2,
+                                                         &info,
+                                                         &server_major_version,
+                                                         &server_minor_version);
                if (!W_ERROR_IS_OK(werror))
                        continue;
-               
+
                /* need at least one success */
-               
+
                success = True;
-                       
+
                printf ("\n[%s]\n", archi_table[i].long_archi);
 
                switch (info_level) {
                case 1:
-                       display_print_driver_1 (ctr.info1);
+                       display_print_driver1(&info.info1);
                        break;
                case 2:
-                       display_print_driver_2 (ctr.info2);
+                       display_print_driver2(&info.info2);
                        break;
                case 3:
-                       display_print_driver_3 (ctr.info3);
+                       display_print_driver3(&info.info3);
                        break;
                default:
                        printf("unknown info level %d\n", info_level);
                        break;
                }
        }
-       
+
        /* Cleanup */
 
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
-       
+
        if ( success )
                werror = WERR_OK;
-               
+
        return werror;
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli, 
+static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
@@ -1093,11 +1191,11 @@ static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
                        continue;
 
                werror = rpccli_spoolss_enumprinterdrivers(
-                       cli, mem_ctx, info_level, 
+                       cli, mem_ctx, 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", 
+                       printf ("Server does not support environment [%s]\n",
                                archi_table[i].long_archi);
                        werror = WERR_OK;
                        continue;
@@ -1105,17 +1203,17 @@ static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
 
                if (returned == 0)
                        continue;
-                       
+
                if (!W_ERROR_IS_OK(werror)) {
                        printf ("Error getting driver for environment [%s] - %d\n",
                                archi_table[i].long_archi, W_ERROR_V(werror));
                        continue;
                }
-               
+
                printf ("\n[%s]\n", archi_table[i].long_archi);
-               switch (info_level) 
+               switch (info_level)
                {
-                       
+
                case 1:
                        for (j=0; j < returned; j++) {
                                display_print_driver_1 (&ctr.info1[j]);
@@ -1136,34 +1234,32 @@ static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
                        return WERR_UNKNOWN_LEVEL;
                }
        }
-       
+
        return werror;
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
+static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
 {
-        fstring name;
-        if (i1 == NULL)
-                return;
-       rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
-       printf ("\tDirectory Name:[%s]\n", name);
+       printf("\tDirectory Name:[%s]\n", r->directory_name);
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *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;
+       NTSTATUS status;
+       const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
+       DATA_BLOB buffer;
+       uint32_t offered;
+       union spoolss_DriverDirectoryInfo info;
+       uint32_t needed;
 
        if (argc > 2) {
                printf("Usage: %s [environment]\n", argv[0]);
@@ -1172,17 +1268,39 @@ static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
 
        /* Get the arguments need to open the printer handle */
 
-       if (argc == 2)
-               fstrcpy (env, argv[1]);
-       else
-               fstrcpy (env, "Windows NT x86");
+       if (argc == 2) {
+               env = argv[1];
+       }
 
        /* Get the directory.  Only use Info level 1 */
 
-       result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
+       status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
+                                                         cli->srv_name_slash,
+                                                         env,
+                                                         1,
+                                                         NULL, /* buffer */
+                                                         0, /* offered */
+                                                         NULL, /* info */
+                                                         &needed,
+                                                         &result);
+       if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
+               offered = needed;
+               buffer = data_blob_talloc_zero(mem_ctx, needed);
+
+               status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
+                                                                 cli->srv_name_slash,
+                                                                 env,
+                                                                 1,
+                                                                 &buffer,
+                                                                 offered,
+                                                                 &info,
+                                                                 &needed,
+                                                                 &result);
+       }
 
-       if (W_ERROR_IS_OK(result))
-               display_printdriverdir_1(ctr.info1);
+       if (W_ERROR_IS_OK(result)) {
+               display_printdriverdir_1(&info.info1);
+       }
 
        return result;
 }
@@ -1190,26 +1308,28 @@ static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
-void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
+static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
+                              struct spoolss_AddDriverInfo3 *info,
+                              const char *arch)
 {
 
        int i;
-       
-       for (i=0; archi_table[i].long_archi != NULL; i++) 
+
+       for (i=0; archi_table[i].long_archi != NULL; i++)
        {
                if (strcmp(arch, archi_table[i].short_archi) == 0)
                {
                        info->version = archi_table[i].version;
-                       init_unistr (&info->architecture, archi_table[i].long_archi);
+                       info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
                        break;
                }
        }
-       
+
        if (archi_table[i].long_archi == NULL)
        {
                DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
        }
-       
+
        return;
 }
 
@@ -1218,9 +1338,10 @@ 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"
  *************************************************************************/
-static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest,
-                                char **saveptr)
+
+static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
+                               const char *delim, const char **dest,
+                               char **saveptr)
 {
        char    *ptr;
 
@@ -1231,84 +1352,94 @@ static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest,
           parameter because two consecutive delimiters
           will not return an empty string.  See man strtok(3)
           for details */
-       if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
+       if (ptr && (StrCaseCmp(ptr, "NULL") == 0)) {
                ptr = NULL;
+       }
 
-       if (dest != NULL)
-               init_unistr(dest, ptr); 
+       if (dest != NULL) {
+               *dest = talloc_strdup(mem_ctx, ptr);
+       }
 
        return ptr;
 }
 
 /********************************************************************************
- fill in the members of a DRIVER_INFO_3 struct using a character 
+ fill in the members of a spoolss_AddDriverInfo3 struct using a character
  string in the form of
         <Long Printer Name>:<Driver File Name>:<Data File Name>:\
             <Config File Name>:<Help File Name>:<Language Monitor Name>:\
-            <Default Data Type>:<Comma Separated list of Files> 
+            <Default Data Type>:<Comma Separated list of Files>
  *******************************************************************************/
-static bool init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info, 
-                                      char *args )
+
+static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
+                                    char *args)
 {
        char    *str, *str2;
-       uint32  len, i;
+       int count = 0;
        char *saveptr = NULL;
+       struct spoolss_StringArray *deps;
+       const char **file_array = NULL;
+       int i;
 
        /* fill in the UNISTR fields */
-       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);
+       str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
+       str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
 
        /* <Comma Separated List of Dependent Files> */
        /* save the beginning of the string */
-       str2 = get_driver_3_param (NULL, ":", NULL, &saveptr);
+       str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
        str = str2;
 
        /* begin to strip out each filename */
        str = strtok_r(str, ",", &saveptr);
-       len = 0;
-       while (str != NULL)
-       {
-               /* keep a cumlative count of the str lengths */
-               len += strlen(str)+1;
+
+       /* no dependent files, we are done */
+       if (!str) {
+               return true;
+       }
+
+       deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
+       if (!deps) {
+               return false;
+       }
+
+       while (str != NULL) {
+               add_string_to_array(deps, str, &file_array, &count);
                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 */
-       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;
+       deps->string = talloc_zero_array(deps, const char *, count + 1);
+       if (!deps->string) {
+               return false;
        }
-       for (i=0; i<len; i++)
-       {
-               SSVAL(&info->dependentfiles[i], 0, str2[i]);
+
+       for (i=0; i < count; i++) {
+               deps->string[i] = file_array[i];
        }
-       info->dependentfiles[len] = '\0';
 
-       return True;
-}
+       r->dependent_files = deps;
 
+       return true;
+}
 
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli, 
+static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
                                              TALLOC_CTX *mem_ctx,
                                              int argc, const char **argv)
 {
        WERROR result;
+       NTSTATUS status;
        uint32                  level = 3;
-       PRINTER_DRIVER_CTR      ctr;
-       DRIVER_INFO_3           info3;
+       struct spoolss_AddDriverInfoCtr info_ctr;
+       struct spoolss_AddDriverInfo3 info3;
        const char              *arch;
-       fstring                 driver_name;
        char                    *driver_args;
 
        /* parse the command arguments */
@@ -1322,16 +1453,17 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
 
             return WERR_OK;
         }
-               
-       /* Fill in the DRIVER_INFO_3 struct */
+
+       /* Fill in the spoolss_AddDriverInfo3 struct */
        ZERO_STRUCT(info3);
-       if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
-       {
+
+       arch = cmd_spoolss_get_short_archi(argv[1]);
+       if (!arch) {
                printf ("Error Unknown architechture [%s]\n", argv[1]);
                return WERR_INVALID_PARAM;
        }
-       else
-               set_drv_info_3_env(&info3, arch);
+
+       set_drv_info_3_env(mem_ctx, &info3, arch);
 
        driver_args = talloc_strdup( mem_ctx, argv[2] );
        if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
@@ -1349,14 +1481,19 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
        }
 
 
-       ctr.info3 = &info3;
-       result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
+       info_ctr.level          = level;
+       info_ctr.info.info3     = &info3;
 
+       status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
+                                                cli->srv_name_slash,
+                                                &info_ctr,
+                                                &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               return ntstatus_to_werror(status);
+       }
        if (W_ERROR_IS_OK(result)) {
-               rpcstr_pull(driver_name, info3.name.buffer, 
-                           sizeof(driver_name), -1, STR_TERMINATE);
                printf ("Printer Driver %s successfully installed.\n",
-                       driver_name);
+                       info3.driver_name);
        }
 
        return result;
@@ -1366,55 +1503,52 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli, 
+static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
        WERROR result;
-       uint32                  level = 2;
-       PRINTER_INFO_CTR        ctr;
-       PRINTER_INFO_2          info2;
-       fstring                 servername;
-       
+       struct spoolss_SetPrinterInfoCtr info_ctr;
+       struct spoolss_SetPrinterInfo2 info2;
+
        /* parse the command arguments */
        if (argc != 5)
        {
                printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
                return WERR_OK;
         }
-       
-        slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-        strupper_m(servername);
 
        /* Fill in the DRIVER_INFO_2 struct */
        ZERO_STRUCT(info2);
-       
-       init_unistr( &info2.printername,        argv[1]);
-       init_unistr( &info2.sharename,          argv[2]);
-       init_unistr( &info2.drivername,         argv[3]);
-       init_unistr( &info2.portname,           argv[4]);
-       init_unistr( &info2.comment,            "Created by rpcclient");
-       init_unistr( &info2.printprocessor,     "winprint");
-       init_unistr( &info2.datatype,           "RAW");
-       info2.devmode =         NULL;
-       info2.secdesc =         NULL;
+
+       info2.printername       = argv[1];
+       info2.drivername        = argv[3];
+       info2.sharename         = argv[2];
+       info2.portname          = argv[4];
+       info2.comment           = "Created by rpcclient";
+       info2.printprocessor    = "winprint";
+       info2.datatype          = "RAW";
+       info2.devmode           = NULL;
+       info2.secdesc           = NULL;
        info2.attributes        = PRINTER_ATTRIBUTE_SHARED;
        info2.priority          = 0;
        info2.defaultpriority   = 0;
        info2.starttime         = 0;
        info2.untiltime         = 0;
-       
-       /* These three fields must not be used by AddPrinter() 
-          as defined in the MS Platform SDK documentation..  
+
+       /* These three fields must not be used by AddPrinter()
+          as defined in the MS Platform SDK documentation..
           --jerry
        info2.status            = 0;
        info2.cjobs             = 0;
        info2.averageppm        = 0;
        */
 
-       ctr.printers_2 = &info2;
-       result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
+       info_ctr.level = 2;
+       info_ctr.info.info2 = &info2;
 
+       result = rpccli_spoolss_addprinterex(cli, mem_ctx,
+                                            &info_ctr);
        if (W_ERROR_IS_OK(result))
                printf ("Printer %s successfully installed.\n", argv[1]);
 
@@ -1424,20 +1558,23 @@ static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *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;
+       NTSTATUS                status;
        uint32                  level = 2;
-       bool                    opened_hnd = False;
-       PRINTER_INFO_CTR        ctr;
-       PRINTER_INFO_2          info2;
-       fstring                 servername,
-                               printername,
-                               user;
-       
+       const char              *printername;
+       union spoolss_PrinterInfo info;
+       struct spoolss_SetPrinterInfoCtr info_ctr;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct sec_desc_buf secdesc_ctr;
+
+       ZERO_STRUCT(devmode_ctr);
+       ZERO_STRUCT(secdesc_ctr);
+
        /* parse the command arguments */
        if (argc != 3)
        {
@@ -1445,29 +1582,24 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
                return WERR_OK;
         }
 
-       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);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
        /* Get a printer handle */
 
-       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
-                                            PRINTER_ALL_ACCESS,
-                                            servername, user, &pol);
-
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              PRINTER_ALL_ACCESS,
+                                              &pol);
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       opened_hnd = True;
-
        /* Get printer info */
 
-       ZERO_STRUCT (info2);
-       ctr.printers_2 = &info2;
-
-       result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
-
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          level,
+                                          0,
+                                          &info);
        if (!W_ERROR_IS_OK(result)) {
                printf ("Unable to retrieve printer information!\n");
                goto done;
@@ -1475,10 +1607,17 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
 
        /* Set the printer driver */
 
-       init_unistr(&ctr.printers_2->drivername, argv[2]);
-
-       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
-
+       info.info2.drivername = argv[2];
+       info_ctr.level = 2;
+       info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
+
+       status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
+                                          &pol,
+                                          &info_ctr,
+                                          &devmode_ctr,
+                                          &secdesc_ctr,
+                                          0, /* command */
+                                          &result);
        if (!W_ERROR_IS_OK(result)) {
                printf("SetPrinter call failed!\n");
                goto done;;
@@ -1489,7 +1628,7 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
 done:
        /* Cleanup */
 
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -1499,7 +1638,7 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli, 
+static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
@@ -1508,7 +1647,7 @@ static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
 
        int   i;
        int vers = -1;
+
        const char *arch = NULL;
        uint32_t delete_flags = 0;
 
@@ -1530,7 +1669,7 @@ static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
        /* delete the driver for all architectures */
        for (i=0; archi_table[i].long_archi; i++) {
 
-               if (arch &&  !strequal( archi_table[i].long_archi, arch)) 
+               if (arch &&  !strequal( archi_table[i].long_archi, arch))
                        continue;
 
                if (vers >= 0 && archi_table[i].version != vers)
@@ -1545,21 +1684,21 @@ static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
                                                              archi_table[i].version,
                                                              &result);
 
-               if ( !W_ERROR_IS_OK(result) ) 
+               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", 
+                               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 
+               }
+               else
                {
-                       printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1], 
+                       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;
 }
 
@@ -1567,29 +1706,25 @@ static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli, 
+static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
        WERROR result = WERR_OK;
        NTSTATUS status;
-       fstring                 servername;
        int                     i;
-       
+
        /* parse the command arguments */
        if (argc != 2) {
                printf ("Usage: %s <driver>\n", argv[0]);
                return WERR_OK;
         }
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
-
        /* delete the driver for all architectures */
        for (i=0; archi_table[i].long_archi; i++) {
                /* make the call to remove the driver */
                status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
-                                                           servername,
+                                                           cli->srv_name_slash,
                                                            archi_table[i].long_archi,
                                                            argv[1],
                                                            &result);
@@ -1598,54 +1733,71 @@ static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
                }
                if ( !W_ERROR_IS_OK(result) ) {
                        if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
-                               printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n", 
-                                       argv[1], archi_table[i].long_archi, 
+                               printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
+                                       argv[1], archi_table[i].long_archi,
                                        W_ERROR_V(result));
                        }
                } else {
-                       printf ("Driver %s removed for arch [%s].\n", argv[1], 
+                       printf ("Driver %s removed for arch [%s].\n", argv[1],
                                archi_table[i].long_archi);
                }
        }
-               
+
        return result;
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *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;
-       
+       NTSTATUS status;
+       const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
+       DATA_BLOB buffer;
+       uint32_t offered;
+       union spoolss_PrintProcessorDirectoryInfo info;
+       uint32_t needed;
+
        /* parse the command arguments */
        if (argc > 2) {
                printf ("Usage: %s [environment]\n", argv[0]);
                return WERR_OK;
         }
 
-       if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
-               return WERR_NOMEM;
-       strupper_m(servername);
-
-       if (asprintf(&environment, "%s", (argc == 2) ? argv[1] : 
-                    PRINTER_DRIVER_ARCHITECTURE) < 0) {
-               SAFE_FREE(servername);
-               return WERR_NOMEM;
+       if (argc == 2) {
+               environment = argv[1];
        }
 
-       result = rpccli_spoolss_getprintprocessordirectory(
-               cli, mem_ctx, servername, environment, procdir);
+       status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
+                                                          cli->srv_name_slash,
+                                                          environment,
+                                                          1,
+                                                          NULL, /* buffer */
+                                                          0, /* offered */
+                                                          NULL, /* info */
+                                                          &needed,
+                                                          &result);
+       if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
+               offered = needed;
+               buffer = data_blob_talloc_zero(mem_ctx, needed);
 
-       if (W_ERROR_IS_OK(result))
-               printf("%s\n", procdir);
+               status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
+                                                                  cli->srv_name_slash,
+                                                                  environment,
+                                                                  1,
+                                                                  &buffer,
+                                                                  offered,
+                                                                  &info,
+                                                                  &needed,
+                                                                  &result);
+       }
 
-       SAFE_FREE(servername);
-       SAFE_FREE(environment);
+       if (W_ERROR_IS_OK(result)) {
+               printf("%s\n", info.info1.directory_name);
+       }
 
        return result;
 }
@@ -1659,68 +1811,84 @@ static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        POLICY_HND handle;
        WERROR werror;
        NTSTATUS status;
-       char *servername = NULL, *printername = NULL;
-       bool got_handle = False;
+       const char *printername;
        union spoolss_AddFormInfo info;
        struct spoolss_AddFormInfo1 info1;
+       struct spoolss_AddFormInfo2 info2;
+       uint32_t level = 1;
 
        /* Parse the command arguments */
 
-       if (argc != 3) {
-               printf ("Usage: %s <printer> <formname>\n", argv[0]);
+       if (argc < 3 || argc > 5) {
+               printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
                return WERR_OK;
         }
-       
-       /* Get a printer handle */
 
-       if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
-               return WERR_NOMEM;
-       }
-       strupper_m(servername);
-       if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
-               SAFE_FREE(servername);
-               return WERR_NOMEM;
-       }
+       /* Get a printer handle */
 
-       werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
-                                            PRINTER_ALL_ACCESS, 
-                                            servername, cli->auth->user_name,
-                                            &handle);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
+       werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              PRINTER_ALL_ACCESS,
+                                              &handle);
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
-
        /* Dummy up some values for the form data */
 
-       info1.flags             = FORM_USER;
-       info1.form_name         = argv[2];
-       info1.size.width        = 100;
-       info1.size.height       = 100;
-       info1.area.left         = 0;
-       info1.area.top          = 10;
-       info1.area.right        = 20;
-       info1.area.bottom       = 30;
+       if (argc == 4) {
+               level = atoi(argv[3]);
+       }
 
-       info.info1 = &info1;
+       switch (level) {
+       case 1:
+               info1.flags             = FORM_USER;
+               info1.form_name         = argv[2];
+               info1.size.width        = 100;
+               info1.size.height       = 100;
+               info1.area.left         = 0;
+               info1.area.top          = 10;
+               info1.area.right        = 20;
+               info1.area.bottom       = 30;
+
+               info.info1 = &info1;
+
+               break;
+       case 2:
+               info2.flags             = FORM_USER;
+               info2.form_name         = argv[2];
+               info2.size.width        = 100;
+               info2.size.height       = 100;
+               info2.area.left         = 0;
+               info2.area.top          = 10;
+               info2.area.right        = 20;
+               info2.area.bottom       = 30;
+               info2.keyword           = argv[2];
+               info2.string_type       = SPOOLSS_FORM_STRING_TYPE_NONE;
+               info2.mui_dll           = NULL;
+               info2.ressource_id      = 0;
+               info2.display_name      = argv[2];
+               info2.lang_id           = 0;
+
+               info.info2 = &info2;
+
+               break;
+       }
 
        /* Add the form */
 
 
        status = rpccli_spoolss_AddForm(cli, mem_ctx,
                                        &handle,
-                                       1,
+                                       level,
                                        info,
                                        &werror);
 
  done:
-       if (got_handle)
+       if (is_valid_policy_hnd(&handle))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
-       SAFE_FREE(servername);
-       SAFE_FREE(printername);
-
        return werror;
 }
 
@@ -1733,8 +1901,7 @@ static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        POLICY_HND handle;
        WERROR werror;
        NTSTATUS status;
-       char *servername = NULL, *printername = NULL;
-       bool got_handle = False;
+       const char *printername;
        union spoolss_AddFormInfo info;
        struct spoolss_AddFormInfo1 info1;
 
@@ -1744,27 +1911,18 @@ static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
                printf ("Usage: %s <printer> <formname>\n", argv[0]);
                return WERR_OK;
         }
-       
-       /* Get a printer handle */
 
-       if (asprintf(&servername, "\\\\%s", cli->desthost)) {
-               return WERR_NOMEM;
-       }
-       strupper_m(servername);
-       if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
-               SAFE_FREE(servername);
-               return WERR_NOMEM;
-       }
+       /* Get a printer handle */
 
-       werror = rpccli_spoolss_open_printer_ex(
-               cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
-               servername, cli->auth->user_name, &handle);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
+       werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &handle);
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
-
        /* Dummy up some values for the form data */
 
        info1.flags             = FORM_PRINTER;
@@ -1788,12 +1946,9 @@ static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
                                        &werror);
 
  done:
-       if (got_handle)
+       if (is_valid_policy_hnd(&handle))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
-       SAFE_FREE(servername);
-       SAFE_FREE(printername);
-
        return werror;
 }
 
@@ -1828,10 +1983,10 @@ static void display_form(FORM_1 *form)
        printf("%s\n" \
                "\tflag: %s (%d)\n" \
                "\twidth: %d, length: %d\n" \
-               "\tleft: %d, right: %d, top: %d, bottom: %d\n\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->width, form->length,
+               form->left, form->right,
                form->top, form->bottom);
 }
 
@@ -1853,64 +2008,81 @@ static void display_form_info1(struct spoolss_FormInfo1 *r)
 /****************************************************************************
 ****************************************************************************/
 
+static void display_form_info2(struct spoolss_FormInfo2 *r)
+{
+       printf("%s\n" \
+               "\tflag: %s (%d)\n" \
+               "\twidth: %d, length: %d\n" \
+               "\tleft: %d, right: %d, top: %d, bottom: %d\n",
+               r->form_name, get_form_flag(r->flags), r->flags,
+               r->size.width, r->size.height,
+               r->area.left, r->area.right,
+               r->area.top, r->area.bottom);
+       printf("\tkeyword: %s\n", r->keyword);
+       printf("\tstring_type: 0x%08x\n", r->string_type);
+       printf("\tmui_dll: %s\n", r->mui_dll);
+       printf("\tressource_id: 0x%08x\n", r->ressource_id);
+       printf("\tdisplay_name: %s\n", r->display_name);
+       printf("\tlang_id: %d\n", r->lang_id);
+       printf("\n");
+}
+
+/****************************************************************************
+****************************************************************************/
+
 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        NTSTATUS status;
-       char *servername = NULL, *printername = NULL;
-       bool got_handle = False;
+       const char *printername;
        DATA_BLOB buffer;
        uint32_t offered = 0;
        union spoolss_FormInfo info;
        uint32_t needed;
+       uint32_t level = 1;
 
        /* Parse the command arguments */
 
-       if (argc != 3) {
-               printf ("Usage: %s <printer> <formname>\n", argv[0]);
+       if (argc < 3 || argc > 5) {
+               printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
                return WERR_OK;
         }
-       
-       /* Get a printer handle */
 
-       if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
-               return WERR_NOMEM;
-       }
-       strupper_m(servername);
-       if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
-               SAFE_FREE(servername);
-               return WERR_NOMEM;
-       }
+       /* Get a printer handle */
 
-       werror = rpccli_spoolss_open_printer_ex(
-               cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
-               servername, cli->auth->user_name, &handle);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
+       werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &handle);
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
+       if (argc == 4) {
+               level = atoi(argv[3]);
+       }
 
        /* Get the form */
 
        status = rpccli_spoolss_GetForm(cli, mem_ctx,
                                        &handle,
                                        argv[2],
-                                       1,
+                                       level,
                                        NULL,
                                        offered,
                                        &info,
                                        &needed,
                                        &werror);
        if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
-               buffer = data_blob_talloc(mem_ctx, NULL, needed);
+               buffer = data_blob_talloc_zero(mem_ctx, needed);
                offered = needed;
                status = rpccli_spoolss_GetForm(cli, mem_ctx,
                                                &handle,
                                                argv[2],
-                                               1,
+                                               level,
                                                &buffer,
                                                offered,
                                                &info,
@@ -1922,57 +2094,52 @@ static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
                return werror;
        }
 
-       display_form_info1(&info.info1);
+       switch (level) {
+       case 1:
+               display_form_info1(&info.info1);
+               break;
+       case 2:
+               display_form_info2(&info.info2);
+               break;
+       }
+
  done:
-       if (got_handle)
+       if (is_valid_policy_hnd(&handle))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
-       SAFE_FREE(servername);
-       SAFE_FREE(printername);
-
        return werror;
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli, 
-                                      TALLOC_CTX *mem_ctx, int argc, 
+static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
+                                      TALLOC_CTX *mem_ctx, int argc,
                                       const char **argv)
 {
        POLICY_HND handle;
        WERROR werror;
        NTSTATUS status;
-       char *servername = NULL, *printername = NULL;
-       bool got_handle = False;
-       
+       const char *printername;
+
        /* Parse the command arguments */
 
        if (argc != 3) {
                printf ("Usage: %s <printer> <formname>\n", argv[0]);
                return WERR_OK;
         }
-       
-       /* Get a printer handle */
 
-       if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
-               return WERR_NOMEM;
-       }
-       strupper_m(servername);
-       if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
-               SAFE_FREE(servername);
-               return WERR_NOMEM;
-       }
+       /* Get a printer handle */
 
-       werror = rpccli_spoolss_open_printer_ex(
-               cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
-               servername, cli->auth->user_name, &handle);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
+       werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &handle);
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
-
        /* Delete the form */
 
        status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
@@ -1984,56 +2151,43 @@ static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
        }
 
  done:
-       if (got_handle)
+       if (is_valid_policy_hnd(&handle))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
-       SAFE_FREE(servername);
-       SAFE_FREE(printername);
-
        return werror;
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli, 
-                                      TALLOC_CTX *mem_ctx, int argc, 
+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;
-       bool got_handle = False;
+       const char *printername;
        uint32 num_forms, level = 1, i;
        FORM_1 *forms;
-       
+
        /* Parse the command arguments */
 
        if (argc != 2) {
                printf ("Usage: %s <printer>\n", argv[0]);
                return WERR_OK;
         }
-       
-       /* Get a printer handle */
 
-       if (asprintf(&servername, "\\\\%s", cli->desthost) == -1) {
-               return WERR_NOMEM;
-       }
-       strupper_m(servername);
-       if (asprintf(&printername, "%s\\%s", servername, argv[1]) == -1) {
-               SAFE_FREE(servername);
-               return WERR_NOMEM;
-       }
+       /* Get a printer handle */
 
-       werror = rpccli_spoolss_open_printer_ex(
-               cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
-               servername, cli->auth->user_name, &handle);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
+       werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &handle);
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
-
        /* Enumerate forms */
 
        werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
@@ -2050,12 +2204,9 @@ static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
        }
 
  done:
-       if (got_handle)
+       if (is_valid_policy_hnd(&handle))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
-       SAFE_FREE(servername);
-       SAFE_FREE(printername);
-
        return werror;
 }
 
@@ -2067,11 +2218,9 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                                            int argc, const char **argv)
 {
        WERROR result;
-       fstring servername, printername, user;
+       const char *printername;
        POLICY_HND pol;
-       bool opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
-       PRINTER_INFO_0 info;
+       union spoolss_PrinterInfo info;
        REGISTRY_VALUE value;
        TALLOC_CTX *tmp_ctx = talloc_stackframe();
 
@@ -2084,10 +2233,7 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                goto done;
        }
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
-       slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
-       fstrcpy(user, cli->auth->user_name);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
        value.type = REG_NONE;
 
@@ -2114,26 +2260,27 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
        }
 
        /* get a printer handle */
-       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
-                                            MAXIMUM_ALLOWED_ACCESS, servername, 
-                                            user, &pol);
+
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &pol);
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       opened_hnd = True;
-
-       ctr.printers_0 = &info;
-
-        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
-
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          0,
+                                          0,
+                                          &info);
         if (!W_ERROR_IS_OK(result))
                 goto done;
-               
+
        printf("%s\n", current_timestring(tmp_ctx, True));
-       printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
+       printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
 
        /* Set the printer data */
-       
+
        fstrcpy(value.valuename, argv[3]);
 
        switch (value.type) {
@@ -2203,25 +2350,28 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
        }
 
        result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
-               
+
        if (!W_ERROR_IS_OK(result)) {
                printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
                goto done;
        }
        printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
-       
-        result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
 
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          0,
+                                          0,
+                                          &info);
         if (!W_ERROR_IS_OK(result))
                 goto done;
-               
+
        printf("%s\n", current_timestring(tmp_ctx, True));
-       printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
+       printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
 
 done:
        /* cleanup */
        TALLOC_FREE(tmp_ctx);
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -2272,15 +2422,54 @@ static void display_job_info_2(JOB_INFO_2 *job)
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli, 
-                                     TALLOC_CTX *mem_ctx, int argc, 
+static void display_job_info1(struct spoolss_JobInfo1 *r)
+{
+       printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
+              r->user_name, r->document_name, r->text_status, r->pages_printed,
+              r->total_pages);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_job_info2(struct spoolss_JobInfo2 *r)
+{
+       printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
+              r->position, r->job_id,
+              r->user_name, r->document_name, r->text_status, r->pages_printed,
+              r->total_pages, r->size);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_job_info3(struct spoolss_JobInfo3 *r)
+{
+       printf("jobid[%d], next_jobid[%d]\n",
+               r->job_id, r->next_job_id);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_job_info4(struct spoolss_JobInfo4 *r)
+{
+       printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
+              r->position, r->job_id,
+              r->user_name, r->document_name, r->text_status, r->pages_printed,
+              r->total_pages, r->size, r->size_high);
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
+                                     TALLOC_CTX *mem_ctx, int argc,
                                      const char **argv)
 {
        WERROR result;
        uint32 level = 1, num_jobs, i;
-       bool got_hnd = False;
-       char *printername = NULL;
-       fstring servername, user;
+       const char *printername;
        POLICY_HND hnd;
        JOB_INFO_CTR ctr;
 
@@ -2294,28 +2483,15 @@ static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
 
        /* Open printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
-       fstrcpy(user, cli->auth->user_name);
-       printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
-       if (!printername) {
-               return WERR_NOMEM;
-       }
-       strupper_m(printername);
-       printername = talloc_asprintf_append(printername, "%s", argv[1]);
-       if (!printername) {
-               return WERR_NOMEM;
-       }
-
-       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
-                                            "", MAXIMUM_ALLOWED_ACCESS,
-                                            servername, user, &hnd);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &hnd);
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       got_hnd = True;
-
        /* Enumerate ports */
 
        result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
@@ -2337,26 +2513,101 @@ static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
                        break;
                }
        }
-       
+
+done:
+       if (is_valid_policy_hnd(&hnd))
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+
+       return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
+                                 TALLOC_CTX *mem_ctx, int argc,
+                                 const char **argv)
+{
+       WERROR result;
+       const char *printername;
+       struct policy_handle hnd;
+       uint32_t job_id;
+       uint32_t level = 1;
+       union spoolss_JobInfo info;
+
+       if (argc < 3 || argc > 4) {
+               printf("Usage: %s printername job_id [level]\n", argv[0]);
+               return WERR_OK;
+       }
+
+       job_id = atoi(argv[2]);
+
+       if (argc == 4) {
+               level = atoi(argv[3]);
+       }
+
+       /* Open printer handle */
+
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
+
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &hnd);
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+       /* Enumerate ports */
+
+       result = rpccli_spoolss_getjob(cli, mem_ctx,
+                                      &hnd,
+                                      job_id,
+                                      level,
+                                      0,
+                                      &info);
+
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+       switch (level) {
+       case 1:
+               display_job_info1(&info.info1);
+               break;
+       case 2:
+               display_job_info2(&info.info2);
+               break;
+       case 3:
+               display_job_info3(&info.info3);
+               break;
+       case 4:
+               display_job_info4(&info.info4);
+               break;
+       default:
+               d_printf("unknown info level %d\n", level);
+               break;
+       }
+
 done:
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd)) {
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+       }
 
        return result;
 }
 
+
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli, 
-                                      TALLOC_CTX *mem_ctx, int argc, 
+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;
-       bool got_hnd = False;
-       char *printername = NULL;
-       fstring servername, user;
+       const char *printername;
        POLICY_HND hnd;
 
        if (argc != 2) {
@@ -2366,27 +2617,14 @@ static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
 
        /* Open printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
-       fstrcpy(user, cli->auth->user_name);
-       printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
-       if (!printername) {
-               return WERR_NOMEM;
-       }
-       strupper_m(printername);
-       printername = talloc_asprintf_append(printername, "%s", argv[1]);
-       if (!printername) {
-               return WERR_NOMEM;
-       }
-
-       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
-                                            "", MAXIMUM_ALLOWED_ACCESS,
-                                            servername, user, &hnd);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &hnd);
        if (!W_ERROR_IS_OK(result))
                goto done;
-       got_hnd = True;
 
        /* Enumerate data */
 
@@ -2405,7 +2643,7 @@ static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
                result = W_ERROR(ERRsuccess);
 
 done:
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
@@ -2414,15 +2652,13 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli, 
-                                         TALLOC_CTX *mem_ctx, int argc, 
+static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
+                                         TALLOC_CTX *mem_ctx, int argc,
                                          const char **argv)
 {
        WERROR result;
        uint32 i;
-       bool got_hnd = False;
-       char *printername = NULL;
-       fstring servername, user;
+       const char *printername;
        const char *keyname = NULL;
        POLICY_HND hnd;
        REGVAL_CTR *ctr = NULL;
@@ -2436,32 +2672,18 @@ static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
 
        /* Open printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
-       fstrcpy(user, cli->auth->user_name);
-
-       printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
-       if (!printername) {
-               return WERR_NOMEM;
-       }
-       strupper_m(printername);
-       printername = talloc_asprintf_append(printername, "%s", argv[1]);
-       if (!printername) {
-               return WERR_NOMEM;
-       }
-
-       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
-                                            "", MAXIMUM_ALLOWED_ACCESS, 
-                                            servername, user, &hnd);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &hnd);
        if (!W_ERROR_IS_OK(result))
                goto done;
-       got_hnd = True;
 
        /* Enumerate subkeys */
 
-       if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) 
+       if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
                return WERR_NOMEM;
 
        result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
@@ -2476,7 +2698,7 @@ static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
        TALLOC_FREE( ctr );
 
 done:
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
@@ -2485,14 +2707,12 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli, 
-                                            TALLOC_CTX *mem_ctx, int argc, 
+static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
+                                            TALLOC_CTX *mem_ctx, int argc,
                                             const char **argv)
 {
        WERROR result;
-       bool got_hnd = False;
-       char *printername = NULL;
-       fstring servername, user;
+       const char *printername;
        const char *keyname = NULL;
        POLICY_HND hnd;
        uint16 *keylist = NULL, *curkey;
@@ -2509,29 +2729,14 @@ static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
 
        /* Open printer handle */
 
-       slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
-       fstrcpy(user, cli->auth->user_name);
-
-       printername = talloc_asprintf(mem_ctx, "\\\\%s\\", cli->desthost);
-       if (!printername) {
-               return WERR_NOMEM;
-       }
-       strupper_m(printername);
-       printername = talloc_asprintf_append(printername, "%s", argv[1]);
-       if (!printername) {
-               return WERR_NOMEM;
-       }
-
-
-       result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
-                                            "", MAXIMUM_ALLOWED_ACCESS, 
-                                            servername, user, &hnd);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &hnd);
        if (!W_ERROR_IS_OK(result))
                goto done;
-        
-       got_hnd = True;
 
        /* Enumerate subkeys */
 
@@ -2556,7 +2761,7 @@ done:
 
        SAFE_FREE(keylist);
 
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
@@ -2565,15 +2770,16 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli, 
-                                    TALLOC_CTX *mem_ctx, int argc, 
+static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
+                                    TALLOC_CTX *mem_ctx, int argc,
                                     const char **argv)
 {
-       fstring servername, printername;
+       const char *printername;
+       const char *clientname;
        POLICY_HND hnd;
-       bool got_hnd = False;
        WERROR result;
-       SPOOL_NOTIFY_OPTION option;
+       NTSTATUS status;
+       struct spoolss_NotifyOption option;
 
        if (argc != 2) {
                printf("Usage: %s printername\n", argv[0]);
@@ -2583,65 +2789,69 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
 
        /* Open printer */
 
-       slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost);
-       strupper_m(servername);
-
-       slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s",
-                cli->desthost, argv[1]);
-       strupper_m(printername);
-
-       result = rpccli_spoolss_open_printer_ex(
-               cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
-               servername, cli->auth->user_name, &hnd);
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &hnd);
        if (!W_ERROR_IS_OK(result)) {
                printf("Error opening %s\n", argv[1]);
                goto done;
        }
 
-       got_hnd = True;
-
        /* Create spool options */
 
-       ZERO_STRUCT(option);
-
        option.version = 2;
-       option.option_type_ptr = 1;
-       option.count = option.ctr.count = 2;
+       option.count = 2;
 
-       option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
-       if (option.ctr.type == NULL) {
+       option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
+       if (option.types == NULL) {
                result = WERR_NOMEM;
                goto done;
        }
 
-       ZERO_STRUCT(option.ctr.type[0]);
-       option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
-       option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
-       option.ctr.type[0].fields_ptr = 1;
-       option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
-
-       ZERO_STRUCT(option.ctr.type[1]);
-       option.ctr.type[1].type = JOB_NOTIFY_TYPE;
-       option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
-       option.ctr.type[1].fields_ptr = 1;
-       option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
+       option.types[0].type = PRINTER_NOTIFY_TYPE;
+       option.types[0].count = 1;
+       option.types[0].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
+       if (option.types[0].fields == NULL) {
+               result = WERR_NOMEM;
+               goto done;
+       }
+       option.types[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
 
-       /* Send rffpcnex */
+       option.types[1].type = JOB_NOTIFY_TYPE;
+       option.types[1].count = 1;
+       option.types[1].fields = talloc_array(mem_ctx, enum spoolss_Field, 1);
+       if (option.types[1].fields == NULL) {
+               result = WERR_NOMEM;
+               goto done;
+       }
+       option.types[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
 
-       slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
-       strupper_m(servername);
+       clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
+       if (!clientname) {
+               result = WERR_NOMEM;
+               goto done;
+       }
 
-       result = rpccli_spoolss_rffpcnex(
-               cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
+       /* Send rffpcnex */
 
+       status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
+                                                                    &hnd,
+                                                                    0,
+                                                                    0,
+                                                                    clientname,
+                                                                    123,
+                                                                    &option,
+                                                                    &result);
        if (!W_ERROR_IS_OK(result)) {
                printf("Error rffpcnex %s\n", argv[1]);
                goto done;
        }
 
-done:          
-       if (got_hnd)
+done:
+       if (is_valid_policy_hnd(&hnd))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
@@ -2653,12 +2863,16 @@ done:
 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;
+       union spoolss_PrinterInfo info1, info2;
        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);
+       werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
+                                          hnd1,
+                                          2,
+                                          0,
+                                          &info1);
        if ( !W_ERROR_IS_OK(werror) ) {
                printf("failed (%s)\n", win_errstr(werror));
                talloc_destroy(mem_ctx);
@@ -2667,7 +2881,11 @@ static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
        printf("ok\n");
 
        printf("Retrieving printer properties for %s...", cli2->desthost);
-       werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
+       werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
+                                          hnd2,
+                                          2,
+                                          0,
+                                          &info2);
        if ( !W_ERROR_IS_OK(werror) ) {
                printf("failed (%s)\n", win_errstr(werror));
                talloc_destroy(mem_ctx);
@@ -2686,7 +2904,7 @@ static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
 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;
+       union spoolss_PrinterInfo info1, info2;
        WERROR werror;
        TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
        SEC_DESC *sd1, *sd2;
@@ -2694,7 +2912,11 @@ static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *h
 
 
        printf("Retrieving printer security for %s...", cli1->desthost);
-       werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
+       werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
+                                          hnd1,
+                                          3,
+                                          0,
+                                          &info1);
        if ( !W_ERROR_IS_OK(werror) ) {
                printf("failed (%s)\n", win_errstr(werror));
                result = False;
@@ -2703,40 +2925,38 @@ static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *h
        printf("ok\n");
 
        printf("Retrieving printer security for %s...", cli2->desthost);
-       werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
+       werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
+                                          hnd2,
+                                          3,
+                                          0,
+                                          &info2);
        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;
-       
+       sd1 = info1.info3.secdesc;
+       sd2 = info2.info3.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;
@@ -2748,13 +2968,12 @@ done:
 
 extern struct user_auth_info *rpcclient_auth_info;
 
-static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli, 
-                                    TALLOC_CTX *mem_ctx, int argc, 
+static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
+                                    TALLOC_CTX *mem_ctx, int argc,
                                     const char **argv)
 {
-       fstring printername, servername1, servername2;
+       const char *printername;
        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;
@@ -2766,16 +2985,11 @@ static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
                return WERR_OK;
        }
 
-       fstrcpy( printername, argv[1] );
-
-       fstrcpy( servername1, cli->desthost );
-       fstrcpy( servername2, argv[2] );
-       strupper_m( servername1 );
-       strupper_m( servername2 );
+       printername = argv[1];
 
        /* first get the connection to the remote server */
 
-       nt_status = cli_full_connection(&cli_server2, global_myname(), servername2, 
+       nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
                                        NULL, 0,
                                        "IPC$", "IPC",
                                        get_cmdline_auth_info_username(rpcclient_auth_info),
@@ -2791,38 +3005,33 @@ static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
                                             &cli2);
        if (!NT_STATUS_IS_OK(nt_status)) {
                printf("failed to open spoolss pipe on server %s (%s)\n",
-                       servername2, nt_errstr(nt_status));
+                       argv[2], 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;
-       }
+       RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
+
        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);
+
+       werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername_path,
+                                              PRINTER_ALL_ACCESS,
+                                              &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;
-       }
+       RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
+
        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 );
+       werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
+                                              printername_path,
+                                              PRINTER_ALL_ACCESS,
+                                              &hPrinter2);
        if ( !W_ERROR_IS_OK(werror) ) {
                 printf("failed (%s)\n", win_errstr(werror));
                goto done;
@@ -2863,6 +3072,7 @@ struct cmd_set spoolss_commands[] = {
        { "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",                "" },
+       { "getjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job,            &syntax_spoolss, NULL, "Get print job",                       "" },
        { "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",                  "" },