s3-rpcclient: add createprinteric command.
[ira/wip.git] / source3 / rpcclient / cmd_spoolss.c
index b6e8f7dd9748f284e14f11d165d2597c44614b5e..48f9df3cacf71ef98cf80c9586a33fce67cc6d2c 100644 (file)
@@ -6,6 +6,7 @@
    Copyright (C) Tim Potter                        2000
    Copyright (C) Andrew Tridgell              1992-1999
    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
+   Copyright (C) Guenther Deschner                 2009
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
        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
@@ -44,7 +39,7 @@ struct table_node {
    enumdriver calls for the same arch */
 
 
-static const struct table_node archi_table[]= {
+static const struct print_architecture_table_node archi_table[]= {
 
        {"Windows 4.0",          "WIN40",       0 },
        {"Windows NT x86",       "W32X86",      2 },
@@ -104,7 +99,7 @@ static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
                                             int argc, const char **argv)
 {
        WERROR          werror;
-       POLICY_HND      hnd;
+       struct policy_handle    hnd;
 
        if (argc != 2) {
                printf("Usage: %s <printername>\n", argv[0]);
@@ -137,57 +132,45 @@ static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static void display_print_info_0(PRINTER_INFO_0 *i0)
+static void display_print_info0(struct spoolss_PrinterInfo0 *r)
 {
-       fstring name = "";
-       fstring servername = "";
-
-       if (!i0)
+       if (!r)
                return;
 
-       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,
-              i0->day, i0->dayofweek);
-       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);
-       printf("\tsession_counter:[0x%x]\n", i0->session_counter);
-       printf("\tunknown11:[0x%x]\n", i0->unknown11);
-       printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
-       printf("\tunknown13:[0x%x]\n", i0->unknown13);
-       printf("\tunknown14:[0x%x]\n", i0->unknown14);
-       printf("\tunknown15:[0x%x]\n", i0->unknown15);
-       printf("\tunknown16:[0x%x]\n", i0->unknown16);
-       printf("\tchange_id:[0x%x]\n", i0->change_id);
-       printf("\tunknown18:[0x%x]\n", i0->unknown18);
-       printf("\tstatus:[0x%x]\n", i0->status);
-       printf("\tunknown20:[0x%x]\n", i0->unknown20);
-       printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
-       printf("\tunknown22:[0x%x]\n", i0->unknown22);
-       printf("\tunknown23:[0x%x]\n", i0->unknown23);
-       printf("\tunknown24:[0x%x]\n", i0->unknown24);
-       printf("\tunknown25:[0x%x]\n", i0->unknown25);
-       printf("\tunknown26:[0x%x]\n", i0->unknown26);
-       printf("\tunknown27:[0x%x]\n", i0->unknown27);
-       printf("\tunknown28:[0x%x]\n", i0->unknown28);
-       printf("\tunknown29:[0x%x]\n", i0->unknown29);
+       printf("\tprintername:[%s]\n", r->printername);
+       printf("\tservername:[%s]\n", r->servername);
+       printf("\tcjobs:[0x%x]\n", r->cjobs);
+       printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
+       printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
+       printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
+              r->time.day, r->time.day_of_week);
+       printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
+              r->time.second, r->time.millisecond);
+
+       printf("\tglobal_counter:[0x%x]\n", r->global_counter);
+       printf("\ttotal_pages:[0x%x]\n", r->total_pages);
+
+       printf("\tversion:[0x%x]\n", r->version);
+       printf("\tfree_build:[0x%x]\n", r->free_build);
+       printf("\tspooling:[0x%x]\n", r->spooling);
+       printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
+       printf("\tsession_counter:[0x%x]\n", r->session_counter);
+       printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
+       printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
+       printf("\tjob_error:[0x%x]\n", r->job_error);
+       printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
+       printf("\tprocessor_type:[0x%x]\n", r->processor_type);
+       printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
+       printf("\tchange_id:[0x%x]\n", r->change_id);
+       printf("\tlast_error: %s\n", win_errstr(r->last_error));
+       printf("\tstatus:[0x%x]\n", r->status);
+       printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
+       printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
+       printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
+       printf("\tprocessor_level:[0x%x]\n", r->processor_level);
+       printf("\tref_ic:[0x%x]\n", r->ref_ic);
+       printf("\treserved2:[0x%x]\n", r->reserved2);
+       printf("\treserved3:[0x%x]\n", r->reserved3);
 
        printf("\n");
 }
@@ -195,22 +178,43 @@ static void display_print_info_0(PRINTER_INFO_0 *i0)
 /****************************************************************************
 ****************************************************************************/
 
-static void display_print_info_1(PRINTER_INFO_1 *i1)
+static void display_print_info1(struct spoolss_PrinterInfo1 *r)
 {
-       fstring desc = "";
-       fstring name = "";
-       fstring comm = "";
+       printf("\tflags:[0x%x]\n", r->flags);
+       printf("\tname:[%s]\n", r->name);
+       printf("\tdescription:[%s]\n", r->description);
+       printf("\tcomment:[%s]\n", r->comment);
 
-       rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
-                   STR_TERMINATE);
+       printf("\n");
+}
 
-       rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
-       rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
+/****************************************************************************
+****************************************************************************/
 
-       printf("\tflags:[0x%x]\n", i1->flags);
-       printf("\tname:[%s]\n", name);
-       printf("\tdescription:[%s]\n", desc);
-       printf("\tcomment:[%s]\n", comm);
+static void display_print_info2(struct spoolss_PrinterInfo2 *r)
+{
+       printf("\tservername:[%s]\n", r->servername);
+       printf("\tprintername:[%s]\n", r->printername);
+       printf("\tsharename:[%s]\n", r->sharename);
+       printf("\tportname:[%s]\n", r->portname);
+       printf("\tdrivername:[%s]\n", r->drivername);
+       printf("\tcomment:[%s]\n", r->comment);
+       printf("\tlocation:[%s]\n", r->location);
+       printf("\tsepfile:[%s]\n", r->sepfile);
+       printf("\tprintprocessor:[%s]\n", r->printprocessor);
+       printf("\tdatatype:[%s]\n", r->datatype);
+       printf("\tparameters:[%s]\n", r->parameters);
+       printf("\tattributes:[0x%x]\n", r->attributes);
+       printf("\tpriority:[0x%x]\n", r->priority);
+       printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
+       printf("\tstarttime:[0x%x]\n", r->starttime);
+       printf("\tuntiltime:[0x%x]\n", r->untiltime);
+       printf("\tstatus:[0x%x]\n", r->status);
+       printf("\tcjobs:[0x%x]\n", r->cjobs);
+       printf("\taverageppm:[0x%x]\n", r->averageppm);
+
+       if (r->secdesc)
+               display_sec_desc(r->secdesc);
 
        printf("\n");
 }
@@ -218,54 +222,9 @@ static void display_print_info_1(PRINTER_INFO_1 *i1)
 /****************************************************************************
 ****************************************************************************/
 
-static void display_print_info_2(PRINTER_INFO_2 *i2)
-{
-       fstring servername = "";
-       fstring printername = "";
-       fstring sharename = "";
-       fstring portname = "";
-       fstring drivername = "";
-       fstring comment = "";
-       fstring location = "";
-       fstring sepfile = "";
-       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);
-       rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
-       rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
-       rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
-       rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
-       rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
-       rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
-       rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
-       rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
-
-       printf("\tservername:[%s]\n", servername);
-       printf("\tprintername:[%s]\n", printername);
-       printf("\tsharename:[%s]\n", sharename);
-       printf("\tportname:[%s]\n", portname);
-       printf("\tdrivername:[%s]\n", drivername);
-       printf("\tcomment:[%s]\n", comment);
-       printf("\tlocation:[%s]\n", location);
-       printf("\tsepfile:[%s]\n", sepfile);
-       printf("\tprintprocessor:[%s]\n", printprocessor);
-       printf("\tdatatype:[%s]\n", datatype);
-       printf("\tparameters:[%s]\n", parameters);
-       printf("\tattributes:[0x%x]\n", i2->attributes);
-       printf("\tpriority:[0x%x]\n", i2->priority);
-       printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
-       printf("\tstarttime:[0x%x]\n", i2->starttime);
-       printf("\tuntiltime:[0x%x]\n", i2->untiltime);
-       printf("\tstatus:[0x%x]\n", i2->status);
-       printf("\tcjobs:[0x%x]\n", i2->cjobs);
-       printf("\taverageppm:[0x%x]\n", i2->averageppm);
-
-       if (i2->secdesc)
-               display_sec_desc(i2->secdesc);
+static void display_print_info3(struct spoolss_PrinterInfo3 *r)
+{
+       display_sec_desc(r->secdesc);
 
        printf("\n");
 }
@@ -273,87 +232,123 @@ static void display_print_info_2(PRINTER_INFO_2 *i2)
 /****************************************************************************
 ****************************************************************************/
 
-static void display_print_info_3(PRINTER_INFO_3 *i3)
+static void display_print_info4(struct spoolss_PrinterInfo4 *r)
 {
-       display_sec_desc(i3->secdesc);
+       printf("\tservername:[%s]\n", r->servername);
+       printf("\tprintername:[%s]\n", r->printername);
+       printf("\tattributes:[0x%x]\n", r->attributes);
+       printf("\n");
+}
+
+/****************************************************************************
+****************************************************************************/
 
+static void display_print_info5(struct spoolss_PrinterInfo5 *r)
+{
+       printf("\tprintername:[%s]\n", r->printername);
+       printf("\tportname:[%s]\n", r->portname);
+       printf("\tattributes:[0x%x]\n", r->attributes);
+       printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
+       printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
        printf("\n");
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static void display_print_info_7(PRINTER_INFO_7 *i7)
+static void display_print_info6(struct spoolss_PrinterInfo6 *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("\tstatus:[0x%x]\n", r->status);
+       printf("\n");
 }
 
+/****************************************************************************
+****************************************************************************/
+
+static void display_print_info7(struct spoolss_PrinterInfo7 *r)
+{
+       printf("\tguid:[%s]\n", r->guid);
+       printf("\taction:[0x%x]\n", r->action);
+       printf("\n");
+}
 
 /****************************************************************************
 ****************************************************************************/
 
 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
-                                          TALLOC_CTX *mem_ctx,
-                                          int argc, const char **argv)
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc, const char **argv)
 {
        WERROR                  result;
-       uint32                  info_level = 1;
-       PRINTER_INFO_CTR        ctr;
-       uint32                  i = 0, num_printers;
-       fstring name;
-
-       if (argc > 3)
-       {
-               printf("Usage: %s [level] [name]\n", argv[0]);
+       uint32_t                level = 1;
+       union spoolss_PrinterInfo *info;
+       uint32_t                i, count;
+       const char *name;
+       uint32_t flags = PRINTER_ENUM_LOCAL;
+
+       if (argc > 4) {
+               printf("Usage: %s [level] [name] [flags]\n", argv[0]);
                return WERR_OK;
        }
 
-       if (argc >= 2)
-               info_level = atoi(argv[1]);
-
-       if (argc == 3)
-               fstrcpy(name, argv[2]);
-       else {
-               slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost);
-               strupper_m(name);
+       if (argc >= 2) {
+               level = atoi(argv[1]);
        }
 
-       ZERO_STRUCT(ctr);
+       if (argc >= 3) {
+               name = argv[2];
+       } else {
+               name = cli->srv_name_slash;
+       }
 
-       result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL,
-               info_level, &num_printers, &ctr);
+       if (argc == 4) {
+               flags = atoi(argv[3]);
+       }
 
+       result = rpccli_spoolss_enumprinters(cli, mem_ctx,
+                                            flags,
+                                            name,
+                                            level,
+                                            0,
+                                            &count,
+                                            &info);
        if (W_ERROR_IS_OK(result)) {
 
-               if (!num_printers) {
+               if (!count) {
                        printf ("No printers returned.\n");
                        goto done;
                }
 
-               for (i = 0; i < num_printers; i++) {
-                       switch(info_level) {
+               for (i = 0; i < count; i++) {
+                       switch (level) {
                        case 0:
-                               display_print_info_0(&ctr.printers_0[i]);
+                               display_print_info0(&info[i].info0);
                                break;
                        case 1:
-                               display_print_info_1(&ctr.printers_1[i]);
+                               display_print_info1(&info[i].info1);
                                break;
                        case 2:
-                               display_print_info_2(&ctr.printers_2[i]);
+                               display_print_info2(&info[i].info2);
                                break;
                        case 3:
-                               display_print_info_3(&ctr.printers_3[i]);
+                               display_print_info3(&info[i].info3);
+                               break;
+                       case 4:
+                               display_print_info4(&info[i].info4);
+                               break;
+                       case 5:
+                               display_print_info5(&info[i].info5);
+                               break;
+                       case 6:
+                               display_print_info6(&info[i].info6);
                                break;
                        default:
-                               printf("unknown info level %d\n", info_level);
+                               printf("unknown info level %d\n", level);
                                goto done;
                        }
                }
        }
      done:
+ done:
 
        return result;
 }
@@ -361,55 +356,45 @@ static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static void display_port_info_1(PORT_INFO_1 *i1)
+static void display_port_info_1(struct spoolss_PortInfo1 *r)
 {
-       fstring buffer;
-
-       rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
-       printf("\tPort Name:\t[%s]\n", buffer);
+       printf("\tPort Name:\t[%s]\n", r->port_name);
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static void display_port_info_2(PORT_INFO_2 *i2)
+static void display_port_info_2(struct spoolss_PortInfo2 *r)
 {
-       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);
-
-       printf("\tMonitor Name:\t[%s]\n", buffer);
-       rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
-
-       printf("\tDescription:\t[%s]\n", buffer);
+       printf("\tPort Name:\t[%s]\n", r->port_name);
+       printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
+       printf("\tDescription:\t[%s]\n", r->description);
        printf("\tPort Type:\t" );
-       if ( i2->port_type ) {
+       if (r->port_type) {
                int comma = 0; /* hack */
                printf( "[" );
-               if ( i2->port_type & PORT_TYPE_READ ) {
+               if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
                        printf( "Read" );
                        comma = 1;
                }
-               if ( i2->port_type & PORT_TYPE_WRITE ) {
+               if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
                        printf( "%sWrite", comma ? ", " : "" );
                        comma = 1;
                }
                /* These two have slightly different interpretations
                 on 95/98/ME but I'm disregarding that for now */
-               if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
+               if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
                        printf( "%sRedirected", comma ? ", " : "" );
                        comma = 1;
                }
-               if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
+               if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
                        printf( "%sNet-Attached", comma ? ", " : "" );
                }
                printf( "]\n" );
        } else {
                printf( "[Unset]\n" );
        }
-       printf("\tReserved:\t[%d]\n", i2->reserved);
+       printf("\tReserved:\t[%d]\n", r->reserved);
        printf("\n");
 }
 
@@ -421,37 +406,40 @@ static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
                                       const char **argv)
 {
        WERROR                  result;
-       uint32                  info_level = 1;
-       PORT_INFO_CTR           ctr;
-       uint32                  returned;
+       uint32_t                level = 1;
+       uint32_t                count;
+       union spoolss_PortInfo *info;
 
        if (argc > 2) {
                printf("Usage: %s [level]\n", argv[0]);
                return WERR_OK;
        }
 
-       if (argc == 2)
-               info_level = atoi(argv[1]);
+       if (argc == 2) {
+               level = atoi(argv[1]);
+       }
 
        /* Enumerate ports */
 
-       ZERO_STRUCT(ctr);
-
-       result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
-
+       result = rpccli_spoolss_enumports(cli, mem_ctx,
+                                         cli->srv_name_slash,
+                                         level,
+                                         0,
+                                         &count,
+                                         &info);
        if (W_ERROR_IS_OK(result)) {
                int i;
 
-               for (i = 0; i < returned; i++) {
-                       switch (info_level) {
+               for (i = 0; i < count; i++) {
+                       switch (level) {
                        case 1:
-                               display_port_info_1(&ctr.port.info_1[i]);
+                               display_port_info_1(&info[i].info1);
                                break;
                        case 2:
-                               display_port_info_2(&ctr.port.info_2[i]);
+                               display_port_info_2(&info[i].info2);
                                break;
                        default:
-                               printf("unknown info level %d\n", info_level);
+                               printf("unknown info level %d\n", level);
                                break;
                        }
                }
@@ -467,12 +455,15 @@ static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv)
 {
-       POLICY_HND      pol;
+       struct policy_handle pol;
        WERROR          result;
-       uint32          info_level = 2;
-       bool            opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
+       NTSTATUS        status;
+       uint32_t        info_level = 2;
+       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,6 +476,9 @@ static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
                comment = argv[2];
        }
 
+       ZERO_STRUCT(devmode_ctr);
+       ZERO_STRUCT(secdesc_ctr);
+
        RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
        /* get a printer handle */
@@ -495,26 +489,36 @@ static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
        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;
+       info.info2.comment = comment;
+       info.info2.secdesc = NULL;
+       info.info2.devmode = NULL;
 
-       result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
+       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;
@@ -527,13 +531,19 @@ static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv)
 {
-       POLICY_HND      pol;
+       struct policy_handle pol;
        WERROR          result;
-       uint32          info_level = 2;
-       bool            opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
+       NTSTATUS        status;
+       uint32_t        info_level = 2;
+       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]);
@@ -556,25 +566,35 @@ static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
        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;
@@ -587,12 +607,11 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
                                        TALLOC_CTX *mem_ctx,
                                        int argc, const char **argv)
 {
-       POLICY_HND      pol;
+       struct policy_handle pol;
        WERROR          result;
-       uint32          info_level = 1;
-       bool            opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
+       uint32_t        level = 1;
        const char      *printername;
+       union spoolss_PrinterInfo info;
 
        if (argc == 1 || argc > 3) {
                printf("Usage: %s <printername> [level]\n", argv[0]);
@@ -601,7 +620,7 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
 
        /* Open a printer handle */
        if (argc == 3) {
-               info_level = atoi(argv[2]);
+               level = atoi(argv[2]);
        }
 
        RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
@@ -612,44 +631,55 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
                                               printername,
                                               SEC_FLAG_MAXIMUM_ALLOWED,
                                               &pol);
-       if (!W_ERROR_IS_OK(result))
+       if (!W_ERROR_IS_OK(result)) {
                goto done;
-
-       opened_hnd = True;
+       }
 
        /* Get printer info */
 
-       result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
-
-       if (!W_ERROR_IS_OK(result))
+       result = rpccli_spoolss_getprinter(cli, mem_ctx,
+                                          &pol,
+                                          level,
+                                          0,
+                                          &info);
+       if (!W_ERROR_IS_OK(result)) {
                goto done;
+       }
 
        /* Display printer info */
-
-       switch (info_level) {
+       switch (level) {
        case 0:
-               display_print_info_0(ctr.printers_0);
+               display_print_info0(&info.info0);
                break;
        case 1:
-               display_print_info_1(ctr.printers_1);
+               display_print_info1(&info.info1);
                break;
        case 2:
-               display_print_info_2(ctr.printers_2);
+               display_print_info2(&info.info2);
                break;
        case 3:
-               display_print_info_3(ctr.printers_3);
+               display_print_info3(&info.info3);
+               break;
+       case 4:
+               display_print_info4(&info.info4);
+               break;
+       case 5:
+               display_print_info5(&info.info5);
+               break;
+       case 6:
+               display_print_info6(&info.info6);
                break;
        case 7:
-               display_print_info_7(ctr.printers_7);
+               display_print_info7(&info.info7);
                break;
        default:
-               printf("unknown info level %d\n", info_level);
+               printf("unknown info level %d\n", level);
                break;
        }
-
  done:
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol)) {
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
+       }
 
        return result;
 }
@@ -657,14 +687,14 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static void display_reg_value(REGISTRY_VALUE value)
+static void display_reg_value(struct regval_blob value)
 {
        char *text = NULL;
 
        switch(value.type) {
        case REG_DWORD:
                printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
-                      *((uint32 *) value.data_p));
+                      *((uint32_t *) value.data_p));
                break;
        case REG_SZ:
                rpcstr_pull_talloc(talloc_tos(),
@@ -693,7 +723,7 @@ static void display_reg_value(REGISTRY_VALUE value)
                break;
        }
        case REG_MULTI_SZ: {
-               uint32 i, num_values;
+               uint32_t i, num_values;
                char **values;
 
                if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
@@ -703,6 +733,7 @@ static void display_reg_value(REGISTRY_VALUE value)
                        break;
                }
 
+               printf("%s: REG_MULTI_SZ: \n", value.valuename);
                for (i=0; i<num_values; i++) {
                        d_printf("%s\n", values[i]);
                }
@@ -718,16 +749,64 @@ static void display_reg_value(REGISTRY_VALUE value)
 /****************************************************************************
 ****************************************************************************/
 
+static void display_printer_data(const char *v,
+                                enum winreg_Type type,
+                                union spoolss_PrinterData *r)
+{
+       int i;
+
+       switch (type) {
+       case REG_DWORD:
+               printf("%s: REG_DWORD: 0x%08x\n", v, r->value);
+               break;
+       case REG_SZ:
+               printf("%s: REG_SZ: %s\n", v, r->string);
+               break;
+       case REG_BINARY: {
+               char *hex = hex_encode_talloc(NULL,
+                       r->binary.data, r->binary.length);
+               size_t len;
+               printf("%s: REG_BINARY:", v);
+               len = strlen(hex);
+               for (i=0; i<len; i++) {
+                       if (hex[i] == '\0') {
+                               break;
+                       }
+                       if (i%40 == 0) {
+                               putchar('\n');
+                       }
+                       putchar(hex[i]);
+               }
+               TALLOC_FREE(hex);
+               putchar('\n');
+               break;
+       }
+       case REG_MULTI_SZ:
+               printf("%s: REG_MULTI_SZ: ", v);
+               for (i=0; r->string_array[i] != NULL; i++) {
+                       printf("%s ", r->string_array[i]);
+               }
+               printf("\n");
+               break;
+       default:
+               printf("%s: unknown type 0x%02x:\n", v, type);
+               break;
+       }
+}
+
+/****************************************************************************
+****************************************************************************/
+
 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
                                           TALLOC_CTX *mem_ctx,
                                           int argc, const char **argv)
 {
-       POLICY_HND      pol;
+       struct policy_handle pol;
        WERROR          result;
-       bool            opened_hnd = False;
        fstring         printername;
        const char *valuename;
-       REGISTRY_VALUE value;
+       enum winreg_Type type;
+       union spoolss_PrinterData data;
 
        if (argc != 3) {
                printf("Usage: %s <printername> <valuename>\n", argv[0]);
@@ -753,23 +832,23 @@ static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       opened_hnd = True;
-
        /* Get printer info */
 
-       result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
-
+       result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
+                                              &pol,
+                                              valuename,
+                                              0,
+                                              &type,
+                                              &data);
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        /* Display printer data */
 
-       fstrcpy(value.valuename, valuename);
-       display_reg_value(value);
-
+       display_printer_data(valuename, type, &data);
 
  done:
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -782,15 +861,14 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
                                             TALLOC_CTX *mem_ctx,
                                             int argc, const char **argv)
 {
-       POLICY_HND      pol;
+       struct policy_handle pol;
        WERROR          result;
        NTSTATUS        status;
-       bool            opened_hnd = False;
        fstring         printername;
        const char *valuename, *keyname;
-       REGISTRY_VALUE value;
+       struct regval_blob value;
 
-       uint32_t type;
+       enum winreg_Type type;
        uint8_t *buffer = NULL;
        uint32_t offered = 0;
        uint32_t needed;
@@ -821,8 +899,6 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       opened_hnd = True;
-
        /* Get printer info */
 
        status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
@@ -870,7 +946,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
        display_reg_value(value);
 
  done:
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
 
        return result;
@@ -879,131 +955,232 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static void display_print_driver_1(DRIVER_INFO_1 *i1)
+static void display_print_driver1(struct spoolss_DriverInfo1 *r)
 {
-       fstring name;
-       if (i1 == NULL)
+       if (!r) {
                return;
+       }
+
+       printf("Printer Driver Info 1:\n");
+       printf("\tDriver Name: [%s]\n", r->driver_name);
+       printf("\n");
+}
 
-       rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
+/****************************************************************************
+****************************************************************************/
 
-       printf ("Printer Driver Info 1:\n");
-       printf ("\tDriver Name: [%s]\n\n", name);
+static void display_print_driver2(struct spoolss_DriverInfo2 *r)
+{
+       if (!r) {
+               return;
+       }
 
-       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", r->config_file);
+       printf("\n");
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static void display_print_driver_2(DRIVER_INFO_2 *i1)
+static void display_print_driver3(struct spoolss_DriverInfo3 *r)
 {
-       fstring name;
-       fstring architecture;
-       fstring driverpath;
-       fstring datafile;
-       fstring configfile;
-       if (i1 == NULL)
+       int i;
+
+       if (!r) {
                return;
+       }
 
-       rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
-       rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
-       rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
-       rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
-       rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
+       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", r->config_file);
+       printf("\tHelpfile: [%s]\n", r->help_file);
 
-       printf ("Printer Driver Info 2:\n");
-       printf ("\tVersion: [%x]\n", i1->version);
-       printf ("\tDriver Name: [%s]\n", name);
-       printf ("\tArchitecture: [%s]\n", architecture);
-       printf ("\tDriver Path: [%s]\n", driverpath);
-       printf ("\tDatafile: [%s]\n", datafile);
-       printf ("\tConfigfile: [%s]\n\n", configfile);
+       for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
+               printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
+       }
 
-       return;
+       printf("\tMonitorname: [%s]\n", r->monitor_name);
+       printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
+       printf("\n");
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_print_driver4(struct spoolss_DriverInfo4 *r)
+{
+       int i;
+
+       if (!r) {
+               return;
+       }
+
+       printf("Printer Driver Info 4:\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", r->config_file);
+       printf("\tHelpfile: [%s]\n", r->help_file);
+
+       for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
+               printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
+       }
+
+       printf("\tMonitorname: [%s]\n", r->monitor_name);
+       printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
+
+       for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
+               printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
+       }
+       printf("\n");
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static void display_print_driver_3(DRIVER_INFO_3 *i1)
+static void display_print_driver5(struct spoolss_DriverInfo5 *r)
 {
-       fstring name = "";
-       fstring architecture = "";
-       fstring driverpath = "";
-       fstring datafile = "";
-       fstring configfile = "";
-       fstring helpfile = "";
-       fstring dependentfiles = "";
-       fstring monitorname = "";
-       fstring defaultdatatype = "";
+       if (!r) {
+               return;
+       }
 
-       int length=0;
-       bool valid = True;
+       printf("Printer Driver Info 5:\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", r->config_file);
+       printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
+       printf("\tConfig Version: [0x%x]\n", r->config_version);
+       printf("\tDriver Version: [0x%x]\n", r->driver_version);
+       printf("\n");
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static void display_print_driver6(struct spoolss_DriverInfo6 *r)
+{
+       int i;
 
-       if (i1 == NULL)
+       if (!r) {
                return;
+       }
 
-       rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
-       rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
-       rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
-       rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
-       rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
-       rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
-       rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
-       rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
-
-       printf ("Printer Driver Info 3:\n");
-       printf ("\tVersion: [%x]\n", i1->version);
-       printf ("\tDriver Name: [%s]\n",name);
-       printf ("\tArchitecture: [%s]\n", architecture);
-       printf ("\tDriver Path: [%s]\n", driverpath);
-       printf ("\tDatafile: [%s]\n", datafile);
-       printf ("\tConfigfile: [%s]\n", configfile);
-       printf ("\tHelpfile: [%s]\n\n", helpfile);
-
-       while (valid)
-       {
-               rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
+       printf("Printer Driver Info 6:\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", r->config_file);
+       printf("\tHelpfile: [%s]\n", r->help_file);
 
-               length+=strlen(dependentfiles)+1;
+       for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
+               printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
+       }
 
-               if (strlen(dependentfiles) > 0)
-               {
-                       printf ("\tDependentfiles: [%s]\n", dependentfiles);
-               }
-               else
-               {
-                       valid = False;
-               }
+       printf("\tMonitorname: [%s]\n", r->monitor_name);
+       printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
+
+       for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
+               printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
        }
 
-       printf ("\n");
+       printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
+       printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
+       printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
+       printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
+       printf("\tHardware ID: [%s]\n", r->hardware_id);
+       printf("\tProvider: [%s]\n", r->provider);
 
-       printf ("\tMonitorname: [%s]\n", monitorname);
-       printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
+       printf("\n");
+}
 
-       return;
+/****************************************************************************
+****************************************************************************/
+
+static void display_print_driver8(struct spoolss_DriverInfo8 *r)
+{
+       int i;
+
+       if (!r) {
+               return;
+       }
+
+       printf("Printer Driver Info 8:\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", r->config_file);
+       printf("\tHelpfile: [%s]\n", r->help_file);
+       printf("\tMonitorname: [%s]\n", r->monitor_name);
+       printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
+
+       for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
+               printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
+       }
+
+       for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
+               printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
+       }
+
+       printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
+       printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
+       printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
+       printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
+       printf("\tHardware ID: [%s]\n", r->hardware_id);
+       printf("\tProvider: [%s]\n", r->provider);
+       printf("\tPrint Processor: [%s]\n", r->print_processor);
+       printf("\tVendor Setup: [%s]\n", r->vendor_setup);
+       for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
+               printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
+       }
+       printf("\tInf Path: [%s]\n", r->inf_path);
+       printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
+       for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
+               printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
+       }
+       printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
+       printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
+               (long long unsigned int)r->min_inbox_driver_ver_version);
+
+       printf("\n");
 }
 
 /****************************************************************************
 ****************************************************************************/
 
 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
-                                      TALLOC_CTX *mem_ctx,
-                                      int argc, const char **argv)
+                                   TALLOC_CTX *mem_ctx,
+                                   int argc, const char **argv)
 {
-       POLICY_HND      pol;
+       struct policy_handle pol;
        WERROR          werror;
-       uint32          info_level = 3;
-       bool            opened_hnd = False;
-       PRINTER_DRIVER_CTR      ctr;
+       uint32_t        level = 3;
        const char      *printername;
-       uint32          i;
-       bool            success = False;
+       uint32_t        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;
        }
@@ -1012,8 +1189,9 @@ static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
 
        RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
-       if (argc == 3)
-               info_level = atoi(argv[2]);
+       if (argc == 3) {
+               level = atoi(argv[2]);
+       }
 
        /* Open a printer handle */
 
@@ -1026,48 +1204,67 @@ static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
                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);
-
-               if (!W_ERROR_IS_OK(werror))
+               werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
+                                                         &pol,
+                                                         archi_table[i].long_archi,
+                                                         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;
+               success = true;
 
-               printf ("\n[%s]\n", archi_table[i].long_archi);
+               printf("\n[%s]\n", archi_table[i].long_archi);
 
-               switch (info_level) {
+               switch (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;
+               case 4:
+                       display_print_driver4(&info.info4);
+                       break;
+               case 5:
+                       display_print_driver5(&info.info5);
+                       break;
+               case 6:
+                       display_print_driver6(&info.info6);
+                       break;
+               case 8:
+                       display_print_driver8(&info.info8);
                        break;
                default:
-                       printf("unknown info level %d\n", info_level);
+                       printf("unknown info level %d\n", level);
                        break;
                }
        }
 
        /* Cleanup */
 
-       if (opened_hnd)
+       if (is_valid_policy_hnd(&pol)) {
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
+       }
 
-       if ( success )
+       if (success) {
                werror = WERR_OK;
+       }
 
        return werror;
 }
@@ -1075,92 +1272,139 @@ static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
+static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
+                                         TALLOC_CTX *mem_ctx,
+                                         const char *architecture,
+                                         uint32_t level)
+{
+       WERROR werror;
+       uint32_t count = 0;
+       union spoolss_DriverInfo *info = NULL;
+       uint32_t j;
+
+       werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
+                                                  cli->srv_name_slash,
+                                                  architecture,
+                                                  level,
+                                                  0,
+                                                  &count,
+                                                  &info);
+
+       if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
+               printf("Server does not support environment [%s]\n",
+                       architecture);
+               return WERR_OK;
+       }
+
+       if (count == 0) {
+               return WERR_OK;
+       }
+
+       if (!W_ERROR_IS_OK(werror)) {
+               printf("Error getting driver for environment [%s] - %s\n",
+                       architecture, win_errstr(werror));
+               return werror;
+       }
+
+       printf("\n[%s]\n", architecture);
+
+       switch (level) {
+       case 1:
+               for (j=0; j < count; j++) {
+                       display_print_driver1(&info[j].info1);
+               }
+               break;
+       case 2:
+               for (j=0; j < count; j++) {
+                       display_print_driver2(&info[j].info2);
+               }
+               break;
+       case 3:
+               for (j=0; j < count; j++) {
+                       display_print_driver3(&info[j].info3);
+               }
+               break;
+       case 4:
+               for (j=0; j < count; j++) {
+                       display_print_driver4(&info[j].info4);
+               }
+               break;
+       case 5:
+               for (j=0; j < count; j++) {
+                       display_print_driver5(&info[j].info5);
+               }
+               break;
+       case 6:
+               for (j=0; j < count; j++) {
+                       display_print_driver6(&info[j].info6);
+               }
+               break;
+       case 8:
+               for (j=0; j < count; j++) {
+                       display_print_driver8(&info[j].info8);
+               }
+               break;
+       default:
+               printf("unknown info level %d\n", level);
+               return WERR_UNKNOWN_LEVEL;
+       }
+
+       return werror;
+}
+
 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
                                          TALLOC_CTX *mem_ctx,
                                          int argc, const char **argv)
 {
        WERROR werror = WERR_OK;
-       uint32          info_level = 1;
-       PRINTER_DRIVER_CTR      ctr;
-       uint32          i, j,
-                       returned;
+       uint32_t        level = 1;
+       uint32_t        i;
+       const char *architecture = NULL;
 
-       if (argc > 2) {
-               printf("Usage: enumdrivers [level]\n");
+       if (argc > 3) {
+               printf("Usage: enumdrivers [level] [architecture]\n");
                return WERR_OK;
        }
 
-       if (argc == 2)
-               info_level = atoi(argv[1]);
+       if (argc >= 2) {
+               level = atoi(argv[1]);
+       }
+
+       if (argc == 3) {
+               architecture = argv[2];
+       }
 
+       if (architecture) {
+               return enum_driver_by_architecture(cli, mem_ctx,
+                                                  architecture,
+                                                  level);
+       }
 
        /* loop through and print driver info level for each architecture */
        for (i=0; archi_table[i].long_archi!=NULL; i++) {
                /* check to see if we already asked for this architecture string */
 
-               if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
-                       continue;
-
-               werror = rpccli_spoolss_enumprinterdrivers(
-                       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",
-                               archi_table[i].long_archi);
-                       werror = WERR_OK;
+               if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
                        continue;
                }
 
-               if (returned == 0)
-                       continue;
-
+               werror = enum_driver_by_architecture(cli, mem_ctx,
+                                                    archi_table[i].long_archi,
+                                                    level);
                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;
+                       break;
                }
+       }
 
-               printf ("\n[%s]\n", archi_table[i].long_archi);
-               switch (info_level)
-               {
-
-               case 1:
-                       for (j=0; j < returned; j++) {
-                               display_print_driver_1 (&ctr.info1[j]);
-                       }
-                       break;
-               case 2:
-                       for (j=0; j < returned; j++) {
-                               display_print_driver_2 (&ctr.info2[j]);
-                       }
-                       break;
-               case 3:
-                       for (j=0; j < returned; j++) {
-                               display_print_driver_3 (&ctr.info3[j]);
-                       }
-                       break;
-               default:
-                       printf("unknown info level %d\n", info_level);
-                       return WERR_UNKNOWN_LEVEL;
-               }
-       }
-
-       return werror;
-}
+       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);
 }
 
 /****************************************************************************
@@ -1171,8 +1415,12 @@ static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
                                          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]);
@@ -1181,17 +1429,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);
 
-       if (W_ERROR_IS_OK(result))
-               display_printdriverdir_1(ctr.info1);
+               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(&info.info1);
+       }
 
        return result;
 }
@@ -1199,7 +1469,9 @@ 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;
@@ -1209,7 +1481,7 @@ void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
                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;
                }
        }
@@ -1228,8 +1500,9 @@ void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
  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;
 
@@ -1240,70 +1513,80 @@ 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>
  *******************************************************************************/
-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;
+}
 
 /****************************************************************************
 ****************************************************************************/
@@ -1313,11 +1596,11 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
                                              int argc, const char **argv)
 {
        WERROR result;
-       uint32                  level = 3;
-       PRINTER_DRIVER_CTR      ctr;
-       DRIVER_INFO_3           info3;
+       NTSTATUS status;
+       uint32_t                  level = 3;
+       struct spoolss_AddDriverInfoCtr info_ctr;
+       struct spoolss_AddDriverInfo3 info3;
        const char              *arch;
-       fstring                 driver_name;
        char                    *driver_args;
 
        /* parse the command arguments */
@@ -1332,15 +1615,16 @@ 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 ))
@@ -1358,14 +1642,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;
@@ -1380,14 +1669,8 @@ static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
                                          int argc, const char **argv)
 {
        WERROR result;
-       NTSTATUS status;
        struct spoolss_SetPrinterInfoCtr info_ctr;
        struct spoolss_SetPrinterInfo2 info2;
-       struct policy_handle handle;
-       struct spoolss_DevmodeContainer devmode_ctr;
-       struct sec_desc_buf sd;
-       struct spoolss_UserLevelCtr userlevel_ctr;
-       struct spoolss_UserLevel1 level1;
 
        /* parse the command arguments */
        if (argc != 5)
@@ -1397,9 +1680,7 @@ static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
         }
 
        /* Fill in the DRIVER_INFO_2 struct */
-       ZERO_STRUCT(devmode_ctr);
        ZERO_STRUCT(info2);
-       ZERO_STRUCT(sd);
 
        info2.printername       = argv[1];
        info2.drivername        = argv[3];
@@ -1427,25 +1708,8 @@ static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
        info_ctr.level = 2;
        info_ctr.info.info2 = &info2;
 
-       level1.size             = 28; /* wild guess */
-       level1.build            = 1381;
-       level1.major            = 2;
-       level1.minor            = 0;
-       level1.processor        = 0;
-       level1.client           = global_myname();
-       level1.user             = cli->auth->user_name;
-
-       userlevel_ctr.level = 1;
-       userlevel_ctr.user_info.level1 = &level1;
-
-       status = rpccli_spoolss_AddPrinterEx(cli, mem_ctx,
-                                            cli->srv_name_slash,
-                                            &info_ctr,
-                                            &devmode_ctr,
-                                            &sd,
-                                            &userlevel_ctr,
-                                            &handle,
-                                            &result);
+       result = rpccli_spoolss_addprinterex(cli, mem_ctx,
+                                            &info_ctr);
        if (W_ERROR_IS_OK(result))
                printf ("Printer %s successfully installed.\n", argv[1]);
 
@@ -1459,13 +1723,18 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
                                       TALLOC_CTX *mem_ctx,
                                       int argc, const char **argv)
 {
-       POLICY_HND              pol;
+       struct policy_handle    pol;
        WERROR                  result;
-       uint32                  level = 2;
-       bool                    opened_hnd = False;
-       PRINTER_INFO_CTR        ctr;
-       PRINTER_INFO_2          info2;
+       NTSTATUS                status;
+       uint32_t                level = 2;
        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)
@@ -1485,15 +1754,13 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
        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;
@@ -1501,10 +1768,20 @@ 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.info2.devmode = NULL;
+       info.info2.secdesc = NULL;
 
+       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;;
@@ -1515,7 +1792,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;
@@ -1641,8 +1918,12 @@ static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
                                            int argc, const char **argv)
 {
        WERROR result;
-       char *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) {
@@ -1650,18 +1931,37 @@ static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
                return WERR_OK;
         }
 
-       if (asprintf(&environment, "%s", (argc == 2) ? argv[1] :
-                    PRINTER_DRIVER_ARCHITECTURE) < 0) {
-               return WERR_NOMEM;
+       if (argc == 2) {
+               environment = argv[1];
        }
 
-       result = rpccli_spoolss_getprintprocessordirectory(
-               cli, mem_ctx, cli->srv_name_slash, 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(environment);
+       if (W_ERROR_IS_OK(result)) {
+               printf("%s\n", info.info1.directory_name);
+       }
 
        return result;
 }
@@ -1672,18 +1972,19 @@ static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
-       POLICY_HND handle;
+       struct policy_handle handle;
        WERROR werror;
        NTSTATUS status;
        const char *printername;
-       bool got_handle = False;
        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;
         }
 
@@ -1698,32 +1999,58 @@ static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        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             = SPOOLSS_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             = SPOOLSS_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);
 
        return werror;
@@ -1735,11 +2062,10 @@ static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
-       POLICY_HND handle;
+       struct policy_handle handle;
        WERROR werror;
        NTSTATUS status;
        const char *printername;
-       bool got_handle = False;
        union spoolss_AddFormInfo info;
        struct spoolss_AddFormInfo1 info1;
 
@@ -1761,11 +2087,9 @@ static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
-
        /* Dummy up some values for the form data */
 
-       info1.flags             = FORM_PRINTER;
+       info1.flags             = SPOOLSS_FORM_PRINTER;
        info1.size.width        = 100;
        info1.size.height       = 100;
        info1.area.left         = 0;
@@ -1786,7 +2110,7 @@ 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);
 
        return werror;
@@ -1798,11 +2122,11 @@ static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
 static const char *get_form_flag(int form_flag)
 {
        switch (form_flag) {
-       case FORM_USER:
+       case SPOOLSS_FORM_USER:
                return "FORM_USER";
-       case FORM_BUILTIN:
+       case SPOOLSS_FORM_BUILTIN:
                return "FORM_BUILTIN";
-       case FORM_PRINTER:
+       case SPOOLSS_FORM_PRINTER:
                return "FORM_PRINTER";
        default:
                return "unknown";
@@ -1812,37 +2136,38 @@ static const char *get_form_flag(int form_flag)
 /****************************************************************************
 ****************************************************************************/
 
-static void display_form(FORM_1 *form)
+static void display_form_info1(struct spoolss_FormInfo1 *r)
 {
-       fstring form_name = "";
-
-       if (form->name.buffer)
-               rpcstr_pull(form_name, form->name.buffer,
-                           sizeof(form_name), -1, STR_TERMINATE);
-
        printf("%s\n" \
                "\tflag: %s (%d)\n" \
                "\twidth: %d, length: %d\n" \
                "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
-               form_name, get_form_flag(form->flag), form->flag,
-               form->width, form->length,
-               form->left, form->right,
-               form->top, form->bottom);
+               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);
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-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\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");
 }
 
 /****************************************************************************
@@ -1851,20 +2176,20 @@ static void display_form_info1(struct spoolss_FormInfo1 *r)
 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
-       POLICY_HND handle;
+       struct policy_handle handle;
        WERROR werror;
        NTSTATUS status;
        const char *printername;
-       bool got_handle = False;
        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;
         }
 
@@ -1879,26 +2204,28 @@ static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        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,
@@ -1910,9 +2237,17 @@ 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);
 
        return werror;
@@ -1925,11 +2260,10 @@ static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
                                       TALLOC_CTX *mem_ctx, int argc,
                                       const char **argv)
 {
-       POLICY_HND handle;
+       struct policy_handle handle;
        WERROR werror;
        NTSTATUS status;
        const char *printername;
-       bool got_handle = False;
 
        /* Parse the command arguments */
 
@@ -1949,8 +2283,6 @@ static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
-
        /* Delete the form */
 
        status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
@@ -1962,7 +2294,7 @@ 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);
 
        return werror;
@@ -1975,17 +2307,16 @@ static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
                                       TALLOC_CTX *mem_ctx, int argc,
                                       const char **argv)
 {
-       POLICY_HND handle;
+       struct policy_handle handle;
        WERROR werror;
        const char *printername;
-       bool got_handle = False;
-       uint32 num_forms, level = 1, i;
-       FORM_1 *forms;
+       uint32_t num_forms, level = 1, i;
+       union spoolss_FormInfo *forms;
 
        /* Parse the command arguments */
 
-       if (argc != 2) {
-               printf ("Usage: %s <printer>\n", argv[0]);
+       if (argc < 2 || argc > 4) {
+               printf ("Usage: %s <printer> [level]\n", argv[0]);
                return WERR_OK;
         }
 
@@ -2000,11 +2331,18 @@ static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(werror))
                goto done;
 
-       got_handle = True;
+       if (argc == 3) {
+               level = atoi(argv[2]);
+       }
 
        /* Enumerate forms */
 
-       werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
+       werror = rpccli_spoolss_enumforms(cli, mem_ctx,
+                                         &handle,
+                                         level,
+                                         0,
+                                         &num_forms,
+                                         &forms);
 
        if (!W_ERROR_IS_OK(werror))
                goto done;
@@ -2012,13 +2350,18 @@ static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
        /* Display output */
 
        for (i = 0; i < num_forms; i++) {
-
-               display_form(&forms[i]);
-
+               switch (level) {
+               case 1:
+                       display_form_info1(&forms[i].info1);
+                       break;
+               case 2:
+                       display_form_info2(&forms[i].info2);
+                       break;
+               }
        }
 
  done:
-       if (got_handle)
+       if (is_valid_policy_hnd(&handle))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
 
        return werror;
@@ -2032,13 +2375,12 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                                            int argc, const char **argv)
 {
        WERROR result;
+       NTSTATUS status;
        const char *printername;
-       POLICY_HND pol;
-       bool opened_hnd = False;
-       PRINTER_INFO_CTR ctr;
-       PRINTER_INFO_0 info;
-       REGISTRY_VALUE value;
-       TALLOC_CTX *tmp_ctx = talloc_stackframe();
+       struct policy_handle pol;
+       union spoolss_PrinterInfo info;
+       enum winreg_Type type;
+       union spoolss_PrinterData data;
 
        /* parse the command arguments */
        if (argc < 5) {
@@ -2051,25 +2393,25 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
 
        RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
 
-       value.type = REG_NONE;
+       type = REG_NONE;
 
        if (strequal(argv[2], "string")) {
-               value.type = REG_SZ;
+               type = REG_SZ;
        }
 
        if (strequal(argv[2], "binary")) {
-               value.type = REG_BINARY;
+               type = REG_BINARY;
        }
 
        if (strequal(argv[2], "dword")) {
-               value.type = REG_DWORD;
+               type = REG_DWORD;
        }
 
        if (strequal(argv[2], "multistring")) {
-               value.type = REG_MULTI_SZ;
+               type = REG_MULTI_SZ;
        }
 
-       if (value.type == REG_NONE) {
+       if (type == REG_NONE) {
                printf("Unknown data type: %s\n", argv[2]);
                result =  WERR_INVALID_PARAM;
                goto done;
@@ -2081,112 +2423,96 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                                               printername,
                                               SEC_FLAG_MAXIMUM_ALLOWED,
                                               &pol);
-       if (!W_ERROR_IS_OK(result))
+       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);
-
-        if (!W_ERROR_IS_OK(result))
+       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("%s\n", current_timestring(mem_ctx, true));
+       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) {
-       case REG_SZ: {
-               UNISTR2 data;
-               init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
-               value.size = data.uni_str_len * 2;
-               if (value.size) {
-                       value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
-                                                     value.size);
-               } else {
-                       value.data_p = NULL;
-               }
+       switch (type) {
+       case REG_SZ:
+               data.string = talloc_strdup(mem_ctx, argv[4]);
+               W_ERROR_HAVE_NO_MEMORY(data.string);
                break;
-       }
-       case REG_DWORD: {
-               uint32 data = strtoul(argv[4], NULL, 10);
-               value.size = sizeof(data);
-               if (sizeof(data)) {
-                       value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
-                                                     sizeof(data));
-               } else {
-                       value.data_p = NULL;
-               }
+       case REG_DWORD:
+               data.value = strtoul(argv[4], NULL, 10);
                break;
-       }
-       case REG_BINARY: {
-               DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
-               value.data_p = data.data;
-               value.size = data.length;
+       case REG_BINARY:
+               data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
                break;
-       }
        case REG_MULTI_SZ: {
-               int i;
-               size_t len = 0;
-               char *p;
+               int i, num_strings;
+               const char **strings = NULL;
 
                for (i=4; i<argc; i++) {
                        if (strcmp(argv[i], "NULL") == 0) {
                                argv[i] = "";
                        }
-                       len += strlen(argv[i])+1;
+                       if (!add_string_to_array(mem_ctx, argv[i],
+                                                &strings,
+                                                &num_strings)) {
+                               result = WERR_NOMEM;
+                               goto done;
+                       }
                }
-
-               value.size = len*2;
-               value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
-               if (value.data_p == NULL) {
+               data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
+               if (!data.string_array) {
                        result = WERR_NOMEM;
                        goto done;
                }
-
-               p = (char *)value.data_p;
-               len = value.size;
-               for (i=4; i<argc; i++) {
-                       size_t l = (strlen(argv[i])+1)*2;
-                       rpcstr_push(p, argv[i], len, STR_TERMINATE);
-                       p += l;
-                       len -= l;
+               for (i=0; i < num_strings; i++) {
+                       data.string_array[i] = strings[i];
                }
-               SMB_ASSERT(len == 0);
                break;
-       }
+               }
        default:
                printf("Unknown data type: %s\n", argv[2]);
                result = WERR_INVALID_PARAM;
                goto done;
        }
 
-       result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
-
+       status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
+                                              &pol,
+                                              argv[3], /* value_name */
+                                              type,
+                                              data,
+                                              0, /* autocalculated size */
+                                              &result);
        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);
-
-        if (!W_ERROR_IS_OK(result))
+       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("%s\n", current_timestring(mem_ctx, true));
+       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;
 }
@@ -2194,43 +2520,42 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static void display_job_info_1(JOB_INFO_1 *job)
+static void display_job_info1(struct spoolss_JobInfo1 *r)
 {
-       fstring username = "", document = "", text_status = "";
-
-       rpcstr_pull(username, job->username.buffer,
-                   sizeof(username), -1, STR_TERMINATE);
-
-       rpcstr_pull(document, job->document.buffer,
-                   sizeof(document), -1, STR_TERMINATE);
-
-       rpcstr_pull(text_status, job->text_status.buffer,
-                   sizeof(text_status), -1, STR_TERMINATE);
-
-       printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
-              username, document, text_status, job->pagesprinted,
-              job->totalpages);
+       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_info_2(JOB_INFO_2 *job)
+static void display_job_info2(struct spoolss_JobInfo2 *r)
 {
-       fstring username = "", document = "", text_status = "";
+       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);
+}
 
-       rpcstr_pull(username, job->username.buffer,
-                   sizeof(username), -1, STR_TERMINATE);
+/****************************************************************************
+****************************************************************************/
 
-       rpcstr_pull(document, job->document.buffer,
-                   sizeof(document), -1, STR_TERMINATE);
+static void display_job_info3(struct spoolss_JobInfo3 *r)
+{
+       printf("jobid[%d], next_jobid[%d]\n",
+               r->job_id, r->next_job_id);
+}
 
-       rpcstr_pull(text_status, job->text_status.buffer,
-                   sizeof(text_status), -1, STR_TERMINATE);
+/****************************************************************************
+****************************************************************************/
 
-       printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
-              username, document, text_status, job->pagesprinted,
-              job->totalpages, job->size);
+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);
 }
 
 /****************************************************************************
@@ -2241,19 +2566,19 @@ static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
                                      const char **argv)
 {
        WERROR result;
-       uint32 level = 1, num_jobs, i;
-       bool got_hnd = False;
+       uint32_t level = 1, count, i;
        const char *printername;
-       POLICY_HND hnd;
-       JOB_INFO_CTR ctr;
+       struct policy_handle hnd;
+       union spoolss_JobInfo *info;
 
        if (argc < 2 || argc > 3) {
                printf("Usage: %s printername [level]\n", argv[0]);
                return WERR_OK;
        }
 
-       if (argc == 3)
+       if (argc == 3) {
                level = atoi(argv[2]);
+       }
 
        /* Open printer handle */
 
@@ -2266,23 +2591,27 @@ static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
        if (!W_ERROR_IS_OK(result))
                goto done;
 
-       got_hnd = True;
-
        /* Enumerate ports */
 
-       result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
-               &num_jobs, &ctr);
-
-       if (!W_ERROR_IS_OK(result))
+       result = rpccli_spoolss_enumjobs(cli, mem_ctx,
+                                        &hnd,
+                                        0, /* firstjob */
+                                        1000, /* numjobs */
+                                        level,
+                                        0,
+                                        &count,
+                                        &info);
+       if (!W_ERROR_IS_OK(result)) {
                goto done;
+       }
 
-       for (i = 0; i < num_jobs; i++) {
-               switch(level) {
+       for (i = 0; i < count; i++) {
+               switch (level) {
                case 1:
-                       display_job_info_1(&ctr.job.job_info_1[i]);
+                       display_job_info1(&info[i].info1);
                        break;
                case 2:
-                       display_job_info_2(&ctr.job.job_info_2[i]);
+                       display_job_info2(&info[i].info2);
                        break;
                default:
                        d_printf("unknown info level %d\n", level);
@@ -2291,8 +2620,9 @@ static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
        }
 
 done:
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd)) {
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+       }
 
        return result;
 }
@@ -2300,15 +2630,153 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
-                                      TALLOC_CTX *mem_ctx, int argc,
-                                      const char **argv)
+static WERROR cmd_spoolss_get_job(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;
        const char *printername;
-       POLICY_HND hnd;
+       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 (is_valid_policy_hnd(&hnd)) {
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+       }
+
+       return result;
+}
+
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
+                                 TALLOC_CTX *mem_ctx, int argc,
+                                 const char **argv)
+{
+       WERROR result;
+       NTSTATUS status;
+       const char *printername;
+       struct policy_handle hnd;
+       uint32_t job_id;
+       enum spoolss_JobControl command;
+
+       if (argc != 4) {
+               printf("Usage: %s printername job_id command\n", argv[0]);
+               return WERR_OK;
+       }
+
+       job_id = atoi(argv[2]);
+       command = 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;
+       }
+
+       /* Set Job */
+
+       status = rpccli_spoolss_SetJob(cli, mem_ctx,
+                                      &hnd,
+                                      job_id,
+                                      NULL,
+                                      command,
+                                      &result);
+
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+done:
+       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,
+                                   const char **argv)
+{
+       WERROR result;
+       NTSTATUS status;
+       uint32_t i = 0;
+       const char *printername;
+       struct policy_handle hnd;
+       uint32_t value_offered = 0;
+       const char *value_name = NULL;
+       uint32_t value_needed;
+       enum winreg_Type type;
+       uint8_t *data = NULL;
+       uint32_t data_offered = 0;
+       uint32_t data_needed;
 
        if (argc != 2) {
                printf("Usage: %s printername\n", argv[0]);
@@ -2323,30 +2791,60 @@ static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli,
                                               printername,
                                               SEC_FLAG_MAXIMUM_ALLOWED,
                                               &hnd);
-       if (!W_ERROR_IS_OK(result))
+       if (!W_ERROR_IS_OK(result)) {
                goto done;
-
-       got_hnd = True;
+       }
 
        /* Enumerate data */
 
-       result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
-                                            &val_needed, &data_needed,
-                                            NULL);
-       while (W_ERROR_IS_OK(result)) {
-               REGISTRY_VALUE value;
-               result = rpccli_spoolss_enumprinterdata(
-                       cli, mem_ctx, &hnd, i++, val_needed,
-                       data_needed, 0, 0, &value);
-               if (W_ERROR_IS_OK(result))
-                       display_reg_value(value);
-       }
-       if (W_ERROR_V(result) == ERRnomoreitems)
+       status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
+                                               &hnd,
+                                               i,
+                                               value_name,
+                                               value_offered,
+                                               &value_needed,
+                                               &type,
+                                               data,
+                                               data_offered,
+                                               &data_needed,
+                                               &result);
+
+       data_offered    = data_needed;
+       value_offered   = value_needed;
+       data            = talloc_zero_array(mem_ctx, uint8_t, data_needed);
+       value_name      = talloc_zero_array(mem_ctx, char, value_needed);
+
+       while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
+
+               status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
+                                                       &hnd,
+                                                       i++,
+                                                       value_name,
+                                                       value_offered,
+                                                       &value_needed,
+                                                       &type,
+                                                       data,
+                                                       data_offered,
+                                                       &data_needed,
+                                                       &result);
+               if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
+                       struct regval_blob v;
+                       fstrcpy(v.valuename, value_name);
+                       v.type = type;
+                       v.size = data_offered;
+                       v.data_p = data;
+                       display_reg_value(v);
+               }
+       }
+
+       if (W_ERROR_V(result) == ERRnomoreitems) {
                result = W_ERROR(ERRsuccess);
+       }
 
 done:
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd)) {
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+       }
 
        return result;
 }
@@ -2359,20 +2857,17 @@ static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
                                          const char **argv)
 {
        WERROR result;
-       uint32 i;
-       bool got_hnd = False;
+       uint32_t i;
        const char *printername;
-       const char *keyname = NULL;
-       POLICY_HND hnd;
-       REGVAL_CTR *ctr = NULL;
+       struct policy_handle hnd;
+       uint32_t count;
+       struct spoolss_PrinterEnumValues *info;
 
        if (argc != 3) {
                printf("Usage: %s printername <keyname>\n", argv[0]);
                return WERR_OK;
        }
 
-       keyname = argv[2];
-
        /* Open printer handle */
 
        RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
@@ -2381,30 +2876,32 @@ static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
                                               printername,
                                               SEC_FLAG_MAXIMUM_ALLOWED,
                                               &hnd);
-       if (!W_ERROR_IS_OK(result))
+       if (!W_ERROR_IS_OK(result)) {
                goto done;
-
-       got_hnd = True;
+       }
 
        /* Enumerate subkeys */
 
-       if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
-               return WERR_NOMEM;
-
-       result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
-
-       if (!W_ERROR_IS_OK(result))
+       result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
+                                                 &hnd,
+                                                 argv[2],
+                                                 0,
+                                                 &count,
+                                                 &info);
+       if (!W_ERROR_IS_OK(result)) {
                goto done;
-
-       for (i=0; i < ctr->num_values; i++) {
-               display_reg_value(*(ctr->values[i]));
        }
 
-       TALLOC_FREE( ctr );
+       for (i=0; i < count; i++) {
+               display_printer_data(info[i].value_name,
+                                    info[i].type,
+                                    info[i].data);
+       }
 
-done:
-       if (got_hnd)
+ done:
+       if (is_valid_policy_hnd(&hnd)) {
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+       }
 
        return result;
 }
@@ -2412,26 +2909,27 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
-                                            TALLOC_CTX *mem_ctx, int argc,
-                                            const char **argv)
+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;
        const char *printername;
        const char *keyname = NULL;
-       POLICY_HND hnd;
-       uint16 *keylist = NULL, *curkey;
+       struct policy_handle hnd;
+       const char **key_buffer = NULL;
+       int i;
 
        if (argc < 2 || argc > 3) {
                printf("Usage: %s printername [keyname]\n", argv[0]);
                return WERR_OK;
        }
 
-       if (argc == 3)
+       if (argc == 3) {
                keyname = argv[2];
-       else
+       } else {
                keyname = "";
+       }
 
        /* Open printer handle */
 
@@ -2441,36 +2939,31 @@ static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli,
                                               printername,
                                               SEC_FLAG_MAXIMUM_ALLOWED,
                                               &hnd);
-       if (!W_ERROR_IS_OK(result))
+       if (!W_ERROR_IS_OK(result)) {
                goto done;
-
-       got_hnd = True;
+       }
 
        /* Enumerate subkeys */
 
-       result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
+       result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
+                                              &hnd,
+                                              keyname,
+                                              &key_buffer,
+                                              0);
 
-       if (!W_ERROR_IS_OK(result))
+       if (!W_ERROR_IS_OK(result)) {
                goto done;
-
-       curkey = keylist;
-       while (*curkey != 0) {
-               char *subkey = NULL;
-               rpcstr_pull_talloc(mem_ctx, &subkey, curkey, -1,
-                           STR_TERMINATE);
-               if (!subkey) {
-                       break;
-               }
-               printf("%s\n", subkey);
-               curkey += strlen(subkey) + 1;
        }
 
-done:
+       for (i=0; key_buffer && key_buffer[i]; i++) {
+               printf("%s\n", key_buffer[i]);
+       }
 
-       SAFE_FREE(keylist);
+ done:
 
-       if (got_hnd)
+       if (is_valid_policy_hnd(&hnd)) {
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+       }
 
        return result;
 }
@@ -2483,10 +2976,11 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
                                     const char **argv)
 {
        const char *printername;
-       POLICY_HND hnd;
-       bool got_hnd = False;
+       const char *clientname;
+       struct policy_handle hnd;
        WERROR result;
-       SPOOL_NOTIFY_OPTION option;
+       NTSTATUS status;
+       struct spoolss_NotifyOption option;
 
        if (argc != 2) {
                printf("Usage: %s printername\n", argv[0]);
@@ -2507,46 +3001,58 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
                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;
+       option.types[0].type = PRINTER_NOTIFY_TYPE;
+       option.types[0].count = 1;
+       option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
+       if (option.types[0].fields == NULL) {
+               result = WERR_NOMEM;
+               goto done;
+       }
+       option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_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[1].type = JOB_NOTIFY_TYPE;
+       option.types[1].count = 1;
+       option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
+       if (option.types[1].fields == NULL) {
+               result = WERR_NOMEM;
+               goto done;
+       }
+       option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
 
-       /* Send rffpcnex */
+       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, cli->srv_name_slash, 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)
+       if (is_valid_policy_hnd(&hnd))
                rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
 
        return result;
@@ -2555,63 +3061,79 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
-                             struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
+static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
+                             struct rpc_pipe_client *cli2, struct policy_handle *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);
-               return False;
+               return false;
        }
        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);
-               return False;
+               return false;
        }
        printf("ok\n");
 
        talloc_destroy(mem_ctx);
 
-       return True;
+       return true;
 }
 
 /****************************************************************************
 ****************************************************************************/
 
-static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
-                                     struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
+static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
+                                     struct rpc_pipe_client *cli2, struct policy_handle *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;
-       bool result = True;
+       bool result = true;
 
 
        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;
+               result = false;
                goto done;
        }
        printf("ok\n");
 
        printf("Retrieving printer security for %s...", cli2->desthost);
-       werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
+       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;
+               result = false;
                goto done;
        }
        printf("ok\n");
@@ -2619,24 +3141,18 @@ static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *h
 
        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;
+               result = false;
                goto done;
        }
 
-       if (!sec_desc_equal( sd1, sd2 ) ) {
+       if (!security_descriptor_equal( sd1, sd2 ) ) {
                printf("Security Descriptors *not* equal!\n");
-               result = False;
+               result = false;
                goto done;
        }
 
@@ -2661,7 +3177,7 @@ static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
        char *printername_path = NULL;
        struct cli_state *cli_server2 = NULL;
        struct rpc_pipe_client *cli2 = NULL;
-       POLICY_HND hPrinter1, hPrinter2;
+       struct policy_handle hPrinter1, hPrinter2;
        NTSTATUS nt_status;
        WERROR werror;
 
@@ -2686,7 +3202,7 @@ static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
        if ( !NT_STATUS_IS_OK(nt_status) )
                return WERR_GENERAL_FAILURE;
 
-       nt_status = cli_rpc_pipe_open_noauth(cli_server2, &syntax_spoolss,
+       nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
                                             &cli2);
        if (!NT_STATUS_IS_OK(nt_status)) {
                printf("failed to open spoolss pipe on server %s (%s)\n",
@@ -2744,40 +3260,258 @@ done:
        return WERR_OK;
 }
 
+static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
+{
+       printf("print_processor_name: %s\n", r->print_processor_name);
+}
+
+static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
+                                    TALLOC_CTX *mem_ctx, int argc,
+                                    const char **argv)
+{
+       WERROR werror;
+       const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
+       uint32_t num_procs, level = 1, i;
+       union spoolss_PrintProcessorInfo *procs;
+
+       /* Parse the command arguments */
+
+       if (argc < 1 || argc > 4) {
+               printf ("Usage: %s [environment] [level]\n", argv[0]);
+               return WERR_OK;
+        }
+
+       if (argc >= 2) {
+               environment = argv[1];
+       }
+
+       if (argc == 3) {
+               level = atoi(argv[2]);
+       }
+
+       /* Enumerate Print Processors */
+
+       werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
+                                                   cli->srv_name_slash,
+                                                   environment,
+                                                   level,
+                                                   0,
+                                                   &num_procs,
+                                                   &procs);
+       if (!W_ERROR_IS_OK(werror))
+               goto done;
+
+       /* Display output */
+
+       for (i = 0; i < num_procs; i++) {
+               switch (level) {
+               case 1:
+                       display_proc_info1(&procs[i].info1);
+                       break;
+               }
+       }
+
+ done:
+       return werror;
+}
+
+static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
+{
+       printf("name_array: %s\n", r->name_array);
+}
+
+static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
+                                              TALLOC_CTX *mem_ctx, int argc,
+                                              const char **argv)
+{
+       WERROR werror;
+       const char *print_processor_name = "winprint";
+       uint32_t num_procs, level = 1, i;
+       union spoolss_PrintProcDataTypesInfo *procs;
+
+       /* Parse the command arguments */
+
+       if (argc < 1 || argc > 4) {
+               printf ("Usage: %s [environment] [level]\n", argv[0]);
+               return WERR_OK;
+        }
+
+       if (argc >= 2) {
+               print_processor_name = argv[1];
+       }
+
+       if (argc == 3) {
+               level = atoi(argv[2]);
+       }
+
+       /* Enumerate Print Processor Data Types */
+
+       werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
+                                                           cli->srv_name_slash,
+                                                           print_processor_name,
+                                                           level,
+                                                           0,
+                                                           &num_procs,
+                                                           &procs);
+       if (!W_ERROR_IS_OK(werror))
+               goto done;
+
+       /* Display output */
+
+       for (i = 0; i < num_procs; i++) {
+               switch (level) {
+               case 1:
+                       display_proc_data_types_info1(&procs[i].info1);
+                       break;
+               }
+       }
+
+ done:
+       return werror;
+}
+
+static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
+{
+       printf("monitor_name: %s\n", r->monitor_name);
+}
+
+static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
+{
+       printf("monitor_name: %s\n", r->monitor_name);
+       printf("environment: %s\n", r->environment);
+       printf("dll_name: %s\n", r->dll_name);
+}
+
+static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
+                                       TALLOC_CTX *mem_ctx, int argc,
+                                       const char **argv)
+{
+       WERROR werror;
+       uint32_t count, level = 1, i;
+       union spoolss_MonitorInfo *info;
+
+       /* Parse the command arguments */
+
+       if (argc > 2) {
+               printf("Usage: %s [level]\n", argv[0]);
+               return WERR_OK;
+       }
+
+       if (argc == 2) {
+               level = atoi(argv[1]);
+       }
+
+       /* Enumerate Print Monitors */
+
+       werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
+                                            cli->srv_name_slash,
+                                            level,
+                                            0,
+                                            &count,
+                                            &info);
+       if (!W_ERROR_IS_OK(werror)) {
+               goto done;
+       }
+
+       /* Display output */
+
+       for (i = 0; i < count; i++) {
+               switch (level) {
+               case 1:
+                       display_monitor1(&info[i].info1);
+                       break;
+               case 2:
+                       display_monitor2(&info[i].info2);
+                       break;
+               }
+       }
+
+ done:
+       return werror;
+}
+
+static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
+                                           TALLOC_CTX *mem_ctx, int argc,
+                                           const char **argv)
+{
+       WERROR result;
+       NTSTATUS status;
+       struct policy_handle handle, gdi_handle;
+       const char *printername;
+       struct spoolss_DevmodeContainer devmode_ctr;
+
+       RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
+
+       result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
+                                              printername,
+                                              SEC_FLAG_MAXIMUM_ALLOWED,
+                                              &handle);
+       if (!W_ERROR_IS_OK(result)) {
+               return result;
+       }
+
+       ZERO_STRUCT(devmode_ctr);
+
+       status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
+                                               &handle,
+                                               &gdi_handle,
+                                               &devmode_ctr,
+                                               &result);
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+ done:
+       if (is_valid_policy_hnd(&gdi_handle)) {
+               rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
+       }
+       if (is_valid_policy_hnd(&handle)) {
+               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
+       }
+
+       return result;
+}
+
 /* List of commands exported by this module */
 struct cmd_set spoolss_commands[] = {
 
        { "SPOOLSS"  },
 
-       { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   &syntax_spoolss, NULL, "Add a print driver",                  "" },
-       { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       &syntax_spoolss, NULL, "Add a printer",                       "" },
-       { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       &syntax_spoolss, NULL, "Delete a printer driver",             "" },
-       { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     &syntax_spoolss, NULL, "Delete a printer driver with files",  "" },
-       { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          &syntax_spoolss, NULL, "Enumerate printer data",              "" },
-       { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       &syntax_spoolss, NULL, "Enumerate printer data for a key",    "" },
-       { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    &syntax_spoolss, NULL, "Enumerate printer keys",              "" },
-       { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          &syntax_spoolss, NULL, "Enumerate print jobs",                "" },
-       { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &syntax_spoolss, NULL, "Enumerate printer ports",             "" },
-       { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
-       { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &syntax_spoolss, NULL, "Enumerate printers",                  "" },
-       { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     &syntax_spoolss, NULL, "Get print driver data",               "" },
-       { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   &syntax_spoolss, NULL, "Get printer driver data with keyname", ""},
-       { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          &syntax_spoolss, NULL, "Get print driver information",        "" },
-       { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       &syntax_spoolss, NULL, "Get print driver upload directory",   "" },
-       { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         &syntax_spoolss, NULL, "Get printer info",                    "" },
-       { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    &syntax_spoolss, NULL, "Open printer handle",                 "" },
-       { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          &syntax_spoolss, NULL, "Set printer driver",                  "" },
-       { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    &syntax_spoolss, NULL, "Get print processor directory",       "" },
-       { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            &syntax_spoolss, NULL, "Add form",                            "" },
-       { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            &syntax_spoolss, NULL, "Set form",                            "" },
-       { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            &syntax_spoolss, NULL, "Get form",                            "" },
-       { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         &syntax_spoolss, NULL, "Delete form",                         "" },
-       { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         &syntax_spoolss, NULL, "Enumerate forms",                     "" },
-       { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         &syntax_spoolss, NULL, "Set printer comment",                 "" },
-       { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     &syntax_spoolss, NULL, "Set printername",                 "" },
-       { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     &syntax_spoolss, NULL, "Set REG_SZ printer data",             "" },
-       { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           &syntax_spoolss, NULL, "Rffpcnex test", "" },
-       { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         &syntax_spoolss, NULL, "Printer comparison test", "" },
+       { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   &ndr_table_spoolss.syntax_id, NULL, "Add a print driver",                  "" },
+       { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       &ndr_table_spoolss.syntax_id, NULL, "Add a printer",                       "" },
+       { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver",             "" },
+       { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files",  "" },
+       { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data",              "" },
+       { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key",    "" },
+       { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys",              "" },
+       { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs",                "" },
+       { "getjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job,            &ndr_table_spoolss.syntax_id, NULL, "Get print job",                       "" },
+       { "setjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job,            &ndr_table_spoolss.syntax_id, NULL, "Set print job",                       "" },
+       { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports",             "" },
+       { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
+       { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers",                  "" },
+       { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     &ndr_table_spoolss.syntax_id, NULL, "Get print driver data",               "" },
+       { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
+       { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          &ndr_table_spoolss.syntax_id, NULL, "Get print driver information",        "" },
+       { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory",   "" },
+       { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         &ndr_table_spoolss.syntax_id, NULL, "Get printer info",                    "" },
+       { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    &ndr_table_spoolss.syntax_id, NULL, "Open printer handle",                 "" },
+       { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          &ndr_table_spoolss.syntax_id, NULL, "Set printer driver",                  "" },
+       { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory",       "" },
+       { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            &ndr_table_spoolss.syntax_id, NULL, "Add form",                            "" },
+       { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            &ndr_table_spoolss.syntax_id, NULL, "Set form",                            "" },
+       { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            &ndr_table_spoolss.syntax_id, NULL, "Get form",                            "" },
+       { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         &ndr_table_spoolss.syntax_id, NULL, "Delete form",                         "" },
+       { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms",                     "" },
+       { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         &ndr_table_spoolss.syntax_id, NULL, "Set printer comment",                 "" },
+       { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     &ndr_table_spoolss.syntax_id, NULL, "Set printername",                 "" },
+       { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data",             "" },
+       { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
+       { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
+       { "enumprocs",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors",          "" },
+       { "enumprocdatatypes",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
+       { "enummonitors",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors,      &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
+       { "createprinteric",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic,  &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
 
        { NULL }
 };