HACK large enumprinters trigger transs
[metze/samba/wip.git] / source3 / rpcclient / cmd_spoolss.c
index 0341b93c42a0a10785c9b8aa5c11aa01f2804b22..38881009ee091b406caa82f32766531c6039b4d3 100644 (file)
 
 #include "includes.h"
 #include "rpcclient.h"
-#include "../librpc/gen_ndr/cli_spoolss.h"
+#include "../librpc/gen_ndr/ndr_spoolss_c.h"
+#include "../librpc/gen_ndr/ndr_spoolss.h"
 #include "rpc_client/cli_spoolss.h"
 #include "rpc_client/init_spoolss.h"
-#include "registry.h"
-#include "registry/reg_objects.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"
+#include "popt_common_cmdline.h"
 
 #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
 { \
@@ -75,11 +80,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));
@@ -106,6 +111,7 @@ static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
        WERROR          werror;
        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> [access_mask]\n", argv[0]);
@@ -124,7 +130,7 @@ static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
                                               &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",
@@ -135,6 +141,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;
+}
 
 /****************************************************************************
 ****************************************************************************/
@@ -316,7 +371,7 @@ static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
                                             flags,
                                             name,
                                             level,
-                                            0,
+                                            4192,
                                             &count,
                                             &info);
        if (W_ERROR_IS_OK(result)) {
@@ -472,6 +527,7 @@ static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
        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]);
@@ -514,19 +570,25 @@ static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
        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 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;
 }
@@ -549,6 +611,7 @@ static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
        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);
@@ -590,19 +653,25 @@ static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
        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;
 }
@@ -619,6 +688,7 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
        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]);
@@ -685,7 +755,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;
@@ -694,25 +765,26 @@ static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
 /****************************************************************************
 ****************************************************************************/
 
-static void display_reg_value(struct regval_blob *value)
+static void display_reg_value(const char *name, enum winreg_Type type, DATA_BLOB blob)
 {
        const char *text = NULL;
-       DATA_BLOB blob;
 
-       switch(regval_type(value)) {
+       switch(type) {
        case REG_DWORD:
-               printf("%s: REG_DWORD: 0x%08x\n", regval_name(value),
-                      *((uint32_t *) regval_data_p(value)));
+               if (blob.length >= sizeof(uint32_t)) {
+                       printf("%s: REG_DWORD: 0x%08x\n", name, IVAL(blob.data,0));
+               } else {
+                       printf("%s: REG_DWORD: <invalid>\n", name);
+               }
                break;
        case REG_SZ:
-               blob = data_blob_const(regval_data_p(value), regval_size(value));
                pull_reg_sz(talloc_tos(), &blob, &text);
-               printf("%s: REG_SZ: %s\n", regval_name(value), text ? text : "");
+               printf("%s: REG_SZ: %s\n", name, text ? text : "");
                break;
        case REG_BINARY: {
-               char *hex = hex_encode_talloc(NULL, regval_data_p(value), regval_size(value));
+               char *hex = hex_encode_talloc(NULL, blob.data, blob.length);
                size_t i, len;
-               printf("%s: REG_BINARY:", regval_name(value));
+               printf("%s: REG_BINARY:", name);
                len = strlen(hex);
                for (i=0; i<len; i++) {
                        if (hex[i] == '\0') {
@@ -730,14 +802,13 @@ static void display_reg_value(struct regval_blob *value)
        case REG_MULTI_SZ: {
                uint32_t i;
                const char **values;
-               blob = data_blob_const(regval_data_p(value), regval_size(value));
 
                if (!pull_reg_multi_sz(NULL, &blob, &values)) {
                        d_printf("pull_reg_multi_sz failed\n");
                        break;
                }
 
-               printf("%s: REG_MULTI_SZ: \n", regval_name(value));
+               printf("%s: REG_MULTI_SZ: \n", name);
                for (i=0; values[i] != NULL; i++) {
                        d_printf("%s\n", values[i]);
                }
@@ -745,7 +816,7 @@ static void display_reg_value(struct regval_blob *value)
                break;
        }
        default:
-               printf("%s: unknown type %d\n", regval_name(value), regval_type(value));
+               printf("%s: unknown type %d\n", name, type);
        }
 
 }
@@ -762,6 +833,7 @@ static void display_printer_data(const char *v,
        union spoolss_PrinterData r;
        DATA_BLOB blob = data_blob_const(data, length);
        WERROR result;
+       enum ndr_err_code ndr_err;
 
        result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
        if (!W_ERROR_IS_OK(result)) {
@@ -792,6 +864,33 @@ static void display_printer_data(const char *v,
                }
                TALLOC_FREE(hex);
                putchar('\n');
+               putchar('\n');
+
+               if (strequal(v, "OsVersion")) {
+                       struct spoolss_OSVersion os;
+                       ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
+                               (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion);
+                       if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               // add output here;
+                               printf("OsMajor: %u\n", os.major);
+                               printf("OsMinor: %u\n", os.minor);
+                               printf("OsBuild: %u\n", os.build);
+                               NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
+                       }
+               }
+               if (strequal(v, "OsVersionEx")) {
+                       struct spoolss_OSVersionEx os;
+                       ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
+                               (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersionEx);
+                       if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                               printf("OsMajor: %u\n", os.major);
+                               printf("OsMinor: %u\n", os.minor);
+                               printf("OsBuild: %u\n", os.build);
+                               printf("ServicePackMajor: %u\n", os.service_pack_major);
+                               printf("ServicePackMinor: %u\n", os.service_pack_minor);
+                               NDR_PRINT_DEBUG(spoolss_OSVersionEx, &os);
+                       }
+               }
                break;
        }
        case REG_MULTI_SZ:
@@ -821,6 +920,7 @@ static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
        enum winreg_Type type;
        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]);
@@ -863,8 +963,10 @@ static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
        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;
 }
@@ -886,6 +988,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
        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",
@@ -920,7 +1023,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
                goto done;
        }
 
-       status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
+       status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
                                                 &pol,
                                                 keyname,
                                                 valuename,
@@ -929,13 +1032,17 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
                                                 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;
                data = talloc_zero_array(mem_ctx, uint8_t, offered);
                if (!data) {
                        goto done;
                }
-               status = rpccli_spoolss_GetPrinterDataEx(cli, mem_ctx,
+               status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
                                                         &pol,
                                                         keyname,
                                                         valuename,
@@ -947,6 +1054,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
        }
 
        if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
                goto done;
        }
 
@@ -959,8 +1067,10 @@ static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
 
 
  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;
 }
@@ -1192,6 +1302,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]);
@@ -1272,7 +1383,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) {
@@ -1359,7 +1471,7 @@ static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
                break;
        default:
                printf("unknown info level %d\n", level);
-               return WERR_UNKNOWN_LEVEL;
+               return WERR_INVALID_LEVEL;
        }
 
        return werror;
@@ -1434,6 +1546,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]);
@@ -1448,7 +1561,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,
@@ -1457,11 +1570,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,
@@ -1470,6 +1586,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)) {
@@ -1479,6 +1598,74 @@ static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
        return result;
 }
 
+/****************************************************************************
+****************************************************************************/
+
+static WERROR cmd_spoolss_getdriverpackagepath(struct rpc_pipe_client *cli,
+                                              TALLOC_CTX *mem_ctx,
+                                              int argc, const char **argv)
+{
+       HRESULT hresult;
+       NTSTATUS status;
+       const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
+       uint32_t offered;
+       uint32_t needed;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
+       const char *package_id = "";
+       const char *cab = NULL;
+
+       if (argc > 4) {
+               printf("Usage: %s [environment] [package_id]\n", argv[0]);
+               return WERR_OK;
+       }
+
+       /* Get the arguments need to open the printer handle */
+
+       if (argc >= 2) {
+               env = argv[1];
+       }
+
+       if (argc == 3) {
+               package_id = argv[2];
+       }
+
+       offered = 1;
+       cab = talloc_array(mem_ctx, char, offered);
+       status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
+                                                           cli->srv_name_slash,
+                                                           env,
+                                                           NULL,
+                                                           package_id,
+                                                           cab,
+                                                           offered,
+                                                           &needed,
+                                                           &hresult);
+       if (!NT_STATUS_IS_OK(status)) {
+               return ntstatus_to_werror(status);
+       }
+
+       if (W_ERROR_EQUAL(W_ERROR(WIN32_FROM_HRESULT(hresult)), WERR_INSUFFICIENT_BUFFER)) {
+               offered = needed;
+               cab = talloc_zero_array(mem_ctx, char, offered);
+
+               status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
+                                                                   cli->srv_name_slash,
+                                                                   env,
+                                                                   NULL,
+                                                                   package_id,
+                                                                   cab,
+                                                                   offered,
+                                                                   &needed,
+                                                                   &hresult);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return ntstatus_to_werror(status);
+               }
+       }
+
+       return W_ERROR(WIN32_FROM_HRESULT(hresult));
+}
+
+
 /****************************************************************************
 ****************************************************************************/
 
@@ -1526,7 +1713,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;
        }
 
@@ -1540,7 +1727,7 @@ static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
 /********************************************************************************
  fill in the members of a spoolss_AddDriverInfo3 struct using a character
  string in the form of
-        <Long Printer Name>:<Driver File Name>:<Data File Name>:\
+        <Long Driver Name>:<Driver File Name>:<Data File Name>:\
             <Config File Name>:<Help File Name>:<Language Monitor Name>:\
             <Default Data Type>:<Comma Separated list of Files>
  *******************************************************************************/
@@ -1549,7 +1736,7 @@ static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDrive
                                     char *args)
 {
        char    *str, *str2;
-       int count = 0;
+       size_t count = 0;
        char *saveptr = NULL;
        struct spoolss_StringArray *deps;
        const char **file_array = NULL;
@@ -1583,7 +1770,11 @@ static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDrive
        }
 
        while (str != NULL) {
-               add_string_to_array(deps, str, &file_array, &count);
+               bool ok;
+               ok = add_string_to_array(deps, str, &file_array, &count);
+               if (!ok) {
+                       return false;
+               }
                str = strtok_r(NULL, ",", &saveptr);
        }
 
@@ -1615,12 +1806,13 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
        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)
        {
                printf ("Usage: %s <Environment> \\\n", argv[0]);
-               printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
+               printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
                printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
                printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
                printf ("\t[version]\n");
@@ -1633,8 +1825,8 @@ 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]);
-               return WERR_INVALID_PARAM;
+               printf ("Error Unknown architecture [%s]\n", argv[1]);
+               return WERR_INVALID_PARAMETER;
        }
 
        set_drv_info_3_env(mem_ctx, &info3, arch);
@@ -1643,7 +1835,7 @@ static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
        if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
        {
                printf ("Error Invalid parameter list - %s.\n", argv[2]);
-               return WERR_INVALID_PARAM;
+               return WERR_INVALID_PARAMETER;
        }
 
        /* if printer driver version specified, override the default version
@@ -1658,7 +1850,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);
@@ -1746,6 +1938,7 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
        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);
@@ -1788,16 +1981,20 @@ static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
        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("SetPrinter call failed!\n");
-               goto done;;
+               goto done;
        }
 
        printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
@@ -1805,8 +2002,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;
 }
@@ -1821,6 +2020,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;
@@ -1829,38 +2029,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) ) {
@@ -1890,6 +2092,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) {
@@ -1899,20 +2102,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],
@@ -1937,6 +2143,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) {
@@ -1948,7 +2155,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,
@@ -1957,11 +2164,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,
@@ -1970,6 +2180,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)) {
@@ -1989,10 +2202,11 @@ static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        WERROR werror;
        NTSTATUS status;
        const char *printername;
-       union spoolss_AddFormInfo info;
+       struct spoolss_AddFormInfoCtr info_ctr;
        struct spoolss_AddFormInfo1 info1;
        struct spoolss_AddFormInfo2 info2;
        uint32_t level = 1;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* Parse the command arguments */
 
@@ -2029,7 +2243,8 @@ static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
                info1.area.right        = 20;
                info1.area.bottom       = 30;
 
-               info.info1 = &info1;
+               info_ctr.level          = 1;
+               info_ctr.info.info1     = &info1;
 
                break;
        case 2:
@@ -2048,23 +2263,30 @@ static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
                info2.display_name      = argv[2];
                info2.lang_id           = 0;
 
-               info.info2 = &info2;
+               info_ctr.level          = 2;
+               info_ctr.info.info2     = &info2;
 
                break;
+       default:
+               werror = WERR_INVALID_PARAMETER;
+               goto done;
        }
 
        /* Add the form */
 
-
-       status = rpccli_spoolss_AddForm(cli, mem_ctx,
+       status = dcerpc_spoolss_AddForm(b, mem_ctx,
                                        &handle,
-                                       level,
-                                       info,
+                                       &info_ctr,
                                        &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;
 }
@@ -2079,8 +2301,9 @@ static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        WERROR werror;
        NTSTATUS status;
        const char *printername;
-       union spoolss_AddFormInfo info;
+       struct spoolss_AddFormInfoCtr info_ctr;
        struct spoolss_AddFormInfo1 info1;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* Parse the command arguments */
 
@@ -2111,20 +2334,25 @@ static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
        info1.area.bottom       = 3000;
        info1.form_name         = argv[2];
 
-       info.info1 = &info1;
+       info_ctr.info.info1 = &info1;
+       info_ctr.level = 1;
 
        /* Set the form */
 
-       status = rpccli_spoolss_SetForm(cli, mem_ctx,
+       status = dcerpc_spoolss_SetForm(b, mem_ctx,
                                        &handle,
                                        argv[2],
-                                       1,
-                                       info,
+                                       &info_ctr,
                                        &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;
 }
@@ -2198,6 +2426,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 */
 
@@ -2223,7 +2452,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,
@@ -2232,10 +2461,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,
@@ -2244,10 +2477,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) {
@@ -2260,8 +2497,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;
 }
@@ -2277,6 +2516,7 @@ static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
        WERROR werror;
        NTSTATUS status;
        const char *printername;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* Parse the command arguments */
 
@@ -2298,17 +2538,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;
 }
@@ -2325,6 +2568,7 @@ static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
        const char *printername;
        uint32_t num_forms, level = 1, i;
        union spoolss_FormInfo *forms;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        /* Parse the command arguments */
 
@@ -2374,8 +2618,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;
 }
@@ -2390,11 +2636,12 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
        WERROR result;
        NTSTATUS status;
        const char *printername;
-       struct policy_handle 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) {
@@ -2426,7 +2673,7 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
 
        if (type == REG_NONE) {
                printf("Unknown data type: %s\n", argv[2]);
-               result =  WERR_INVALID_PARAM;
+               result =  WERR_INVALID_PARAMETER;
                goto done;
        }
 
@@ -2466,9 +2713,12 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
                break;
        case REG_MULTI_SZ: {
-               int i, num_strings;
+               int i;
+               size_t num_strings;
                const char **strings = NULL;
 
+               num_strings = 0;
+
                for (i=4; i<argc; i++) {
                        if (strcmp(argv[i], "NULL") == 0) {
                                argv[i] = "";
@@ -2476,13 +2726,13 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                        if (!add_string_to_array(mem_ctx, argv[i],
                                                 &strings,
                                                 &num_strings)) {
-                               result = WERR_NOMEM;
+                               result = WERR_NOT_ENOUGH_MEMORY;
                                goto done;
                        }
                }
                data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
                if (!data.string_array) {
-                       result = WERR_NOMEM;
+                       result = WERR_NOT_ENOUGH_MEMORY;
                        goto done;
                }
                for (i=0; i < num_strings; i++) {
@@ -2492,7 +2742,7 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                }
        default:
                printf("Unknown data type: %s\n", argv[2]);
-               result = WERR_INVALID_PARAM;
+               result = WERR_INVALID_PARAMETER;
                goto done;
        }
 
@@ -2501,13 +2751,18 @@ static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
                goto done;
        }
 
-       status = rpccli_spoolss_SetPrinterData(cli, mem_ctx,
+       status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
                                               &pol,
                                               argv[3], /* value_name */
                                               type,
                                               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;
@@ -2529,7 +2784,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;
@@ -2588,6 +2844,7 @@ static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
        const char *printername;
        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]);
@@ -2639,7 +2896,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;
@@ -2658,6 +2916,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]);
@@ -2715,7 +2974,8 @@ 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;
@@ -2761,6 +3021,7 @@ static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
        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]);
@@ -2786,20 +3047,24 @@ static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
 
        /* Set Job */
 
-       status = rpccli_spoolss_SetJob(cli, mem_ctx,
+       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)) {
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &hnd, NULL);
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
        }
 
        return result;
@@ -2814,16 +3079,13 @@ static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
 {
        WERROR result;
        NTSTATUS status;
-       uint32_t i = 0;
        const char *printername;
        struct policy_handle hnd;
-       uint32_t value_offered = 0;
-       const char *value_name = NULL;
        uint32_t value_needed;
        enum winreg_Type type;
-       uint8_t *data = NULL;
-       uint32_t data_offered = 0;
        uint32_t data_needed;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
+       struct spoolss_EnumPrinterData r;
 
        if (argc != 2) {
                printf("Usage: %s printername\n", argv[0]);
@@ -2844,61 +3106,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);
+       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;
+       }
 
-       data_offered    = data_needed;
-       value_offered   = value_needed;
-       data            = talloc_zero_array(mem_ctx, uint8_t, data_needed);
-       value_name      = talloc_zero_array(mem_ctx, char, value_needed);
-
-       while (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
-
-               status = rpccli_spoolss_EnumPrinterData(cli, mem_ctx,
-                                                       &hnd,
-                                                       i++,
-                                                       value_name,
-                                                       value_offered,
-                                                       &value_needed,
-                                                       &type,
-                                                       data,
-                                                       data_offered,
-                                                       &data_needed,
-                                                       &result);
-               if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(result)) {
-                       struct regval_blob *v;
-
-                       v = regval_compose(talloc_tos(),
-                                          value_name,
-                                          type,
-                                          data,
-                                          data_offered);
-                       if (v == NULL) {
-                               result = WERR_NOMEM;
-                               goto done;
-                       }
+       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 {
 
-                       display_reg_value(v);
-                       talloc_free(v);
+               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_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;
@@ -2917,6 +3174,7 @@ static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
        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]);
@@ -2956,7 +3214,8 @@ static WERROR cmd_spoolss_enum_data_ex( 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;
@@ -2976,6 +3235,7 @@ static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
        const char **key_buffer = NULL;
        int i;
        uint32_t offered = 0;
+       struct dcerpc_binding_handle *b = cli->binding_handle;
 
        if (argc < 2 || argc > 4) {
                printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
@@ -3023,7 +3283,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;
@@ -3038,10 +3299,11 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
 {
        const char *printername;
        const char *clientname;
-       struct policy_handle 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]);
@@ -3069,7 +3331,7 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
 
        option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
        if (option.types == NULL) {
-               result = WERR_NOMEM;
+               result = WERR_NOT_ENOUGH_MEMORY;
                goto done;
        }
 
@@ -3077,7 +3339,7 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
        option.types[0].count = 1;
        option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
        if (option.types[0].fields == NULL) {
-               result = WERR_NOMEM;
+               result = WERR_NOT_ENOUGH_MEMORY;
                goto done;
        }
        option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
@@ -3086,20 +3348,20 @@ static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
        option.types[1].count = 1;
        option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
        if (option.types[1].fields == NULL) {
-               result = WERR_NOMEM;
+               result = WERR_NOT_ENOUGH_MEMORY;
                goto done;
        }
        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;
+               result = WERR_NOT_ENOUGH_MEMORY;
                goto done;
        }
 
        /* Send rffpcnex */
 
-       status = rpccli_spoolss_RemoteFindFirstPrinterChangeNotifyEx(cli, mem_ctx,
+       status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
                                                                     &hnd,
                                                                     0,
                                                                     0,
@@ -3107,14 +3369,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;
 }
@@ -3228,8 +3496,6 @@ done:
 /****************************************************************************
 ****************************************************************************/
 
-extern struct user_auth_info *rpcclient_auth_info;
-
 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
                                     TALLOC_CTX *mem_ctx, int argc,
                                     const char **argv)
@@ -3251,24 +3517,29 @@ 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],
-                                       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);
+       nt_status = cli_full_connection(&cli_server2, lp_netbios_name(), argv[2],
+                               NULL, 0,
+                               "IPC$", "IPC",
+                               get_cmdline_auth_info_username(
+                                       popt_get_cmdline_auth_info()),
+                               lp_workgroup(),
+                               get_cmdline_auth_info_password(
+                                       popt_get_cmdline_auth_info()),
+                               get_cmdline_auth_info_use_kerberos(
+                                       popt_get_cmdline_auth_info()) ?
+                                       CLI_FULL_CONNECTION_USE_KERBEROS : 0,
+                               get_cmdline_auth_info_signing_state(
+                                       popt_get_cmdline_auth_info()));
 
        if ( !NT_STATUS_IS_OK(nt_status) )
-               return WERR_GENERAL_FAILURE;
+               return WERR_GEN_FAILURE;
 
-       nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss.syntax_id,
+       nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss,
                                             &cli2);
        if (!NT_STATUS_IS_OK(nt_status)) {
                printf("failed to open spoolss pipe on server %s (%s)\n",
                        argv[2], nt_errstr(nt_status));
-               return WERR_GENERAL_FAILURE;
+               return WERR_GEN_FAILURE;
        }
 
        /* now open up both printers */
@@ -3311,8 +3582,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 */
@@ -3500,6 +3774,7 @@ static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
        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]);
 
@@ -3513,21 +3788,129 @@ static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
 
        ZERO_STRUCT(devmode_ctr);
 
-       status = rpccli_spoolss_CreatePrinterIC(cli, mem_ctx,
+       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)) {
-               rpccli_spoolss_DeletePrinterIC(cli, mem_ctx, &gdi_handle, NULL);
+               WERROR _result;
+               dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
        }
        if (is_valid_policy_hnd(&handle)) {
-               rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
+               WERROR _result;
+               dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
+       }
+
+       return result;
+}
+
+static WERROR cmd_spoolss_play_gdi_script_on_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;
+       DATA_BLOB in,out;
+       uint32_t count = 0;
+
+       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;
+       }
+
+       in = data_blob_string_const("");
+       out = data_blob_talloc_zero(mem_ctx, 4);
+
+       status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
+                                                        &gdi_handle,
+                                                        in.data,
+                                                        in.length,
+                                                        out.data,
+                                                        out.length,
+                                                        0, /* ul */
+                                                        &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
+               goto done;
+       }
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+       count = IVAL(out.data, 0);
+
+       out = data_blob_talloc_zero(mem_ctx,
+                                   count * sizeof(struct UNIVERSAL_FONT_ID) + 4);
+
+       status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
+                                                        &gdi_handle,
+                                                        in.data,
+                                                        in.length,
+                                                        out.data,
+                                                        out.length,
+                                                        0, /* ul */
+                                                        &result);
+       if (!NT_STATUS_IS_OK(status)) {
+               result = ntstatus_to_werror(status);
+               goto done;
+       }
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+       {
+               enum ndr_err_code ndr_err;
+               struct UNIVERSAL_FONT_ID_ctr r;
+
+               ndr_err = ndr_pull_struct_blob(&out, mem_ctx, &r,
+                       (ndr_pull_flags_fn_t)ndr_pull_UNIVERSAL_FONT_ID_ctr);
+               if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+                       NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr, &r);
+               }
+       }
+
+ 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;
@@ -3536,43 +3919,393 @@ static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
 /* List of commands exported by this module */
 struct cmd_set spoolss_commands[] = {
 
-       { "SPOOLSS"  },
-
-       { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   &ndr_table_spoolss.syntax_id, NULL, "Add a print driver",                  "" },
-       { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       &ndr_table_spoolss.syntax_id, NULL, "Add a printer",                       "" },
-       { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver",             "" },
-       { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     &ndr_table_spoolss.syntax_id, NULL, "Delete a printer driver with files",  "" },
-       { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data",              "" },
-       { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer data for a key",    "" },
-       { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer keys",              "" },
-       { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          &ndr_table_spoolss.syntax_id, NULL, "Enumerate print jobs",                "" },
-       { "getjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_get_job,            &ndr_table_spoolss.syntax_id, NULL, "Get print job",                       "" },
-       { "setjob",             RPC_RTYPE_WERROR, NULL, cmd_spoolss_set_job,            &ndr_table_spoolss.syntax_id, NULL, "Set print job",                       "" },
-       { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate printer ports",             "" },
-       { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       &ndr_table_spoolss.syntax_id, NULL, "Enumerate installed printer drivers", "" },
-       { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      &ndr_table_spoolss.syntax_id, NULL, "Enumerate printers",                  "" },
-       { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     &ndr_table_spoolss.syntax_id, NULL, "Get print driver data",               "" },
-       { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   &ndr_table_spoolss.syntax_id, NULL, "Get printer driver data with keyname", ""},
-       { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          &ndr_table_spoolss.syntax_id, NULL, "Get print driver information",        "" },
-       { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       &ndr_table_spoolss.syntax_id, NULL, "Get print driver upload directory",   "" },
-       { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         &ndr_table_spoolss.syntax_id, NULL, "Get printer info",                    "" },
-       { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    &ndr_table_spoolss.syntax_id, NULL, "Open printer handle",                 "" },
-       { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          &ndr_table_spoolss.syntax_id, NULL, "Set printer driver",                  "" },
-       { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    &ndr_table_spoolss.syntax_id, NULL, "Get print processor directory",       "" },
-       { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            &ndr_table_spoolss.syntax_id, NULL, "Add form",                            "" },
-       { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            &ndr_table_spoolss.syntax_id, NULL, "Set form",                            "" },
-       { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            &ndr_table_spoolss.syntax_id, NULL, "Get form",                            "" },
-       { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         &ndr_table_spoolss.syntax_id, NULL, "Delete form",                         "" },
-       { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate forms",                     "" },
-       { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         &ndr_table_spoolss.syntax_id, NULL, "Set printer comment",                 "" },
-       { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     &ndr_table_spoolss.syntax_id, NULL, "Set printername",                 "" },
-       { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     &ndr_table_spoolss.syntax_id, NULL, "Set REG_SZ printer data",             "" },
-       { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           &ndr_table_spoolss.syntax_id, NULL, "Rffpcnex test", "" },
-       { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         &ndr_table_spoolss.syntax_id, NULL, "Printer comparison test", "" },
-       { "enumprocs",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_procs,         &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processors",          "" },
-       { "enumprocdatatypes",  RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_proc_data_types, &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Processor Data Types", "" },
-       { "enummonitors",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_monitors,      &ndr_table_spoolss.syntax_id, NULL, "Enumerate Print Monitors", "" },
-       { "createprinteric",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_create_printer_ic,  &ndr_table_spoolss.syntax_id, NULL, "Create Printer IC", "" },
-
-       { NULL }
+       {
+               .name = "SPOOLSS",
+       },
+
+       {
+               .name               = "adddriver",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_addprinterdriver,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Add a print driver",
+               .usage              = "",
+               .use_netlogon_creds = false,
+       },
+       {
+               .name               = "addprinter",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_addprinterex,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Add a printer",
+               .usage              = "",
+       },
+       {
+               .name               = "deldriver",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_deletedriver,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Delete a printer driver",
+               .usage              = "",
+       },
+       {
+               .name               = "deldriverex",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_deletedriverex,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Delete a printer driver with files",
+               .usage              = "",
+       },
+       {
+               .name               = "enumdata",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_enum_data,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Enumerate printer data",
+               .usage              = "",
+       },
+       {
+               .name               = "enumdataex",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_enum_data_ex,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Enumerate printer data for a key",
+               .usage              = "",
+       },
+       {
+               .name               = "enumkey",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_enum_printerkey,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Enumerate printer keys",
+               .usage              = "",
+       },
+       {
+               .name               = "enumjobs",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_enum_jobs,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Enumerate print jobs",
+               .usage              = "",
+       },
+       {
+               .name               = "getjob",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_get_job,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Get print job",
+               .usage              = "",
+       },
+       {
+               .name               = "setjob",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_set_job,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Set print job",
+               .usage              = "",
+       },
+       {
+               .name               = "enumports",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_enum_ports,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Enumerate printer ports",
+               .usage              = "",
+       },
+       {
+               .name               = "enumdrivers",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_enum_drivers,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Enumerate installed printer drivers",
+               .usage              = "",
+       },
+       {
+               .name               = "enumprinters",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_enum_printers,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Enumerate printers",
+               .usage              = "",
+       },
+       {
+               .name               = "getdata",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_getprinterdata,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Get print driver data",
+               .usage              = "",
+       },
+       {
+               .name               = "getdataex",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_getprinterdataex,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Get printer driver data with keyname",
+               .usage              = "",
+       },
+       {
+               .name               = "getdriver",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_getdriver,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Get print driver information",
+               .usage              = "",
+       },
+       {
+               .name               = "getdriverdir",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_getdriverdir,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Get print driver upload directory",
+               .usage              = "",
+       },
+       {
+               .name               = "getdriverpackagepath",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_getdriverpackagepath,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Get print driver package download directory",
+               .usage              = "",
+       },
+       {
+               .name               = "getprinter",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_getprinter,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Get printer info",
+               .usage              = "",
+       },
+       {
+               .name               = "openprinter",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_open_printer,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Open printer handle",
+               .usage              = "",
+       },
+       {
+               .name               = "openprinter_ex",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_open_printer_ex,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Open printer handle",
+               .usage              = "",
+       },
+       {
+               .name               = "setdriver",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_setdriver,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Set printer driver",
+               .usage              = "",
+       },
+       {
+               .name               = "getprintprocdir",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_getprintprocdir,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Get print processor directory",
+               .usage              = "",
+       },
+       {
+               .name               = "addform",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_addform,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Add form",
+               .usage              = "",
+       },
+       {
+               .name               = "setform",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_setform,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Set form",
+               .usage              = "",
+       },
+       {
+               .name               = "getform",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_getform,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Get form",
+               .usage              = "",
+       },
+       {
+               .name               = "deleteform",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_deleteform,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Delete form",
+               .usage              = "",
+       },
+       {
+               .name               = "enumforms",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_enum_forms,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Enumerate forms",
+               .usage              = "",
+       },
+       {
+               .name               = "setprinter",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_setprinter,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Set printer comment",
+               .usage              = "",
+       },
+       {
+               .name               = "setprintername",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_setprintername,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Set printername",
+               .usage              = "",
+       },
+       {
+               .name               = "setprinterdata",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_setprinterdata,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Set REG_SZ printer data",
+               .usage              = "",
+       },
+       {
+               .name               = "rffpcnex",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_rffpcnex,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Rffpcnex test",
+               .usage              = "",
+       },
+       {
+               .name               = "printercmp",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_printercmp,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Printer comparison test",
+               .usage              = "",
+       },
+       {
+               .name               = "enumprocs",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_enum_procs,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Enumerate Print Processors",
+               .usage              = "",
+       },
+       {
+               .name               = "enumprocdatatypes",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_enum_proc_data_types,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Enumerate Print Processor Data Types",
+               .usage              = "",
+       },
+       {
+               .name               = "enummonitors",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_enum_monitors,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Enumerate Print Monitors",
+               .usage              = "",
+       },
+       {
+               .name               = "createprinteric",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_create_printer_ic,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Create Printer IC",
+               .usage              = "",
+       },
+       {
+               .name               = "playgdiscriptonprinteric",
+               .returntype         = RPC_RTYPE_WERROR,
+               .ntfn               = NULL,
+               .wfn                = cmd_spoolss_play_gdi_script_on_printer_ic,
+               .table              = &ndr_table_spoolss,
+               .rpc_pipe           = NULL,
+               .description        = "Create Printer IC",
+               .usage              = "",
+       },
+
+       {
+               .name = NULL,
+       },
 };