s3: Use dbwrap_parse_record in fetch_share_mode_unlocked
[kai/samba.git] / source3 / rpcclient / cmd_spoolss.c
index aba2939343fbdb48f58e60406fd6f12840ab51f1..b189fd7379ec6ac12c4af27e8ac0fba6d0638c16 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
 
 #include "includes.h"
 #include "rpcclient.h"
+#include "../librpc/gen_ndr/ndr_spoolss_c.h"
+#include "rpc_client/cli_spoolss.h"
+#include "rpc_client/init_spoolss.h"
+#include "nt_printing.h"
+#include "../libcli/security/display_sec.h"
+#include "../libcli/security/security_descriptor.h"
+#include "../libcli/registry/util_reg.h"
+#include "libsmb/libsmb.h"
 
 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
 { \
        W_ERROR_HAVE_NO_MEMORY(_printername); \
 }
 
-struct table_node {
-       const char      *long_archi;
-       const char      *short_archi;
-       int     version;
-};
-
 /* The version int is used by getdrivers.  Note that
    all architecture strings that support mutliple
    versions must be grouped together since enumdrivers
@@ -44,7 +47,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 },
@@ -75,11 +78,11 @@ static const char *cmd_spoolss_get_short_archi(const char *long_archi)
 {
         int i=-1;
 
-        DEBUG(107,("Getting architecture dependant directory\n"));
+        DEBUG(107,("Getting architecture dependent directory\n"));
         do {
                 i++;
         } while ( (archi_table[i].long_archi!=NULL ) &&
-                  StrCaseCmp(long_archi, archi_table[i].long_archi) );
+                  strcasecmp_m(long_archi, archi_table[i].long_archi) );
 
         if (archi_table[i].long_archi==NULL) {
                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
@@ -104,25 +107,28 @@ 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;
+       uint32_t access_mask = PRINTER_ALL_ACCESS;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
-       if (argc != 2) {
-               printf("Usage: %s <printername>\n", argv[0]);
+       if (argc < 2) {
+               printf("Usage: %s <printername> [access_mask]\n", argv[0]);
                return WERR_OK;
        }
 
-       if (!cli)
-            return WERR_GENERAL_FAILURE;
+       if (argc >= 3) {
+               sscanf(argv[2], "%x", &access_mask);
+       }
 
        /* Open the printer handle */
 
        werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
                                               argv[1],
-                                              PRINTER_ALL_ACCESS,
+                                              access_mask,
                                               &hnd);
        if (W_ERROR_IS_OK(werror)) {
                printf("Printer %s opened successfully\n", argv[1]);
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, &werror);
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
 
                if (!W_ERROR_IS_OK(werror)) {
                        printf("Error closing printer handle! (%s)\n",
@@ -133,6 +139,55 @@ static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
        return werror;
 }
 
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc, const char **argv)
+{
+       WERROR          werror;
+       struct policy_handle    hnd;
+       uint32_t access_mask = PRINTER_ALL_ACCESS;
+       NTSTATUS status;
+       struct spoolss_DevmodeContainer devmode_ctr;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
+
+       ZERO_STRUCT(devmode_ctr);
+
+       if (argc < 2) {
+               printf("Usage: %s <printername> [access_mask]\n", argv[0]);
+               return WERR_OK;
+       }
+
+       if (argc >= 3) {
+               sscanf(argv[2], "%x", &access_mask);
+       }
+
+       /* Open the printer handle */
+
+       status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
+                                           argv[1],
+                                           NULL,
+                                           devmode_ctr,
+                                           access_mask,
+                                           &hnd,
+                                           &werror);
+       if (!NT_STATUS_IS_OK(status)) {
+               return ntstatus_to_werror(status);
+       }
+       if (W_ERROR_IS_OK(werror)) {
+               printf("Printer %s opened successfully\n", argv[1]);
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
+
+               if (!W_ERROR_IS_OK(werror)) {
+                       printf("Error closing printer handle! (%s)\n",
+                               get_dos_error_msg(werror));
+               }
+       }
+
+       return werror;
+}
 
 /****************************************************************************
 ****************************************************************************/
@@ -237,13 +292,46 @@ static void display_print_info3(struct spoolss_PrinterInfo3 *r)
 /****************************************************************************
 ****************************************************************************/
 
+static void display_print_info4(struct spoolss_PrinterInfo4 *r)
+{
+       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_info6(struct spoolss_PrinterInfo6 *r)
+{
+       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");
 }
 
-
 /****************************************************************************
 ****************************************************************************/
 
@@ -256,9 +344,10 @@ static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
        union spoolss_PrinterInfo *info;
        uint32_t                i, count;
        const char *name;
+       uint32_t flags = PRINTER_ENUM_LOCAL;
 
-       if (argc > 3) {
-               printf("Usage: %s [level] [name]\n", argv[0]);
+       if (argc > 4) {
+               printf("Usage: %s [level] [name] [flags]\n", argv[0]);
                return WERR_OK;
        }
 
@@ -266,14 +355,18 @@ static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
                level = atoi(argv[1]);
        }
 
-       if (argc == 3) {
+       if (argc >= 3) {
                name = argv[2];
        } else {
                name = cli->srv_name_slash;
        }
 
+       if (argc == 4) {
+               flags = atoi(argv[3]);
+       }
+
        result = rpccli_spoolss_enumprinters(cli, mem_ctx,
-                                            PRINTER_ENUM_LOCAL,
+                                            flags,
                                             name,
                                             level,
                                             0,
@@ -300,6 +393,15 @@ static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
                        case 3:
                                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", level);
                                goto done;
@@ -413,15 +515,17 @@ 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;
        NTSTATUS        status;
-       uint32          info_level = 2;
+       uint32_t        info_level = 2;
        union spoolss_PrinterInfo info;
        struct spoolss_SetPrinterInfoCtr info_ctr;
+       struct spoolss_SetPrinterInfo2 info2;
        const char      *printername, *comment = NULL;
        struct spoolss_DevmodeContainer devmode_ctr;
        struct sec_desc_buf secdesc_ctr;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        if (argc == 1 || argc > 3) {
                printf("Usage: %s printername comment\n", argv[0]);
@@ -458,26 +562,31 @@ static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
 
 
        /* Modify the comment. */
-       info.info2.comment = comment;
-       info.info2.secdesc = NULL;
-       info.info2.devmode = NULL;
+       spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
+       info2.comment = comment;
 
        info_ctr.level = 2;
-       info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
+       info_ctr.info.info2 = &info2;
 
-       status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
+       status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
                                           &pol,
                                           &info_ctr,
                                           &devmode_ctr,
                                           &secdesc_ctr,
                                           0, /* command */
                                           &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
+               goto done;
+       }
        if (W_ERROR_IS_OK(result))
                printf("Success in setting comment.\n");
 
  done:
-       if (is_valid_policy_hnd(&pol))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
+       if (is_valid_policy_hnd(&pol)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
+       }
 
        return result;
 }
@@ -489,16 +598,18 @@ 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;
        NTSTATUS        status;
-       uint32          info_level = 2;
+       uint32_t        info_level = 2;
        union spoolss_PrinterInfo info;
        const char      *printername,
                        *new_printername = NULL;
        struct spoolss_SetPrinterInfoCtr info_ctr;
+       struct spoolss_SetPrinterInfo2 info2;
        struct spoolss_DevmodeContainer devmode_ctr;
        struct sec_desc_buf secdesc_ctr;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        ZERO_STRUCT(devmode_ctr);
        ZERO_STRUCT(secdesc_ctr);
@@ -534,26 +645,31 @@ static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
                 goto done;
 
        /* Modify the printername. */
-       info.info2.printername = new_printername;
-       info.info2.devmode = NULL;
-       info.info2.secdesc = NULL;
+       spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
+       info2.printername = new_printername;
 
-       info_ctr.level = info_level;
-       info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
+       info_ctr.level = 2;
+       info_ctr.info.info2 = &info2;
 
-       status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
+       status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
                                           &pol,
                                           &info_ctr,
                                           &devmode_ctr,
                                           &secdesc_ctr,
                                           0, /* command */
                                           &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
+               goto done;
+       }
        if (W_ERROR_IS_OK(result))
                printf("Success in setting printername.\n");
 
  done:
-       if (is_valid_policy_hnd(&pol))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
+       if (is_valid_policy_hnd(&pol)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
+       }
 
        return result;
 }
@@ -565,11 +681,12 @@ 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_t        level = 1;
        const char      *printername;
        union spoolss_PrinterInfo info;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        if (argc == 1 || argc > 3) {
                printf("Usage: %s <printername> [level]\n", argv[0]);
@@ -618,6 +735,15 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
        case 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_info7(&info.info7);
                break;
@@ -627,7 +753,8 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
        }
  done:
        if (is_valid_policy_hnd(&pol)) {
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
        }
 
        return result;
@@ -636,27 +763,26 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static void display_reg_value(REGISTRY_VALUE value)
+static void display_reg_value(const char *name, enum winreg_Type type, DATA_BLOB blob)
 {
-       char *text = NULL;
+       const char *text = NULL;
 
-       switch(value.type) {
+       switch(type) {
        case REG_DWORD:
-               printf("%s: REG_DWORD: 0x%08x\n", value.valuename,
-                      *((uint32 *) value.data_p));
+               if (blob.length == sizeof(uint32)) {
+                       printf("%s: REG_DWORD: 0x%08x\n", name, IVAL(blob.data,0));
+               } else {
+                       printf("%s: REG_DWORD: <invalid>\n", name);
+               }
                break;
        case REG_SZ:
-               rpcstr_pull_talloc(talloc_tos(),
-                               &text,
-                               value.data_p,
-                               value.size,
-                               STR_TERMINATE);
-               printf("%s: REG_SZ: %s\n", value.valuename, text ? text : "");
+               pull_reg_sz(talloc_tos(), &blob, &text);
+               printf("%s: REG_SZ: %s\n", name, text ? text : "");
                break;
        case REG_BINARY: {
-               char *hex = hex_encode_talloc(NULL, value.data_p, value.size);
+               char *hex = hex_encode_talloc(NULL, blob.data, blob.length);
                size_t i, len;
-               printf("%s: REG_BINARY:", value.valuename);
+               printf("%s: REG_BINARY:", name);
                len = strlen(hex);
                for (i=0; i<len; i++) {
                        if (hex[i] == '\0') {
@@ -672,24 +798,23 @@ static void display_reg_value(REGISTRY_VALUE value)
                break;
        }
        case REG_MULTI_SZ: {
-               uint32 i, num_values;
-               char **values;
+               uint32_t i;
+               const char **values;
 
-               if (!W_ERROR_IS_OK(reg_pull_multi_sz(NULL, value.data_p,
-                                                    value.size, &num_values,
-                                                    &values))) {
-                       d_printf("reg_pull_multi_sz failed\n");
+               if (!pull_reg_multi_sz(NULL, &blob, &values)) {
+                       d_printf("pull_reg_multi_sz failed\n");
                        break;
                }
 
-               for (i=0; i<num_values; i++) {
+               printf("%s: REG_MULTI_SZ: \n", name);
+               for (i=0; values[i] != NULL; i++) {
                        d_printf("%s\n", values[i]);
                }
                TALLOC_FREE(values);
                break;
        }
        default:
-               printf("%s: unknown type %d\n", value.valuename, value.type);
+               printf("%s: unknown type %d\n", name, type);
        }
 
 }
@@ -699,20 +824,29 @@ static void display_reg_value(REGISTRY_VALUE value)
 
 static void display_printer_data(const char *v,
                                 enum winreg_Type type,
-                                union spoolss_PrinterData *r)
+                                uint8_t *data,
+                                uint32_t length)
 {
        int i;
+       union spoolss_PrinterData r;
+       DATA_BLOB blob = data_blob_const(data, length);
+       WERROR result;
+
+       result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
+       if (!W_ERROR_IS_OK(result)) {
+               return;
+       }
 
        switch (type) {
        case REG_DWORD:
-               printf("%s: REG_DWORD: 0x%08x\n", v, r->value);
+               printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
                break;
        case REG_SZ:
-               printf("%s: REG_SZ: %s\n", v, r->string);
+               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);
+                       r.binary.data, r.binary.length);
                size_t len;
                printf("%s: REG_BINARY:", v);
                len = strlen(hex);
@@ -731,8 +865,8 @@ static void display_printer_data(const char *v,
        }
        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]);
+               for (i=0; r.string_array[i] != NULL; i++) {
+                       printf("%s ", r.string_array[i]);
                }
                printf("\n");
                break;
@@ -749,12 +883,14 @@ 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;
        fstring         printername;
        const char *valuename;
        enum winreg_Type type;
-       union spoolss_PrinterData data;
+       uint8_t *data;
+       uint32_t needed;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        if (argc != 3) {
                printf("Usage: %s <printername> <valuename>\n", argv[0]);
@@ -787,17 +923,20 @@ static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
                                               valuename,
                                               0,
                                               &type,
+                                              &needed,
                                               &data);
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        /* Display printer data */
 
-       display_printer_data(valuename, type, &data);
+       display_printer_data(valuename, type, data, needed);
 
  done:
-       if (is_valid_policy_hnd(&pol))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
+       if (is_valid_policy_hnd(&pol)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
+       }
 
        return result;
 }
@@ -809,17 +948,17 @@ 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;
        fstring         printername;
        const char *valuename, *keyname;
-       REGISTRY_VALUE value;
 
        enum winreg_Type type;
-       uint8_t *buffer = NULL;
+       uint8_t *data = NULL;
        uint32_t offered = 0;
        uint32_t needed;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        if (argc != 4) {
                printf("Usage: %s <printername> <keyname> <valuename>\n",
@@ -849,53 +988,59 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
 
        /* Get printer info */
 
-       status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
+       data = talloc_zero_array(mem_ctx, uint8_t, offered);
+       if (!data) {
+               goto done;
+       }
+
+       status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
                                                 &pol,
                                                 keyname,
                                                 valuename,
                                                 &type,
-                                                buffer,
+                                                data,
                                                 offered,
                                                 &needed,
                                                 &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
+               goto done;
+       }
        if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
                offered = needed;
-               buffer = talloc_array(mem_ctx, uint8_t, needed);
-               status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
+               data = talloc_zero_array(mem_ctx, uint8_t, offered);
+               if (!data) {
+                       goto done;
+               }
+               status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
                                                         &pol,
                                                         keyname,
                                                         valuename,
                                                         &type,
-                                                        buffer,
+                                                        data,
                                                         offered,
                                                         &needed,
                                                         &result);
        }
 
        if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
                goto done;
        }
 
-       if (!W_ERROR_IS_OK(result)) {
-               goto done;
-       }
-
-
        if (!W_ERROR_IS_OK(result))
                goto done;
 
        /* Display printer data */
 
-       fstrcpy(value.valuename, valuename);
-       value.type = type;
-       value.size = needed;
-       value.data_p = buffer;
+       display_printer_data(valuename, type, data, needed);
 
-       display_reg_value(value);
 
  done:
-       if (is_valid_policy_hnd(&pol))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
+       if (is_valid_policy_hnd(&pol)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
+       }
 
        return result;
 }
@@ -910,7 +1055,8 @@ static void display_print_driver1(struct spoolss_DriverInfo1 *r)
        }
 
        printf("Printer Driver Info 1:\n");
-       printf("\tDriver Name: [%s]\n\n", r->driver_name);
+       printf("\tDriver Name: [%s]\n", r->driver_name);
+       printf("\n");
 }
 
 /****************************************************************************
@@ -928,7 +1074,8 @@ static void display_print_driver2(struct spoolss_DriverInfo2 *r)
        printf("\tArchitecture: [%s]\n", r->architecture);
        printf("\tDriver Path: [%s]\n", r->driver_path);
        printf("\tDatafile: [%s]\n", r->data_file);
-       printf("\tConfigfile: [%s]\n\n", r->config_file);
+       printf("\tConfigfile: [%s]\n", r->config_file);
+       printf("\n");
 }
 
 /****************************************************************************
@@ -948,19 +1095,166 @@ static void display_print_driver3(struct spoolss_DriverInfo3 *r)
        printf("\tArchitecture: [%s]\n", r->architecture);
        printf("\tDriver Path: [%s]\n", r->driver_path);
        printf("\tDatafile: [%s]\n", r->data_file);
-       printf("\tConfigfile: [%s]\n\n", r->config_file);
-       printf("\tHelpfile: [%s]\n\n", r->help_file);
+       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);
+       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[i] != NULL; i++) {
+       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_driver5(struct spoolss_DriverInfo5 *r)
+{
+       if (!r) {
+               return;
+       }
+
+       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 (!r) {
+               return;
+       }
+
+       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);
+
+       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\n", r->default_datatype);
+       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("\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("\n");
 }
 
+/****************************************************************************
+****************************************************************************/
+
+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");
+}
 
 /****************************************************************************
 ****************************************************************************/
@@ -969,7 +1263,7 @@ static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
                                    TALLOC_CTX *mem_ctx,
                                    int argc, const char **argv)
 {
-       POLICY_HND      pol;
+       struct policy_handle pol;
        WERROR          werror;
        uint32_t        level = 3;
        const char      *printername;
@@ -978,6 +1272,7 @@ static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
        union spoolss_DriverInfo info;
        uint32_t server_major_version;
        uint32_t server_minor_version;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        if ((argc == 1) || (argc > 3)) {
                printf("Usage: %s <printername> [level]\n", argv[0]);
@@ -1037,6 +1332,18 @@ static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
                case 3:
                        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", level);
                        break;
@@ -1046,7 +1353,8 @@ static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
        /* Cleanup */
 
        if (is_valid_policy_hnd(&pol)) {
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
        }
 
        if (success) {
@@ -1059,24 +1367,113 @@ 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_t        level = 1;
-       union spoolss_DriverInfo *info;
-       uint32_t        i, j, count;
+       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) {
+       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++) {
@@ -1086,52 +1483,11 @@ static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
                        continue;
                }
 
-               werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
-                                                          cli->srv_name_slash,
-                                                          archi_table[i].long_archi,
-                                                          level,
-                                                          0,
-                                                          &count,
-                                                          &info);
-
-               if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
-                       printf("Server does not support environment [%s]\n",
-                               archi_table[i].long_archi);
-                       werror = WERR_OK;
-                       continue;
-               }
-
-               if (count == 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;
-               }
-
-               printf("\n[%s]\n", archi_table[i].long_archi);
-
-               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;
-               default:
-                       printf("unknown info level %d\n", level);
-                       return WERR_UNKNOWN_LEVEL;
                }
        }
 
@@ -1160,6 +1516,7 @@ static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
        uint32_t offered;
        union spoolss_DriverDirectoryInfo info;
        uint32_t needed;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        if (argc > 2) {
                printf("Usage: %s [environment]\n", argv[0]);
@@ -1174,7 +1531,7 @@ static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
 
        /* Get the directory.  Only use Info level 1 */
 
-       status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
+       status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
                                                          cli->srv_name_slash,
                                                          env,
                                                          1,
@@ -1183,11 +1540,14 @@ static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
                                                          NULL, /* info */
                                                          &needed,
                                                          &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               return ntstatus_to_werror(status);
+       }
        if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
                offered = needed;
                buffer = data_blob_talloc_zero(mem_ctx, needed);
 
-               status = rpccli_spoolss_GetPrinterDriverDirectory(cli, mem_ctx,
+               status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
                                                                  cli->srv_name_slash,
                                                                  env,
                                                                  1,
@@ -1196,6 +1556,9 @@ static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
                                                                  &info,
                                                                  &needed,
                                                                  &result);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ntstatus_to_werror(status);
+               }
        }
 
        if (W_ERROR_IS_OK(result)) {
@@ -1252,7 +1615,7 @@ static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
           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_m(ptr, "NULL") == 0)) {
                ptr = NULL;
        }
 
@@ -1336,11 +1699,12 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
 {
        WERROR result;
        NTSTATUS status;
-       uint32                  level = 3;
+       uint32_t                  level = 3;
        struct spoolss_AddDriverInfoCtr info_ctr;
        struct spoolss_AddDriverInfo3 info3;
        const char              *arch;
        char                    *driver_args;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* parse the command arguments */
        if (argc != 3 && argc != 4)
@@ -1359,7 +1723,7 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
 
        arch = cmd_spoolss_get_short_archi(argv[1]);
        if (!arch) {
-               printf ("Error Unknown architechture [%s]\n", argv[1]);
+               printf ("Error Unknown architecture [%s]\n", argv[1]);
                return WERR_INVALID_PARAM;
        }
 
@@ -1384,7 +1748,7 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
        info_ctr.level          = level;
        info_ctr.info.info3     = &info3;
 
-       status = rpccli_spoolss_AddPrinterDriver(cli, mem_ctx,
+       status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
                                                 cli->srv_name_slash,
                                                 &info_ctr,
                                                 &result);
@@ -1428,8 +1792,8 @@ static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
        info2.comment           = "Created by rpcclient";
        info2.printprocessor    = "winprint";
        info2.datatype          = "RAW";
-       info2.devmode           = NULL;
-       info2.secdesc           = NULL;
+       info2.devmode_ptr       = 0;
+       info2.secdesc_ptr       = 0;
        info2.attributes        = PRINTER_ATTRIBUTE_SHARED;
        info2.priority          = 0;
        info2.defaultpriority   = 0;
@@ -1462,15 +1826,17 @@ 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;
        NTSTATUS                status;
-       uint32                  level = 2;
+       uint32_t                level = 2;
        const char              *printername;
        union spoolss_PrinterInfo info;
        struct spoolss_SetPrinterInfoCtr info_ctr;
+       struct spoolss_SetPrinterInfo2 info2;
        struct spoolss_DevmodeContainer devmode_ctr;
        struct sec_desc_buf secdesc_ctr;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        ZERO_STRUCT(devmode_ctr);
        ZERO_STRUCT(secdesc_ctr);
@@ -1507,23 +1873,26 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
 
        /* Set the printer driver */
 
-       info.info2.drivername = argv[2];
-       info.info2.devmode = NULL;
-       info.info2.secdesc = NULL;
+       spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
+       info2.drivername = argv[2];
 
        info_ctr.level = 2;
-       info_ctr.info.info2 = (struct spoolss_SetPrinterInfo2 *)&info.info2;
+       info_ctr.info.info2 = &info2;
 
-       status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
+       status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
                                           &pol,
                                           &info_ctr,
                                           &devmode_ctr,
                                           &secdesc_ctr,
                                           0, /* command */
                                           &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
+               goto done;
+       }
        if (!W_ERROR_IS_OK(result)) {
                printf("SetPrinter call failed!\n");
-               goto done;;
+               goto done;
        }
 
        printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
@@ -1531,8 +1900,10 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
 done:
        /* Cleanup */
 
-       if (is_valid_policy_hnd(&pol))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
+       if (is_valid_policy_hnd(&pol)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
+       }
 
        return result;
 }
@@ -1547,6 +1918,7 @@ static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
 {
        WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
        NTSTATUS status;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        int   i;
        int vers = -1;
@@ -1555,38 +1927,40 @@ static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
        uint32_t delete_flags = 0;
 
        /* parse the command arguments */
-       if (argc < 2 || argc > 4) {
-               printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
+       if (argc < 2 || argc > 5) {
+               printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
                return WERR_OK;
        }
 
        if (argc >= 3)
                arch = argv[2];
-       if (argc == 4)
-               vers = atoi (argv[3]);
-
-       if (vers >= 0) {
+       if (argc >= 4) {
+               vers = atoi(argv[3]);
                delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
        }
+       if (argc == 5)
+               delete_flags = atoi(argv[4]);
 
        /* delete the driver for all architectures */
        for (i=0; archi_table[i].long_archi; i++) {
 
-               if (arch &&  !strequal( archi_table[i].long_archi, arch))
+               if (arch && !strequal(archi_table[i].long_archi, arch))
                        continue;
 
                if (vers >= 0 && archi_table[i].version != vers)
                        continue;
 
                /* make the call to remove the driver */
-               status = rpccli_spoolss_DeletePrinterDriverEx(cli, mem_ctx,
+               status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
                                                              cli->srv_name_slash,
                                                              archi_table[i].long_archi,
                                                              argv[1],
                                                              delete_flags,
                                                              archi_table[i].version,
                                                              &result);
-
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ntstatus_to_werror(status);
+               }
                if ( !W_ERROR_IS_OK(result) )
                {
                        if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
@@ -1616,6 +1990,7 @@ static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
        WERROR result = WERR_OK;
        NTSTATUS status;
        int                     i;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* parse the command arguments */
        if (argc != 2) {
@@ -1625,20 +2000,23 @@ static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
 
        /* delete the driver for all architectures */
        for (i=0; archi_table[i].long_archi; i++) {
+               result = WERR_OK;
+
                /* make the call to remove the driver */
-               status = rpccli_spoolss_DeletePrinterDriver(cli, mem_ctx,
+               status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
                                                            cli->srv_name_slash,
                                                            archi_table[i].long_archi,
                                                            argv[1],
                                                            &result);
                if (!NT_STATUS_IS_OK(status)) {
-                       return result;
+                       result = ntstatus_to_werror(status);
+                       continue;
                }
                if ( !W_ERROR_IS_OK(result) ) {
                        if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
-                               printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n",
+                               printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
                                        argv[1], archi_table[i].long_archi,
-                                       W_ERROR_V(result));
+                                       win_errstr(result));
                        }
                } else {
                        printf ("Driver %s removed for arch [%s].\n", argv[1],
@@ -1663,6 +2041,7 @@ static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
        uint32_t offered;
        union spoolss_PrintProcessorDirectoryInfo info;
        uint32_t needed;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* parse the command arguments */
        if (argc > 2) {
@@ -1674,7 +2053,7 @@ static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
                environment = argv[1];
        }
 
-       status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
+       status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
                                                           cli->srv_name_slash,
                                                           environment,
                                                           1,
@@ -1683,11 +2062,14 @@ static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
                                                           NULL, /* info */
                                                           &needed,
                                                           &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               return ntstatus_to_werror(status);
+       }
        if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
                offered = needed;
                buffer = data_blob_talloc_zero(mem_ctx, needed);
 
-               status = rpccli_spoolss_GetPrintProcessorDirectory(cli, mem_ctx,
+               status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
                                                                   cli->srv_name_slash,
                                                                   environment,
                                                                   1,
@@ -1696,6 +2078,9 @@ static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
                                                                   &info,
                                                                   &needed,
                                                                   &result);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ntstatus_to_werror(status);
+               }
        }
 
        if (W_ERROR_IS_OK(result)) {
@@ -1711,7 +2096,7 @@ 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;
@@ -1719,6 +2104,7 @@ static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        struct spoolss_AddFormInfo1 info1;
        struct spoolss_AddFormInfo2 info2;
        uint32_t level = 1;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* Parse the command arguments */
 
@@ -1777,20 +2163,28 @@ static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
                info.info2 = &info2;
 
                break;
+       default:
+               werror = WERR_INVALID_PARAM;
+               goto done;
        }
 
        /* Add the form */
 
 
-       status = rpccli_spoolss_AddForm(cli, mem_ctx,
+       status = dcerpc_spoolss_AddForm(b, mem_ctx,
                                        &handle,
                                        level,
                                        info,
                                        &werror);
-
+       if (!NT_STATUS_IS_OK(status)) {
+               werror = ntstatus_to_werror(status);
+               goto done;
+       }
  done:
-       if (is_valid_policy_hnd(&handle))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
+       if (is_valid_policy_hnd(&handle)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
+       }
 
        return werror;
 }
@@ -1801,12 +2195,13 @@ 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;
        union spoolss_AddFormInfo info;
        struct spoolss_AddFormInfo1 info1;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* Parse the command arguments */
 
@@ -1841,16 +2236,21 @@ static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
 
        /* Set the form */
 
-       status = rpccli_spoolss_SetForm(cli, mem_ctx,
+       status = dcerpc_spoolss_SetForm(b, mem_ctx,
                                        &handle,
                                        argv[2],
                                        1,
                                        info,
                                        &werror);
-
+       if (!NT_STATUS_IS_OK(status)) {
+               werror = ntstatus_to_werror(status);
+               goto done;
+       }
  done:
-       if (is_valid_policy_hnd(&handle))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
+       if (is_valid_policy_hnd(&handle)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
+       }
 
        return werror;
 }
@@ -1915,7 +2315,7 @@ static void display_form_info2(struct spoolss_FormInfo2 *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;
@@ -1924,6 +2324,7 @@ static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        union spoolss_FormInfo info;
        uint32_t needed;
        uint32_t level = 1;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* Parse the command arguments */
 
@@ -1949,7 +2350,7 @@ static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
 
        /* Get the form */
 
-       status = rpccli_spoolss_GetForm(cli, mem_ctx,
+       status = dcerpc_spoolss_GetForm(b, mem_ctx,
                                        &handle,
                                        argv[2],
                                        level,
@@ -1958,10 +2359,14 @@ static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
                                        &info,
                                        &needed,
                                        &werror);
+       if (!NT_STATUS_IS_OK(status)) {
+               werror = ntstatus_to_werror(status);
+               goto done;
+       }
        if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
                buffer = data_blob_talloc_zero(mem_ctx, needed);
                offered = needed;
-               status = rpccli_spoolss_GetForm(cli, mem_ctx,
+               status = dcerpc_spoolss_GetForm(b, mem_ctx,
                                                &handle,
                                                argv[2],
                                                level,
@@ -1970,10 +2375,14 @@ static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
                                                &info,
                                                &needed,
                                                &werror);
+               if (!NT_STATUS_IS_OK(status)) {
+                       werror = ntstatus_to_werror(status);
+                       goto done;
+               }
        }
 
-       if (!NT_STATUS_IS_OK(status)) {
-               return werror;
+       if (!W_ERROR_IS_OK(werror)) {
+               goto done;
        }
 
        switch (level) {
@@ -1986,8 +2395,10 @@ static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        }
 
  done:
-       if (is_valid_policy_hnd(&handle))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
+       if (is_valid_policy_hnd(&handle)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
+       }
 
        return werror;
 }
@@ -1999,10 +2410,11 @@ 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;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* Parse the command arguments */
 
@@ -2024,17 +2436,20 @@ static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
 
        /* Delete the form */
 
-       status = rpccli_spoolss_DeleteForm(cli, mem_ctx,
+       status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
                                           &handle,
                                           argv[2],
                                           &werror);
        if (!NT_STATUS_IS_OK(status)) {
-               return ntstatus_to_werror(status);
+               werror = ntstatus_to_werror(status);
+               goto done;
        }
 
  done:
-       if (is_valid_policy_hnd(&handle))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
+       if (is_valid_policy_hnd(&handle)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
+       }
 
        return werror;
 }
@@ -2046,11 +2461,12 @@ 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;
-       uint32 num_forms, level = 1, i;
+       uint32_t num_forms, level = 1, i;
        union spoolss_FormInfo *forms;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* Parse the command arguments */
 
@@ -2100,8 +2516,10 @@ static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
        }
 
  done:
-       if (is_valid_policy_hnd(&handle))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
+       if (is_valid_policy_hnd(&handle)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
+       }
 
        return werror;
 }
@@ -2116,18 +2534,19 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
        WERROR result;
        NTSTATUS status;
        const char *printername;
-       POLICY_HND pol;
+       struct policy_handle pol = { 0, };
        union spoolss_PrinterInfo info;
        enum winreg_Type type;
        union spoolss_PrinterData data;
+       DATA_BLOB blob;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* parse the command arguments */
        if (argc < 5) {
                printf ("Usage: %s <printer> <string|binary|dword|multistring>"
                        " <value> <data>\n",
                        argv[0]);
-               result = WERR_INVALID_PARAM;
-               goto done;
+               return WERR_OK;
        }
 
        RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
@@ -2195,6 +2614,8 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                int i, num_strings;
                const char **strings = NULL;
 
+               num_strings = 0;
+
                for (i=4; i<argc; i++) {
                        if (strcmp(argv[i], "NULL") == 0) {
                                argv[i] = "";
@@ -2222,13 +2643,23 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                goto done;
        }
 
-       status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
+       result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+       status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
                                               &pol,
                                               argv[3], /* value_name */
                                               type,
-                                              data,
-                                              0, /* autocalculated size */
+                                              blob.data,
+                                              blob.length,
                                               &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
+               result = ntstatus_to_werror(status);
+               goto done;
+       }
        if (!W_ERROR_IS_OK(result)) {
                printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
                goto done;
@@ -2250,7 +2681,8 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
 done:
        /* cleanup */
        if (is_valid_policy_hnd(&pol)) {
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
        }
 
        return result;
@@ -2307,8 +2739,9 @@ static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
        WERROR result;
        uint32_t level = 1, count, i;
        const char *printername;
-       POLICY_HND hnd;
+       struct policy_handle hnd;
        union spoolss_JobInfo *info;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        if (argc < 2 || argc > 3) {
                printf("Usage: %s printername [level]\n", argv[0]);
@@ -2360,7 +2793,8 @@ static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
 
 done:
        if (is_valid_policy_hnd(&hnd)) {
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
        }
 
        return result;
@@ -2379,6 +2813,7 @@ static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
        uint32_t job_id;
        uint32_t level = 1;
        union spoolss_JobInfo info;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        if (argc < 3 || argc > 4) {
                printf("Usage: %s printername job_id [level]\n", argv[0]);
@@ -2436,12 +2871,101 @@ static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
 
 done:
        if (is_valid_policy_hnd(&hnd)) {
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
        }
 
        return result;
 }
 
+/****************************************************************************
+****************************************************************************/
+
+static struct {
+       const char *name;
+       enum spoolss_JobControl val;
+} cmdvals[] = {
+       {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
+       {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
+       {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
+       {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
+       {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
+       {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
+       {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
+       {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
+       {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
+};
+
+static enum spoolss_JobControl parse_setjob_command(const char *cmd)
+{
+       int i;
+
+       for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
+               if (strequal(cmdvals[i].name, cmd)) {
+                       return cmdvals[i].val;
+               }
+       }
+       return (enum spoolss_JobControl)atoi(cmd);
+}
+
+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;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
+
+       if (argc != 4) {
+               printf("Usage: %s printername job_id command\n", argv[0]);
+               printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
+                       "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
+               return WERR_OK;
+       }
+
+       job_id = atoi(argv[2]);
+       command = parse_setjob_command(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 = dcerpc_spoolss_SetJob(b, mem_ctx,
+                                      &hnd,
+                                      job_id,
+                                      NULL,
+                                      command,
+                                      &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
+               goto done;
+       }
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+done:
+       if (is_valid_policy_hnd(&hnd)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
+       }
+
+       return result;
+}
 
 /****************************************************************************
 ****************************************************************************/
@@ -2452,16 +2976,13 @@ static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
 {
        WERROR result;
        NTSTATUS status;
-       uint32_t i = 0;
        const char *printername;
-       POLICY_HND hnd;
-       uint32_t value_offered = 0;
-       const char *value_name = NULL;
+       struct policy_handle hnd;
        uint32_t value_needed;
        enum winreg_Type type;
-       uint8_t *data = NULL;
-       uint32_t data_offered = 0;
        uint32_t data_needed;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
+       struct spoolss_EnumPrinterData r;
 
        if (argc != 2) {
                printf("Usage: %s printername\n", argv[0]);
@@ -2482,53 +3003,56 @@ static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
 
        /* Enumerate data */
 
-       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)) {
-                       REGISTRY_VALUE v;
-                       fstrcpy(v.valuename, value_name);
-                       v.type = type;
-                       v.size = data_offered;
-                       v.data_p = data;
-                       display_reg_value(v);
-               }
+       r.in.handle = &hnd;
+       r.in.enum_index = 0;
+       r.in.value_offered = 0;
+       r.in.data_offered = 0;
+       r.out.value_name = NULL;
+       r.out.value_needed = &value_needed;
+       r.out.type = &type;
+       r.out.data = NULL;
+       r.out.data_needed = &data_needed;
+
+       status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
+       if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
+               goto done;
        }
 
-       if (W_ERROR_V(result) == ERRnomoreitems) {
-               result = W_ERROR(ERRsuccess);
+       if (!W_ERROR_IS_OK(r.out.result)) {
+               result = r.out.result;
+               goto done;
        }
 
+       r.in.data_offered       = *r.out.data_needed;
+       r.in.value_offered      = *r.out.value_needed;
+       r.out.data              = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
+       r.out.value_name        = talloc_zero_array(mem_ctx, char, r.in.value_offered);
+
+       do {
+
+               status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
+               if (!NT_STATUS_IS_OK(status)) {
+                       result = ntstatus_to_werror(status);
+                       goto done;
+               }
+
+               if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
+                       result = WERR_OK;
+                       break;
+               }
+
+               r.in.enum_index++;
+
+               display_reg_value(r.out.value_name, *r.out.type,
+                                 data_blob_const(r.out.data, r.in.data_offered));
+
+       } while (W_ERROR_IS_OK(r.out.result));
+
 done:
        if (is_valid_policy_hnd(&hnd)) {
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
        }
 
        return result;
@@ -2542,19 +3066,18 @@ static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
                                          const char **argv)
 {
        WERROR result;
-       uint32 i;
+       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;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        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]);
@@ -2563,28 +3086,34 @@ 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;
+       }
 
        /* 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->data,
+                                    info[i].data->length);
+       }
 
-done:
-       if (is_valid_policy_hnd(&hnd))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+ done:
+       if (is_valid_policy_hnd(&hnd)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
+       }
 
        return result;
 }
@@ -2599,21 +3128,27 @@ static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
        WERROR result;
        const char *printername;
        const char *keyname = NULL;
-       POLICY_HND hnd;
+       struct policy_handle hnd;
        const char **key_buffer = NULL;
        int i;
+       uint32_t offered = 0;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
-       if (argc < 2 || argc > 3) {
-               printf("Usage: %s printername [keyname]\n", argv[0]);
+       if (argc < 2 || argc > 4) {
+               printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
                return WERR_OK;
        }
 
-       if (argc == 3) {
+       if (argc >= 3) {
                keyname = argv[2];
        } else {
                keyname = "";
        }
 
+       if (argc == 4) {
+               offered = atoi(argv[3]);
+       }
+
        /* Open printer handle */
 
        RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
@@ -2632,7 +3167,7 @@ static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
                                               &hnd,
                                               keyname,
                                               &key_buffer,
-                                              0);
+                                              offered);
 
        if (!W_ERROR_IS_OK(result)) {
                goto done;
@@ -2645,7 +3180,8 @@ static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
  done:
 
        if (is_valid_policy_hnd(&hnd)) {
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
        }
 
        return result;
@@ -2660,10 +3196,11 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
 {
        const char *printername;
        const char *clientname;
-       POLICY_HND hnd;
+       struct policy_handle hnd = { 0, };
        WERROR result;
        NTSTATUS status;
        struct spoolss_NotifyOption option;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        if (argc != 2) {
                printf("Usage: %s printername\n", argv[0]);
@@ -2697,23 +3234,23 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
 
        option.types[0].type = PRINTER_NOTIFY_TYPE;
        option.types[0].count = 1;
-       option.types[0].fields = talloc_array(mem_ctx, enum spoolss_Field, 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] = PRINTER_NOTIFY_SERVER_NAME;
+       option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
 
        option.types[1].type = JOB_NOTIFY_TYPE;
        option.types[1].count = 1;
-       option.types[1].fields = talloc_array(mem_ctx, enum spoolss_Field, 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] = JOB_NOTIFY_PRINTER_NAME;
+       option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
 
-       clientname = talloc_asprintf(mem_ctx, "\\\\%s", global_myname());
+       clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
        if (!clientname) {
                result = WERR_NOMEM;
                goto done;
@@ -2721,7 +3258,7 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
 
        /* Send rffpcnex */
 
-       status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
+       status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
                                                                     &hnd,
                                                                     0,
                                                                     0,
@@ -2729,14 +3266,20 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
                                                                     123,
                                                                     &option,
                                                                     &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
+               goto done;
+       }
        if (!W_ERROR_IS_OK(result)) {
                printf("Error rffpcnex %s\n", argv[1]);
                goto done;
        }
 
 done:
-       if (is_valid_policy_hnd(&hnd))
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+       if (is_valid_policy_hnd(&hnd)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
+       }
 
        return result;
 }
@@ -2744,8 +3287,8 @@ 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 )
 {
        union spoolss_PrinterInfo info1, info2;
        WERROR werror;
@@ -2760,7 +3303,7 @@ static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
        if ( !W_ERROR_IS_OK(werror) ) {
                printf("failed (%s)\n", win_errstr(werror));
                talloc_destroy(mem_ctx);
-               return False;
+               return false;
        }
        printf("ok\n");
 
@@ -2773,26 +3316,26 @@ static bool compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
        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 )
 {
        union spoolss_PrinterInfo info1, info2;
        WERROR werror;
        TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
-       SEC_DESC *sd1, *sd2;
-       bool result = True;
+       struct security_descriptor *sd1, *sd2;
+       bool result = true;
 
 
        printf("Retrieving printer security for %s...", cli1->desthost);
@@ -2803,7 +3346,7 @@ static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *h
                                           &info1);
        if ( !W_ERROR_IS_OK(werror) ) {
                printf("failed (%s)\n", win_errstr(werror));
-               result = False;
+               result = false;
                goto done;
        }
        printf("ok\n");
@@ -2816,7 +3359,7 @@ static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *h
                                           &info2);
        if ( !W_ERROR_IS_OK(werror) ) {
                printf("failed (%s)\n", win_errstr(werror));
-               result = False;
+               result = false;
                goto done;
        }
        printf("ok\n");
@@ -2829,13 +3372,13 @@ static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *h
 
        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;
        }
 
@@ -2860,7 +3403,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;
 
@@ -2873,19 +3416,19 @@ static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
 
        /* first get the connection to the remote server */
 
-       nt_status = cli_full_connection(&cli_server2, global_myname(), argv[2],
+       nt_status = cli_full_connection(&cli_server2, lp_netbios_name(), argv[2],
                                        NULL, 0,
                                        "IPC$", "IPC",
                                        get_cmdline_auth_info_username(rpcclient_auth_info),
                                        lp_workgroup(),
                                        get_cmdline_auth_info_password(rpcclient_auth_info),
                                        get_cmdline_auth_info_use_kerberos(rpcclient_auth_info) ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
-                                       get_cmdline_auth_info_signing_state(rpcclient_auth_info), NULL);
+                                       get_cmdline_auth_info_signing_state(rpcclient_auth_info));
 
        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",
@@ -2933,8 +3476,11 @@ done:
        /* cleanup */
 
        printf("Closing printers...");
-       rpccli_spoolss_ClosePrinter( cli, mem_ctx, &hPrinter1, NULL );
-       rpccli_spoolss_ClosePrinter( cli2, mem_ctx, &hPrinter2, NULL );
+       {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
+               dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
+       }
        printf("ok\n");
 
        /* close the second remote connection */
@@ -3113,44 +3659,96 @@ static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
        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;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
+
+       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 = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
+                                               &handle,
+                                               &gdi_handle,
+                                               &devmode_ctr,
+                                               &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
+               goto done;
+       }
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+ done:
+       if (is_valid_policy_hnd(&gdi_handle)) {
+               WERROR _result;
+               dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
+       }
+       if (is_valid_policy_hnd(&handle)) {
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
+       }
+
+       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",                "" },
-       { "getjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job,            &syntax_spoolss, NULL, "Get print job",                       "" },
-       { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &syntax_spoolss, NULL, "Enumerate printer ports",             "" },
-       { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &syntax_spoolss, NULL, "Enumerate installed printer drivers", "" },
-       { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &syntax_spoolss, NULL, "Enumerate printers",                  "" },
-       { "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", "" },
-       { "enumprocs",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs,         &syntax_spoolss, NULL, "Enumerate Print Processors",          "" },
-       { "enumprocdatatypes",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &syntax_spoolss, NULL, "Enumerate Print Processor Data Types", "" },
-       { "enummonitors",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors,      &syntax_spoolss, NULL, "Enumerate Print Monitors", "" },
+       { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   &ndr_table_spoolss, NULL, "Add a print driver",                  "" },
+       { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       &ndr_table_spoolss, NULL, "Add a printer",                       "" },
+       { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       &ndr_table_spoolss, NULL, "Delete a printer driver",             "" },
+       { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     &ndr_table_spoolss, NULL, "Delete a printer driver with files",  "" },
+       { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          &ndr_table_spoolss, NULL, "Enumerate printer data",              "" },
+       { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       &ndr_table_spoolss, NULL, "Enumerate printer data for a key",    "" },
+       { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    &ndr_table_spoolss, NULL, "Enumerate printer keys",              "" },
+       { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          &ndr_table_spoolss, NULL, "Enumerate print jobs",                "" },
+       { "getjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job,            &ndr_table_spoolss, NULL, "Get print job",                       "" },
+       { "setjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job,            &ndr_table_spoolss, NULL, "Set print job",                       "" },
+       { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &ndr_table_spoolss, NULL, "Enumerate printer ports",             "" },
+       { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &ndr_table_spoolss, NULL, "Enumerate installed printer drivers", "" },
+       { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &ndr_table_spoolss, NULL, "Enumerate printers",                  "" },
+       { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     &ndr_table_spoolss, NULL, "Get print driver data",               "" },
+       { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   &ndr_table_spoolss, NULL, "Get printer driver data with keyname", ""},
+       { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          &ndr_table_spoolss, NULL, "Get print driver information",        "" },
+       { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       &ndr_table_spoolss, NULL, "Get print driver upload directory",   "" },
+       { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         &ndr_table_spoolss, NULL, "Get printer info",                    "" },
+       { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer,       &ndr_table_spoolss, NULL, "Open printer handle",                 "" },
+       { "openprinter_ex",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    &ndr_table_spoolss, NULL, "Open printer handle",                 "" },
+       { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          &ndr_table_spoolss, NULL, "Set printer driver",                  "" },
+       { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    &ndr_table_spoolss, NULL, "Get print processor directory",       "" },
+       { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            &ndr_table_spoolss, NULL, "Add form",                            "" },
+       { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            &ndr_table_spoolss, NULL, "Set form",                            "" },
+       { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            &ndr_table_spoolss, NULL, "Get form",                            "" },
+       { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         &ndr_table_spoolss, NULL, "Delete form",                         "" },
+       { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         &ndr_table_spoolss, NULL, "Enumerate forms",                     "" },
+       { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         &ndr_table_spoolss, NULL, "Set printer comment",                 "" },
+       { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     &ndr_table_spoolss, NULL, "Set printername",                 "" },
+       { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     &ndr_table_spoolss, NULL, "Set REG_SZ printer data",             "" },
+       { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           &ndr_table_spoolss, NULL, "Rffpcnex test", "" },
+       { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         &ndr_table_spoolss, NULL, "Printer comparison test", "" },
+       { "enumprocs",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs,         &ndr_table_spoolss, NULL, "Enumerate Print Processors",          "" },
+       { "enumprocdatatypes",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss, NULL, "Enumerate Print Processor Data Types", "" },
+       { "enummonitors",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors,      &ndr_table_spoolss, NULL, "Enumerate Print Monitors", "" },
+       { "createprinteric",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic,  &ndr_table_spoolss, NULL, "Create Printer IC", "" },
 
        { NULL }
 };