Removed version number from file header.
[samba.git] / source / rpcclient / cmd_spoolss.c
index 181ef97deccf3f9919dc6952b3fcb58958e7bb5b..45a553beb2d7fcc8555f26c87d33f2314722592d 100644 (file)
@@ -1,12 +1,12 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 1.9.
-   NT Domain Authentication SMB / MSRPC client
-   Copyright (C) Andrew Tridgell              1994-2000
-   Copyright (C) Luke Kenneth Casson Leighton 1996-2000
-   Copyright (C) Jean-Francois Micouleau      1999-2000
-   Copyright (C) Gerald Carter                     2000
-   
+   Unix SMB/CIFS implementation.
+   RPC pipe client
+
+   Copyright (C) Gerald Carter                     2001
+   Copyright (C) Tim Potter                        2000
+   Copyright (C) Andrew Tridgell              1992-1999
+   Copyright (C) Luke Kenneth Casson Leighton 1996-1999
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
 */
 
 #include "includes.h"
-#include "nterr.h"
-#include "rpc_parse.h"
-#include "rpc_client.h"
 #include "rpcclient.h"
 
-extern int DEBUGLEVEL;
-
-#define DEBUG_TESTING
-
-extern FILE* out_hnd;
-
-extern struct user_creds *usr_creds;
+struct table_node {
+       char    *long_archi;
+       char    *short_archi;
+       int     version;
+};
+struct table_node archi_table[]= {
+
+       {"Windows 4.0",          "WIN40",       0 },
+       {"Windows NT x86",       "W32X86",      2 },
+       {"Windows NT R4000",     "W32MIPS",     2 },
+       {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
+       {"Windows NT PowerPC",   "W32PPC",      2 },
+       {NULL,                   "",            -1 }
+};
 
 /****************************************************************************
 function to do the mapping between the long architecture name and
 the short one.
 ****************************************************************************/
-static BOOL get_short_archi(char *short_archi, char *long_archi)
+BOOL get_short_archi(char *short_archi, char *long_archi)
 {
-        struct table {
-                char *long_archi;
-                char *short_archi;
-        };
-
-        struct table archi_table[]=
-        {
-                {"Windows 4.0",          "WIN40"    },
-                {"Windows NT x86",       "W32X86"   },
-                {"Windows NT R4000",     "W32MIPS"  },
-                {"Windows NT Alpha_AXP", "W32ALPHA" },
-                {"Windows NT PowerPC",   "W32PPC"   },
-                {NULL,                   ""         }
-        };
-
         int i=-1;
 
         DEBUG(107,("Getting architecture dependant directory\n"));
@@ -66,8 +56,8 @@ static BOOL get_short_archi(char *short_archi, char *long_archi)
                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
 
         if (archi_table[i].long_archi==NULL) {
-                DEBUGADD(107,("Unknown architecture [%s] !\n", long_archi));
-                return FALSE;
+                DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
+                return False;
         }
 
         StrnCpy (short_archi, archi_table[i].short_archi, strlen(archi_table[i].short_archi));
@@ -76,712 +66,798 @@ static BOOL get_short_archi(char *short_archi, char *long_archi)
         DEBUGADD(108,("long architecture: [%s]\n", long_archi));
         DEBUGADD(108,("short architecture: [%s]\n", short_archi));
 
-        return TRUE;
+        return True;
 }
 
-/****************************************************************************
-nt spoolss query
-****************************************************************************/
-uint32 cmd_spoolss_enum_printers(struct client_info *info, int argc, char *argv[])
+
+/**********************************************************************
+ * dummy function  -- placeholder
+  */
+static NTSTATUS cmd_spoolss_not_implemented(struct cli_state *cli, 
+                                            TALLOC_CTX *mem_ctx,
+                                            int argc, char **argv)
 {
-       PRINTER_INFO_CTR ctr;
-       
-       uint32 flags;
-       uint32 level = 1;
+       printf ("(*) This command is not currently implemented.\n");
+       return NT_STATUS_OK;
+}
 
-       fstring srv_name;
-       fstrcpy(srv_name, "\\\\");
-       fstrcat(srv_name, info->dest_host);
-       strupper(srv_name);
+/***********************************************************************
+ * Get printer information
+ */
+static NTSTATUS cmd_spoolss_open_printer_ex(struct cli_state *cli, 
+                                            TALLOC_CTX *mem_ctx,
+                                            int argc, char **argv)
+{
+       WERROR          werror;
+       pstring         printername;
+       fstring         servername, user;
+       POLICY_HND      hnd;
        
-       flags=PRINTER_ENUM_LOCAL;
-
-       if (msrpc_spoolss_enum_printers(srv_name, flags, level, ctr))
-               DEBUG(5,("cmd_spoolss_enum_printer: query succeeded\n"));
-       else
-               report(out_hnd, "FAILED\n");
-               
-               
-#if 0  /* JERRY */
-       flags=PRINTER_ENUM_NAME;
-
-       if (msrpc_spoolss_enum_printers(srv_name, flags, level, ctr))
-               DEBUG(5,("cmd_spoolss_enum_printer: query succeeded\n"));
-       else
-               report(out_hnd, "FAILED\n");
-
-       flags=PRINTER_ENUM_SHARED|PRINTER_ENUM_NAME;
+       if (argc != 2) {
+               printf("Usage: %s <printername>\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+       
+       if (!cli)
+               return NT_STATUS_UNSUCCESSFUL;
 
-       if (msrpc_spoolss_enum_printers(srv_name, flags, level, ctr))
-               DEBUG(5,("cmd_spoolss_enum_printer: query succeeded\n"));
-       else
-               report(out_hnd, "FAILED\n");
+       slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       strupper (servername);
+       fstrcpy  (user, cli->user_name);
+       fstrcpy  (printername, argv[1]);
 
-       flags=PRINTER_ENUM_CONNECTIONS;
+       /* Open the printer handle */
 
-       if (msrpc_spoolss_enum_printers(srv_name, flags, level, ctr))
-               DEBUG(5,("cmd_spoolss_enum_printer: query succeeded\n"));
-       else
-               report(out_hnd, "FAILED\n");
-               
-       flags=PRINTER_ENUM_NETWORK;
+       werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+                                            "", MAXIMUM_ALLOWED_ACCESS, 
+                                            servername, user, &hnd);
 
-       if (msrpc_spoolss_enum_printers(srv_name, flags, level, ctr))
-               DEBUG(5,("cmd_spoolss_enum_printer: query succeeded\n"));
-       else
-               report(out_hnd, "FAILED\n");
-               
-       flags=PRINTER_ENUM_REMOTE;
+       if (W_ERROR_IS_OK(werror)) {
+               printf("Printer %s opened successfully\n", printername);
+               werror = cli_spoolss_close_printer(cli, mem_ctx, &hnd);
 
-       if (msrpc_spoolss_enum_printers(srv_name, flags, level, ctr))
-               DEBUG(5,("cmd_spoolss_enum_printer: query succeeded\n"));
-       else
-               report(out_hnd, "FAILED\n");
-#endif
+               if (!W_ERROR_IS_OK(werror)) {
+                       printf("Error closing printer handle! (%s)\n", 
+                               get_dos_error_msg(werror));
+               }
+       }
 
-       return NT_STATUS_NOPROBLEMO;
+       return werror_to_ntstatus(werror);
 }
 
+
 /****************************************************************************
-nt spoolss query
+printer info level 0 display function
 ****************************************************************************/
-uint32 cmd_spoolss_enum_ports(struct client_info *info, int argc, char *argv[])
+static void display_print_info_0(PRINTER_INFO_0 *i0)
 {
-       PORT_INFO_CTR ctr;
-       uint32 level;
-       fstring srv_name;
+       fstring         name = "";
+       fstring         servername = "";
+
+       if (i0->printername.buffer)
+               rpcstr_pull(name, i0->printername.buffer, sizeof(name), 0, STR_TERMINATE);
+
+       if (i0->servername.buffer)
+               rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), 0,STR_TERMINATE);
+  
+       printf("\tprintername:[%s]\n", name);
+       printf("\tservername:[%s]\n", servername);
+       printf("\tcjobs:[0x%x]\n", i0->cjobs);
+       printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
        
-       if (argc < 1)
-       {
-               report (out_hnd, "spoolenumports <level>\n");
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-               
-       fstrcpy(srv_name, "\\\\");
-       fstrcat(srv_name, info->dest_host);
-       strupper(srv_name);
+       printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month, 
+              i0->day, i0->dayofweek);
+       printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute, 
+              i0->second, i0->milliseconds);
        
-       level = atoi(argv[1]);
+       printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
+       printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
        
-       if (msrpc_spoolss_enum_ports(srv_name, level, &ctr))
-               DEBUG(5,("cmd_spoolss_enum_printer: query succeeded\n"));
-       else
-               report(out_hnd, "FAILED\n");
-               
-       return NT_STATUS_NOPROBLEMO;
+       printf("\tmajorversion:[0x%x]\n", i0->major_version);
+       printf("\tbuildversion:[0x%x]\n", i0->build_version);
+       
+       printf("\tunknown7:[0x%x]\n", i0->unknown7);
+       printf("\tunknown8:[0x%x]\n", i0->unknown8);
+       printf("\tunknown9:[0x%x]\n", i0->unknown9);
+       printf("\tsession_counter:[0x%x]\n", i0->session_counter);
+       printf("\tunknown11:[0x%x]\n", i0->unknown11);
+       printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
+       printf("\tunknown13:[0x%x]\n", i0->unknown13);
+       printf("\tunknown14:[0x%x]\n", i0->unknown14);
+       printf("\tunknown15:[0x%x]\n", i0->unknown15);
+       printf("\tunknown16:[0x%x]\n", i0->unknown16);
+       printf("\tchange_id:[0x%x]\n", i0->change_id);
+       printf("\tunknown18:[0x%x]\n", i0->unknown18);
+       printf("\tstatus:[0x%x]\n", i0->status);
+       printf("\tunknown20:[0x%x]\n", i0->unknown20);
+       printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
+       printf("\tunknown22:[0x%x]\n", i0->unknown22);
+       printf("\tunknown23:[0x%x]\n", i0->unknown23);
+       printf("\tunknown24:[0x%x]\n", i0->unknown24);
+       printf("\tunknown25:[0x%x]\n", i0->unknown25);
+       printf("\tunknown26:[0x%x]\n", i0->unknown26);
+       printf("\tunknown27:[0x%x]\n", i0->unknown27);
+       printf("\tunknown28:[0x%x]\n", i0->unknown28);
+       printf("\tunknown29:[0x%x]\n", i0->unknown29);
 }
 
 /****************************************************************************
-nt spoolss query
+printer info level 1 display function
 ****************************************************************************/
-uint32 cmd_spoolss_enum_printerdata(struct client_info *info, int argc, char *argv[])
+static void display_print_info_1(PRINTER_INFO_1 *i1)
 {
-       fstring srv_name;
-       fstring station;
-       char *printer_name;
-
-       if (argc < 1) {
-               report(out_hnd, "spoolenumdata <printer name>\n");
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-
-       printer_name = argv[1];
-
-       fstrcpy(station, "\\\\");
-       fstrcat(station, info->myhostname);
-       strupper(station);
-
-       fstrcpy(srv_name, "\\\\");
-       fstrcat(srv_name, info->dest_host);
-       strupper(srv_name);
-
-       if (!strnequal("\\\\", printer_name, 2))
-       {
-               fstrcat(srv_name, "\\");
-               fstrcat(srv_name, printer_name);
-               printer_name = srv_name;
-       }
-
-       DEBUG(0,("spoolenumdata - printer: %s station: %s user: %s\n", printer_name, station, usr_creds->ntc.user_name));
-
-       if (msrpc_spoolss_enum_printerdata( printer_name, station,
-                               usr_creds->ntc.user_name))
-       {
-               DEBUG(0,("cmd_spoolss_enum_printerdata: query succeeded\n"));
-               return NT_STATUS_NOPROBLEMO;
-       }
-       report(out_hnd, "FAILED\n");
-       return NT_STATUS_UNSUCCESSFUL;
+       fstring desc = "";
+       fstring name = "";
+       fstring comm = "";
+
+       if (i1->description.buffer)
+               rpcstr_pull(desc, i1->description.buffer, sizeof(desc), 0, 
+                           STR_TERMINATE);
+
+       if (i1->name.buffer)
+               rpcstr_pull(name, i1->name.buffer, sizeof(name), 0, 
+                           STR_TERMINATE);
+
+       if (i1->comment.buffer)
+               rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), 0, 
+                           STR_TERMINATE);
+
+       printf("\tflags:[0x%x]\n", i1->flags);
+       printf("\tname:[%s]\n", name);
+       printf("\tdescription:[%s]\n", desc);
+       printf("\tcomment:[%s]\n\n", comm);
 }
 
 /****************************************************************************
-nt spoolss query
+printer info level 2 display function
 ****************************************************************************/
-uint32 cmd_spoolss_getprinter(struct client_info *info, int argc, char *argv[])
+static void display_print_info_2(PRINTER_INFO_2 *i2)
 {
-        PRINTER_INFO_CTR ctr;
-        fstring srv_name;
-        fstring station;
-        char *printer_name;
-        uint32 level;
-
-        if (argc < 1) {
-                report(out_hnd, "spoolgetprinter <printer name>\n");
-                return NT_STATUS_INVALID_PARAMETER;
-        }
-
-        printer_name = argv[1];
-
-        fstrcpy(station, "\\\\");
-        fstrcat(station, info->myhostname);
-        strupper(station);
-
-        fstrcpy(srv_name, "\\\\");
-        fstrcat(srv_name, info->dest_host);
-        strupper(srv_name);
-
-        if (!strnequal("\\\\", printer_name, 2))
-        {
-                fstrcat(srv_name, "\\");
-                fstrcat(srv_name, printer_name);
-                printer_name = srv_name;
-        }
-
-        if (argc < 3)
-                level=2;
-        else
-                level = atoi(argv[2]);
-
-        if (msrpc_spoolss_getprinter(printer_name, level, station, "Administrator", ctr))
-                DEBUG(5,("cmd_spoolss_getprinter: query succeeded\n"));
-        else
-                report(out_hnd, "FAILED\n");
-
-        return NT_STATUS_NOPROBLEMO;
+       fstring servername = "";
+       fstring printername = "";
+       fstring sharename = "";
+       fstring portname = "";
+       fstring drivername = "";
+       fstring comment = "";
+       fstring location = "";
+       fstring sepfile = "";
+       fstring printprocessor = "";
+       fstring datatype = "";
+       fstring parameters = "";
+       
+       if (i2->servername.buffer)
+               rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), 0, STR_TERMINATE);
+
+       if (i2->printername.buffer)
+               rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), 0, STR_TERMINATE);
+
+       if (i2->sharename.buffer)
+               rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), 0, STR_TERMINATE);
+
+       if (i2->portname.buffer)
+               rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), 0, STR_TERMINATE);
+
+       if (i2->drivername.buffer)
+               rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), 0, STR_TERMINATE);
+
+       if (i2->comment.buffer)
+               rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), 0, STR_TERMINATE);
+
+       if (i2->location.buffer)
+               rpcstr_pull(location, i2->location.buffer,sizeof(location), 0, STR_TERMINATE);
+
+       if (i2->sepfile.buffer)
+               rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), 0, STR_TERMINATE);
+
+       if (i2->printprocessor.buffer) 
+               rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), 0, STR_TERMINATE);
+
+       if (i2->datatype.buffer)
+               rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), 0, STR_TERMINATE);
+
+       if (i2->parameters.buffer)
+               rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), 0, STR_TERMINATE);
+
+       printf("\tservername:[%s]\n", servername);
+       printf("\tprintername:[%s]\n", printername);
+       printf("\tsharename:[%s]\n", sharename);
+       printf("\tportname:[%s]\n", portname);
+       printf("\tdrivername:[%s]\n", drivername);
+       printf("\tcomment:[%s]\n", comment);
+       printf("\tlocation:[%s]\n", location);
+       printf("\tsepfile:[%s]\n", sepfile);
+       printf("\tprintprocessor:[%s]\n", printprocessor);
+       printf("\tdatatype:[%s]\n", datatype);
+       printf("\tparameters:[%s]\n", parameters);
+       printf("\tattributes:[0x%x]\n", i2->attributes);
+       printf("\tpriority:[0x%x]\n", i2->priority);
+       printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
+       printf("\tstarttime:[0x%x]\n", i2->starttime);
+       printf("\tuntiltime:[0x%x]\n", i2->untiltime);
+       printf("\tstatus:[0x%x]\n", i2->status);
+       printf("\tcjobs:[0x%x]\n", i2->cjobs);
+       printf("\taverageppm:[0x%x]\n", i2->averageppm);
+
+       if (i2->secdesc) display_sec_desc(i2->secdesc);
 }
 
-
-static void display_spool_job_info_ctr( const char* printer_name,
-                                const char* station,
-                                uint32 level,
-                                uint32 num, void *const *const ctr)
+/****************************************************************************
+printer info level 3 display function
+****************************************************************************/
+static void display_print_info_3(PRINTER_INFO_3 *i3)
 {
-        display_job_info_ctr(out_hnd, ACTION_HEADER   , level, num, ctr);
-        display_job_info_ctr(out_hnd, ACTION_ENUMERATE, level, num, ctr);
-        display_job_info_ctr(out_hnd, ACTION_FOOTER   , level, num, ctr);
+       printf("\tflags:[0x%x]\n", i3->flags);
+
+       display_sec_desc(i3->secdesc);
 }
 
-/****************************************************************************
-nt spoolss query
-****************************************************************************/
-uint32 cmd_spoolss_enum_jobs(struct client_info *info, int argc, char *argv[])
+/* Enumerate printers */
+
+static NTSTATUS cmd_spoolss_enum_printers(struct cli_state *cli, 
+                                          TALLOC_CTX *mem_ctx,
+                                          int argc, char **argv)
 {
-        fstring srv_name;
-        fstring station;
-        char *printer_name;
+       WERROR                  result;
+       uint32                  info_level = 1;
+       PRINTER_INFO_CTR        ctr;
+       uint32                  i = 0, num_printers, needed;
 
-        void **ctr = NULL;
-        uint32 level = 1;
+       if (argc > 2) 
+       {
+               printf("Usage: %s [level]\n", argv[0]);
+               return NT_STATUS_OK;
+       }
 
-        if (argc < 1) {
-                report(out_hnd, "spooljobs <printer name>\n");
-                return NT_STATUS_INVALID_PARAMETER;
-        }
+       if (argc == 2) {
+               info_level = atoi(argv[1]);
+       }
 
-        printer_name = argv[1];
+       /* Enumerate printers  -- Should we enumerate types other 
+          than PRINTER_ENUM_LOCAL?  Maybe accept as a parameter?  --jerry */
 
-        fstrcpy(station, "\\\\");
-        fstrcat(station, info->myhostname);
-        strupper(station);
+       ZERO_STRUCT(ctr);
 
-        fstrcpy(srv_name, "\\\\");
-        fstrcat(srv_name, info->dest_host);
-        strupper(srv_name);
+       result = cli_spoolss_enum_printers(
+               cli, mem_ctx, 0, &needed, PRINTER_ENUM_LOCAL, 
+               info_level, &num_printers, &ctr);
 
-        if (!strnequal("\\\\", printer_name, 2))
-        {
-                fstrcat(srv_name, "\\");
-                fstrcat(srv_name, printer_name);
-                printer_name = srv_name;
-        }
+       if (W_ERROR_V(result) == ERRinsufficientbuffer)
+               result = cli_spoolss_enum_printers(
+                       cli, mem_ctx, needed, NULL, PRINTER_ENUM_LOCAL, 
+                       info_level, &num_printers, &ctr);
 
-        DEBUG(4,("spoolopen - printer: %s station: %s user: %s\n", printer_name, 
-                 station, usr_creds->ntc.user_name));
+       if (W_ERROR_IS_OK(result)) {
+               if (!num_printers)
+                       printf ("No Printers printers returned.\n");
+       
+               switch(info_level) {
+               case 0:
+                       for (i=0; i < num_printers; i++)
+                               display_print_info_0(&ctr.printers_0[i]);
+                       break;
+               case 1:
+                       for (i=0; i < num_printers; i++)
+                               display_print_info_1(&ctr.printers_1[i]);
+                       break;
+               case 2:
+                       for (i=0; i < num_printers; i++)
+                               display_print_info_2(&ctr.printers_2[i]);
+                       break;
+               case 3:
+                       for (i=0; i < num_printers; i++)
+                               display_print_info_3(&ctr.printers_3[i]);
+                       break;
+               default:
+                       printf("unknown info level %d\n", info_level);
+                       break;
+               }
+       }
 
-        if (msrpc_spoolss_enum_jobs( printer_name, station,
-                                usr_creds->ntc.user_name,
-                                level, &ctr, display_spool_job_info_ctr))
-        {
-                DEBUG(5,("cmd_spoolss_enum_jobs: query succeeded\n"));
-                return NT_STATUS_NOPROBLEMO;
-        }
-        report(out_hnd, "FAILED\n");
-        return NT_STATUS_UNSUCCESSFUL;
+       return werror_to_ntstatus(result);
 }
 
 /****************************************************************************
-nt spoolss query
+port info level 1 display function
 ****************************************************************************/
-uint32 cmd_spoolss_open_printer_ex(struct client_info *info, int argc, char *argv[])
+static void display_port_info_1(PORT_INFO_1 *i1)
 {
-        fstring srv_name;
-        fstring station;
-        char *printer_name;
-        POLICY_HND hnd;
-
-        BOOL res = True;
-
-        if (argc < 1)
-        {
-                report(out_hnd, "spoolopen <printer name>\n");
-                return NT_STATUS_INVALID_PARAMETER;
-        }
-
-        printer_name = argv[1];
-
-        fstrcpy(station, "\\\\");
-        fstrcat(station, info->myhostname);
-        strupper(station);
-
-        fstrcpy(srv_name, "\\\\");
-        fstrcat(srv_name, info->dest_host);
-        strupper(srv_name);
-
-        if (!strnequal("\\\\", printer_name, 2))
-        {
-                fstrcat(srv_name, "\\");
-                fstrcat(srv_name, printer_name);
-                printer_name = srv_name;
-        }
-
-        DEBUG(4,("spoolopen - printer: %s server: %s user: %s\n",
-                printer_name, station, usr_creds->ntc.user_name));
-
-        res = res ? spoolss_open_printer_ex( printer_name, "", PRINTER_ALL_ACCESS,
-                                station, "Administrator", &hnd) : False;
-
-        res = res ? spoolss_closeprinter(&hnd) : False;
-
-        if (res)
-        {
-                DEBUG(5,("cmd_spoolss_open_printer_ex: query succeeded\n"));
-                report(out_hnd, "OK\n");
-                return NT_STATUS_NOPROBLEMO;
-        }
-        DEBUG(5,("cmd_spoolss_open_printer_ex: query failed\n"));
-        return NT_STATUS_UNSUCCESSFUL;
+       fstring buffer;
+       
+       rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), 0, STR_TERMINATE);
+       printf("\tPort Name:\t[%s]\n", buffer);
 }
 
 /****************************************************************************
-nt spoolss query
+port info level 2 display function
 ****************************************************************************/
-uint32 cmd_spoolss_getprinterdata(struct client_info *info, int argc, char *argv[])
+static void display_port_info_2(PORT_INFO_2 *i2)
 {
-        fstring srv_name;
-        fstring station;
-        char *printer_name;
-        char *value_name;
-
-        NEW_BUFFER ctr;
-        uint32 status;
-        uint32 type = 1;
-
-        if (argc < 2) {
-                report(out_hnd, "spoolgetdata <printer name> <value name>\n");
-                return NT_STATUS_INVALID_PARAMETER;
-        }
-
-        printer_name = argv[1];
-        value_name = argv[2];
-
-        fstrcpy(station, "\\\\");
-        fstrcat(station, info->myhostname);
-        strupper(station);
-
-        fstrcpy(srv_name, "\\\\");
-        fstrcat(srv_name, info->dest_host);
-        strupper(srv_name);
-
-        if (!strnequal("\\\\", printer_name, 2))
-        {
-                fstrcat(srv_name, "\\");
-                fstrcat(srv_name, printer_name);
-                printer_name = srv_name;
-        }
+       fstring buffer;
+       
+       rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), 0, STR_TERMINATE);
+       printf("\tPort Name:\t[%s]\n", buffer);
+       rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), 0, STR_TERMINATE);
 
-        DEBUG(4,("spoolgetdata - printer: %s station: %s value: %s\n",
-                                printer_name, station, value_name));
+       printf("\tMonitor Name:\t[%s]\n", buffer);
+       rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), 0, STR_TERMINATE);
 
-        status = msrpc_spoolss_getprinterdata( printer_name, station,
-                                /* "Administrateur", */
-                                usr_creds->ntc.user_name,
-                                value_name, &type,
-                                &ctr, NULL);
+       printf("\tDescription:\t[%s]\n", buffer);
+       printf("\tPort Type:\t[%d]\n", i2->port_type);
+       printf("\tReserved:\t[%d]\n", i2->reserved);
+       printf("\n");
+}
 
-        if (status == NT_STATUS_NOPROBLEMO)
-        {
-                DEBUG(5,("cmd_spoolss_getprinterdata: query succeeded\n"));
-        }
-        else
-        {
-                report(out_hnd, "FAILED\n");
-        }
+/* Enumerate ports */
 
-        return status;
+static NTSTATUS cmd_spoolss_enum_ports(struct cli_state *cli, 
+                                      TALLOC_CTX *mem_ctx, int argc, 
+                                      char **argv)
+{
+       WERROR                  result;
+       uint32                  needed, info_level = 1;
+       PORT_INFO_CTR           ctr;
+       int                     returned;
+       
+       if (argc > 2) {
+               printf("Usage: %s [level]\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+       
+       if (argc == 2)
+               info_level = atoi(argv[1]);
+
+       /* Enumerate ports */
+
+       ZERO_STRUCT(ctr);
+
+       result = cli_spoolss_enum_ports(cli, mem_ctx, 0, &needed, info_level, 
+                                       &returned, &ctr);
+
+       if (W_ERROR_V(result) == ERRinsufficientbuffer)
+               result = cli_spoolss_enum_ports(cli, mem_ctx, needed, NULL,
+                                               info_level, &returned, &ctr);
+
+       if (W_ERROR_IS_OK(result)) {
+               int i;
+
+               for (i = 0; i < returned; i++) {
+                       switch (info_level) {
+                       case 1:
+                               display_port_info_1(&ctr.port.info_1[i]);
+                               break;
+                       case 2:
+                               display_port_info_2(&ctr.port.info_2[i]);
+                               break;
+                       default:
+                               printf("unknown info level %d\n", info_level);
+                               break;
+                       }
+               }
+       }
+       
+       return werror_to_ntstatus(result);
 }
 
-/****************************************************************************
-nt spoolss query
-****************************************************************************/
-uint32 cmd_spoolss_getprinterdriver(struct client_info *info, int argc, char *argv[])
+/***********************************************************************
+ * Get printer information
+ */
+static NTSTATUS cmd_spoolss_getprinter(struct cli_state *cli, 
+                                       TALLOC_CTX *mem_ctx,
+                                       int argc, char **argv)
 {
-        PRINTER_DRIVER_CTR ctr;
-        fstring srv_name;
-        fstring station;
-        char *printer_name;
-        fstring environment;
-        uint32 level;
-
-        if (argc < 1) {
-                report(out_hnd, "spoolgetprinterdriver <printer name>\n");
-                return NT_STATUS_INVALID_PARAMETER;
-        }
-
-        printer_name = argv[1];
-
-        fstrcpy(station, "\\\\");
-        fstrcat(station, info->myhostname);
-        strupper(station);
+       POLICY_HND      pol;
+       WERROR          werror;
+       NTSTATUS        result;
+       uint32          info_level = 1;
+       BOOL            opened_hnd = False;
+       PRINTER_INFO_CTR ctr;
+       fstring         printername, 
+                       servername,
+                       user;
 
-        fstrcpy(srv_name, "\\\\");
-        fstrcat(srv_name, info->dest_host);
-        strupper(srv_name);
+       if (argc == 1 || argc > 3) {
+               printf("Usage: %s <printername> [level]\n", argv[0]);
+               return NT_STATUS_OK;
+       }
 
-        if (!strnequal("\\\\", printer_name, 2))
-        {
-                fstrcat(srv_name, "\\");
-                fstrcat(srv_name, printer_name);
-                printer_name = srv_name;
-        }
+       /* Open a printer handle */
+       if (argc == 3) {
+               info_level = atoi(argv[2]);
+       }
 
-        fstrcpy(environment, "Windows NT x86");
-        level=3;
+       slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       strupper (servername);
+       slprintf (printername, sizeof(fstring)-1, "%s\\%s", servername, argv[1]);
+       fstrcpy  (user, cli->user_name);
+       
+       /* get a printer handle */
+
+       werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
+                                            "", MAXIMUM_ALLOWED_ACCESS, 
+                                            servername, user, &pol);
+
+       result = werror_to_ntstatus(werror);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+       opened_hnd = True;
+
+       /* Get printer info */
+
+       result = cli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       /* Display printer info */
+
+       switch (info_level) {
+       case 0: 
+               display_print_info_0(ctr.printers_0);
+               break;
+       case 1:
+               display_print_info_1(ctr.printers_1);
+               break;
+       case 2:
+               display_print_info_2(ctr.printers_2);
+               break;
+       case 3:
+               display_print_info_3(ctr.printers_3);
+               break;
+       default:
+               printf("unknown info level %d\n", info_level);
+               break;
+       }
 
-        if (msrpc_spoolss_getprinterdriver(printer_name, environment, level, station, "Administrator", ctr))
-                DEBUG(5,("cmd_spoolss_getprinterdriver: query succeeded\n"));
-        else
-                report(out_hnd, "FAILED\n");
+ done: 
+       if (opened_hnd) 
+               cli_spoolss_close_printer(cli, mem_ctx, &pol);
 
-        return NT_STATUS_NOPROBLEMO;
+       return result;
 }
 
 /****************************************************************************
-nt spoolss query
+printer info level 0 display function
 ****************************************************************************/
-uint32 cmd_spoolss_enumprinterdrivers(struct client_info *info, int argc, char *argv[])
+static void display_print_driver_1(DRIVER_INFO_1 *i1)
 {
-        PRINTER_DRIVER_CTR ctr;
-        fstring srv_name;
-        fstring environment;
-        uint32 level;
+       fstring name;
+       if (i1 == NULL)
+               return;
 
-        fstrcpy(srv_name, "\\\\");
-        fstrcat(srv_name, info->dest_host);
-        strupper(srv_name);
+       rpcstr_pull(name, i1->name.buffer, sizeof(name), 0, STR_TERMINATE);
 
-        fstrcpy(environment, "Windows NT x86");
-        level=3;
-
-        if (msrpc_spoolss_enumprinterdrivers(srv_name, environment, level, ctr))
-                DEBUG(5,("cmd_spoolss_enumprinterdrivers: query succeeded\n"));
-        else
-                report(out_hnd, "FAILED\n");
-
-        return NT_STATUS_NOPROBLEMO;
+       printf ("Printer Driver Info 1:\n");
+       printf ("\tDriver Name: [%s]\n\n", name);
+       
+       return;
 }
 
 /****************************************************************************
-nt spoolss query
+printer info level 1 display function
 ****************************************************************************/
-uint32 cmd_spoolss_getprinterdriverdir(struct client_info *info, int argc, char *argv[])
+static void display_print_driver_2(DRIVER_INFO_2 *i1)
 {
-        DRIVER_DIRECTORY_CTR ctr;
-        int i;
-
-        uint32 level = 1;
-
-        fstring srv_name;
-       fstring env;
+       fstring name;
+       fstring architecture;
+       fstring driverpath;
+       fstring datafile;
+       fstring configfile;
+       if (i1 == NULL)
+               return;
+
+       rpcstr_pull(name, i1->name.buffer, sizeof(name), 0, STR_TERMINATE);
+       rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), 0, STR_TERMINATE);
+       rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), 0, STR_TERMINATE);
+       rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), 0, STR_TERMINATE);
+       rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), 0, STR_TERMINATE);
+
+       printf ("Printer Driver Info 2:\n");
+       printf ("\tVersion: [%x]\n", i1->version);
+       printf ("\tDriver Name: [%s]\n", name);
+       printf ("\tArchitecture: [%s]\n", architecture);
+       printf ("\tDriver Path: [%s]\n", driverpath);
+       printf ("\tDatafile: [%s]\n", datafile);
+       printf ("\tConfigfile: [%s]\n\n", configfile);
 
-        fstrcpy(srv_name, "\\\\");
-        fstrcat(srv_name, info->dest_host);
-        strupper(srv_name);
-
-        if (argc < 1) {
-                report(out_hnd, "spoolgetprinterdriverdir <arch>\n");
-                return NT_STATUS_NOPROBLEMO;
-        }
-
-        fstrcpy(env, argv[1]);
-
-        for (i=2; i<=argc; i++) {
-                fstrcat(env, " ");
-                fstrcat(env, argv[i]);
-        }
-
-        if (msrpc_spoolss_getprinterdriverdir(srv_name, env, level, ctr))
-                DEBUG(5,("cmd_spoolss_getprinterdriverdir: query succeeded\n"));
-        else
-                report(out_hnd, "FAILED\n");
-
-        return NT_STATUS_NOPROBLEMO;
+       return;
 }
 
-/********************************************************************************
- send an AddPrinterEx() request
-********************************************************************************/
-uint32 cmd_spoolss_addprinterex(struct client_info *info, int argc, char *argv[])
+/****************************************************************************
+printer info level 2 display function
+****************************************************************************/
+static void display_print_driver_3(DRIVER_INFO_3 *i1)
 {
-        fstring        srv_name, 
-                       printer_name, 
-                       driver_name,
-                       port_name,
-                       share_name;
-       POLICY_HND hnd;
-       PRINTER_INFO_2  print_info_2;
-       PORT_INFO_1     *port_info_1 = NULL;
-       NEW_BUFFER      buffer;
-       uint32          status,
-                       needed,
-                       returned;
-       uint32          i;
-       fstring         srv_port_name;
-       BOOL            valid_port = False;
-       TALLOC_CTX      *mem_ctx = NULL;
-
-        fstrcpy(srv_name, "\\\\");
-        fstrcat(srv_name, info->dest_host);
-        strupper(srv_name);
-
-       /* check (and copy) the command line arguments */
-        if (argc < 4) {
-                report(out_hnd, "spooladdprinterex <name> <shared name> <driver> <port>\n");
-                return NT_STATUS_INVALID_PARAMETER;
-        }
-       else
-       {
-               fstrcpy(printer_name, argv[1]);
-               fstrcpy(share_name, argv[2]);
-               fstrcpy(driver_name, argv[3]);
-               fstrcpy(port_name, argv[4]);
-       }
+       fstring name;
+       fstring architecture;
+       fstring driverpath;
+       fstring datafile;
+       fstring configfile;
+       fstring helpfile;
+       fstring dependentfiles;
+       fstring monitorname;
+       fstring defaultdatatype;
+       
+       int length=0;
+       BOOL valid = True;
        
-       /* Verify that the specified port is ok; spoolss_enum_ports() should 
-          be a level 1 since all we need is the name */
-       if ((mem_ctx=talloc_init()) == NULL)
+       if (i1 == NULL)
+               return;
+
+       rpcstr_pull(name, i1->name.buffer, sizeof(name), 0, STR_TERMINATE);
+       rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), 0, STR_TERMINATE);
+       rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), 0, STR_TERMINATE);
+       rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), 0, STR_TERMINATE);
+       rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), 0, STR_TERMINATE);
+       rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), 0, STR_TERMINATE);
+       rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), 0, STR_TERMINATE);
+       rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), 0, STR_TERMINATE);
+
+       printf ("Printer Driver Info 3:\n");
+       printf ("\tVersion: [%x]\n", i1->version);
+       printf ("\tDriver Name: [%s]\n",name);
+       printf ("\tArchitecture: [%s]\n", architecture);
+       printf ("\tDriver Path: [%s]\n", driverpath);
+       printf ("\tDatafile: [%s]\n", datafile);
+       printf ("\tConfigfile: [%s]\n", configfile);
+       printf ("\tHelpfile: [%s]\n\n", helpfile);
+
+       while (valid)
        {
-               DEBUG(0, ("cmd_spoolss_addprinterex: talloc_init() failed!\n"));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-       init_buffer (&buffer, 0, mem_ctx);
-       
-       /* send a NULL buffer first */
-       status=spoolss_enum_ports(srv_name, 1, &buffer, 0, 
-                                    &needed, &returned);
-       
-       /* send the right amount of space this time */
-       if (status==ERROR_INSUFFICIENT_BUFFER) {
-               init_buffer(&buffer, needed, mem_ctx);
-               status=spoolss_enum_ports(srv_name, 1, &buffer, 
-                                         needed, &needed, &returned);
-                                         
-               /* if the call succeeded, then decode the buffer into 
-                  an PRINTER_INFO_1 structre */
-               if (status == NT_STATUS_NO_PROBLEMO)
+               rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), 0, STR_TERMINATE);
+               
+               length+=strlen(dependentfiles)+1;
+               
+               if (strlen(dependentfiles) > 0)
                {
-                       decode_port_info_1(&buffer, returned, &port_info_1);
+                       printf ("\tDependentfiles: [%s]\n", dependentfiles);
                }
                else
                {
-                       report (out_hnd, "cmd_spoolss_addprinterex: FAILED to enumerate ports\n");
-                       return NT_STATUS_NOPROBLEMO;
+                       valid = False;
                }
        }
        
-       /*
-        * now we have an array of port names and we can interate
-        * through it to verify port_name before actually attempting 
-        * to add the printer on the server.
-        */
-       for (i=0; i<returned; i++)
+       printf ("\n");
+
+       printf ("\tMonitorname: [%s]\n", monitorname);
+       printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
+
+       return; 
+}
+
+/***********************************************************************
+ * Get printer information
+ */
+static NTSTATUS cmd_spoolss_getdriver(struct cli_state *cli, 
+                                      TALLOC_CTX *mem_ctx,
+                                      int argc, char **argv)
+{
+       POLICY_HND      pol;
+       WERROR          werror;
+       NTSTATUS        result;
+       uint32          info_level = 3;
+       BOOL            opened_hnd = False;
+       PRINTER_DRIVER_CTR      ctr;
+       fstring         printername, 
+                       servername, 
+                       user;
+       uint32          i;
+
+       if ((argc == 1) || (argc > 3)) 
        {
-               /* compare port_info_1[i].port_name to the port_name specified */
-               unistr_to_ascii(srv_port_name, port_info_1[i].port_name.buffer, 
-                               sizeof(srv_port_name)-1);
-               if (strequal(srv_port_name, port_name))
-               {
-                       valid_port = True;
-                       break;
-               }
+               printf("Usage: %s <printername> [level]\n", argv[0]);
+               return NT_STATUS_OK;
        }
-       if (!valid_port)
-       {
-               report (out_hnd, "cmd_spoolss_addprinterex: Invalid port specified!\n");
-               return NT_STATUS_NOPROBLEMO;
+
+       /* get the arguments need to open the printer handle */
+       slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       strupper (servername);
+       fstrcpy  (user, cli->user_name);
+       fstrcpy  (printername, argv[1]);
+       if (argc == 3)
+               info_level = atoi(argv[2]);
+
+       /* Open a printer handle */
+
+       werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+                                            PRINTER_ACCESS_USE,
+                                            servername, user, &pol);
+
+       result = werror_to_ntstatus(werror);
+
+       if (!NT_STATUS_IS_OK(result)) {
+               printf("Error opening printer handle for %s!\n", printername);
+               return result;
        }
-       
-       /*
-        * Need to build the PRINTER_INFO_2 struct here.
-        * I think it would be better only to deal with a PRINTER_INFO_2
-        * and the abstract the creation of a SPOOL_PRINTER_INFO_LEVEL_2
-        * from that rather than dealing with the struct passed directly 
-        * on the wire.  We don't need the extra *_ptr fields, etc... 
-        * here anyways.  --jerry
-        */
-       ZERO_STRUCTP(&print_info_2);
-       /* init_unistr( &print_info_2.servername,       srv_name); */
-       init_unistr( &print_info_2.printername, printer_name);
-       init_unistr( &print_info_2.sharename,   share_name);
-       init_unistr( &print_info_2.portname,    port_name);
-       init_unistr( &print_info_2.drivername,  driver_name);
-       init_unistr( &print_info_2.comment,     "Created by rpcclient");
-       /* init_unistr( &print_info_2.location, "");
-       init_unistr( &print_info_2.sepfile,     ""); */
-       init_unistr( &print_info_2.printprocessor, "winprint");
-       init_unistr( &print_info_2.datatype,    "RAW");
-       /* init_unistr( &print_info_2.parameters,       ""); */
-       print_info_2.devmode = NULL;
-       print_info_2.secdesc = NULL;
-       print_info_2.attributes         = PRINTER_ATTRIBUTE_SHARED;
-       print_info_2.priority           = 0;
-       print_info_2.defaultpriority    = 0;
-       print_info_2.starttime          = 0;
-       print_info_2.untiltime          = 0;
-       print_info_2.status             = 0;
-       print_info_2.cjobs              = 0;
-       print_info_2.averageppm         = 0;
-
-
-       /* if successful, spoolss_addprinterex() should return True and hnd 
-          should be a valid handle to an open printer */
-       if (spoolss_addprinterex(&hnd, srv_name, &print_info_2))
-       {
-               DEBUG(0,("cmd_spoolss_addprinterex: [%s] added successfully.\n", printer_name));
-               if (!spoolss_closeprinter( &hnd ))
-               {
-                       report (out_hnd, "cmd_spoolss_addprinterex: spoolss_closeprinter FAILED!\n");
+
+       opened_hnd = True;
+
+       /* loop through and print driver info level for each architecture */
+
+       for (i=0; archi_table[i].long_archi!=NULL; i++) {
+               uint32 needed;
+
+               werror = cli_spoolss_getprinterdriver(
+                       cli, mem_ctx, 0, &needed, &pol, info_level, 
+                       archi_table[i].long_archi, &ctr);
+
+               if (W_ERROR_V(werror) == ERRinsufficientbuffer)
+                       werror = cli_spoolss_getprinterdriver(
+                               cli, mem_ctx, needed, NULL, &pol, info_level, 
+                               archi_table[i].long_archi, &ctr);
+
+               if (!W_ERROR_IS_OK(werror))
+                       continue;
+                       
+               printf ("\n[%s]\n", archi_table[i].long_archi);
+
+               switch (info_level) {
+               case 1:
+                       display_print_driver_1 (ctr.info1);
+                       break;
+               case 2:
+                       display_print_driver_2 (ctr.info2);
+                       break;
+               case 3:
+                       display_print_driver_3 (ctr.info3);
+                       break;
+               default:
+                       printf("unknown info level %d\n", info_level);
+                       break;
                }
        }
-       else
-       {
-               report (out_hnd, "cmd_spoolss_addprinterex: spoolss_addprinterex FAILED!\n");
-       }
+       
+       /* Cleanup */
 
+       if (opened_hnd)
+               cli_spoolss_close_printer (cli, mem_ctx, &pol);
        
-        return NT_STATUS_NOPROBLEMO;
+       return result;
 }
-        
-/********************************************************************************
- send an AddPrinterDriver() request
-********************************************************************************/
-uint32 cmd_spoolss_addprinterdriver(struct client_info *info, int argc, char *argv[])
+
+/***********************************************************************
+ * Get printer information
+ */
+static NTSTATUS cmd_spoolss_enum_drivers(struct cli_state *cli, 
+                                         TALLOC_CTX *mem_ctx,
+                                         int argc, char **argv)
 {
-       PRINTER_DRIVER_CTR      driver_info;
-       DRIVER_INFO_3           info3;
-       fstring                 arch;
-        fstring                srv_name;
-       uint32                  result = NT_STATUS_NO_PROBLEMO;
-       
-       /* parse the command arguements */
-       if (argc < 2)
+       NTSTATUS        result = NT_STATUS_OK;
+       uint32          info_level = 1;
+       PRINTER_DRIVER_CTR      ctr;
+       fstring         servername;
+       uint32          i, j,
+                       returned;
+
+       if (argc > 2) 
        {
-               report (out_hnd, "spooladdprinterdriver <arch>\\\n");
-               report (out_hnd, "\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
-               report (out_hnd, "\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
-               report (out_hnd, "\t<Default Data Type>:<Comma Separated list of Files>\n");
+               printf("Usage: enumdrivers [level]\n");
+               return NT_STATUS_OK;
+       }
 
-                return NT_STATUS_INVALID_PARAMETER;
-        }
-       else
+       /* get the arguments need to open the printer handle */
+       slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       strupper (servername);
+       if (argc == 2)
+               info_level = atoi(argv[1]);
+
+
+       /* loop through and print driver info level for each architecture */
+       for (i=0; archi_table[i].long_archi!=NULL; i++) 
        {
-               ZERO_STRUCT(info3);
-               
-               /* get the enviorment for the driver */
-               if (!get_short_archi(arch, argv[1]))
-               {
-                       report (out_hnd, "Unknown architechture [%s]\n", argv[1]);
-                       return NT_STATUS_INVALID_PARAMETER;
+               returned = 0;   
+               result = cli_spoolss_enumprinterdrivers (cli, mem_ctx, info_level, 
+                               archi_table[i].long_archi, &returned, &ctr);
+
+               if (returned == 0)
+                       continue;
                        
-               }
-               else
+
+               if (!NT_STATUS_IS_OK(result))
                {
-                       set_drv_info_3_env(&info3, arch);
+                       printf ("Error getting driver for environment [%s] - %s\n",
+                               archi_table[i].long_archi, get_nt_error_msg(result));
+                       continue;
                }
                
-               /* fill in the other struct members */
-               if (!init_drv_info_3_members(&info3, argv[2]))
+               printf ("\n[%s]\n", archi_table[i].long_archi);
+               switch (info_level) 
                {
-                       report (out_hnd, "Invalid parameter list.\n");
-                       return NT_STATUS_INVALID_PARAMETER;
+                       
+               case 1:
+                       for (j=0; j < returned; j++) {
+                               display_print_driver_1 (&(ctr.info1[j]));
+                       }
+                       break;
+               case 2:
+                       for (j=0; j < returned; j++) {
+                               display_print_driver_2 (&(ctr.info2[j]));
+                       }
+                       break;
+               case 3:
+                       for (j=0; j < returned; j++) {
+                               display_print_driver_3 (&(ctr.info3[j]));
+                       }
+                       break;
+               default:
+                       printf("unknown info level %d\n", info_level);
+                       break;
                }
        }
        
-       /* get the server name */
-        fstrcpy(srv_name, "\\\\");
-        fstrcat(srv_name, info->dest_host);
-        strupper(srv_name);
-       
-       /* call AddPrinterDriver() woth an info level 3 */
-       driver_info.info3 = &info3;
-       if ((result=spoolss_addprinterdriver(srv_name, 3, &driver_info)) != NT_STATUS_NO_PROBLEMO)
+       return result;
+}
+
+/****************************************************************************
+printer info level 1 display function
+****************************************************************************/
+static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
+{
+        fstring name;
+        if (i1 == NULL)
+                return;
+       rpcstr_pull(name, i1->name.buffer, sizeof(name), 0, STR_TERMINATE);
+       printf ("\tDirectory Name:[%s]\n", name);
+}
+
+/***********************************************************************
+ * Get printer driver directory information
+ */
+static NTSTATUS cmd_spoolss_getdriverdir(struct cli_state *cli, 
+                                         TALLOC_CTX *mem_ctx,
+                                         int argc, char **argv)
+{
+       NTSTATUS                result;
+       fstring                 env;
+       DRIVER_DIRECTORY_CTR    ctr;
+
+       if (argc > 2) 
        {
-               report( out_hnd, "spoolss_addprinterdriver: Add Printer failed [%d]\n",
-                       result);
+               printf("Usage: %s [environment]\n", argv[0]);
+               return NT_STATUS_OK;
        }
+
+       /* get the arguments need to open the printer handle */
+       if (argc == 2)
+               fstrcpy (env, argv[1]);
        else
-       {
-               fstring driver_name;
-               unistr_to_ascii (driver_name, info3.name.buffer, sizeof(driver_name)-1);
-               report( out_hnd, "cmd_spoolss_addprinterdriver: Printer Driver [%s] added successfully\n", driver_name);
+               fstrcpy (env, "Windows NT x86");
+
+       /* Get the directory.  Only use Info level 1 */
+       result = cli_spoolss_getprinterdriverdir (cli, mem_ctx, 1, env, &ctr);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
        }
+
        
-       free_drv_info_3(&info3);
-       
-        return result;
-}      
+       display_printdriverdir_1 (ctr.info1);
+
+       return result;
+}
 
 /*******************************************************************************
  set the version and environment fields of a DRIVER_INFO_3 struct
  ******************************************************************************/
 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
 {
-       if (strcmp(arch, "WIN40") == 0)
-       {
-               info->version = 0;
-               init_unistr(&info->architecture, "Windows 4.0");
-       }
-       else if (strcmp(arch, "W32X86") == 0)
-       {
-               info->version = 2;
-               init_unistr(&info->architecture, "Windows NT x86");
-       }
-       else if (strcmp(arch, "W32MIPS") == 0)
-       {
-               info->version = 2;
-               init_unistr(&info->architecture, "Windows NT R4000");
-       }
-       else if (strcmp(arch, "W32ALPHA") == 0)
-       {
-               info->version = 2;
-               init_unistr(&info->architecture, "Windows NT Alpha_AXP");
-       }
-       else if (strcmp(arch, "W32PPC") == 0)
+
+       int i;
+       
+       for (i=0; archi_table[i].long_archi != NULL; i++) 
        {
-               info->version = 2;
-               init_unistr(&info->architecture, "Windows NT PowerPC");
+               if (strcmp(arch, archi_table[i].short_archi) == 0)
+               {
+                       info->version = archi_table[i].version;
+                       init_unistr (&info->architecture, archi_table[i].long_archi);
+                       break;
+               }
        }
-       else
+       
+       if (archi_table[i].long_archi == NULL)
        {
                DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
        }
@@ -789,6 +865,7 @@ void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
        return;
 }
 
+
 /**************************************************************************
  wrapper for strtok to get the next parameter from a delimited list.
  Needed to handle the empty parameter string denoted by "NULL"
@@ -820,7 +897,11 @@ static char* get_driver_3_param (char* str, char* delim, UNISTR* dest)
             <Config File Name>:<Help File Name>:<Language Monitor Name>:\
             <Default Data Type>:<Comma Separated list of Files> 
  *******************************************************************************/
-BOOL init_drv_info_3_members (DRIVER_INFO_3 *info, char *args)
+static BOOL init_drv_info_3_members (
+       TALLOC_CTX *mem_ctx, 
+       DRIVER_INFO_3 *info, 
+       char *args
+)
 {
        char    *str, *str2;
        uint32  len, i;
@@ -851,33 +932,298 @@ BOOL init_drv_info_3_members (DRIVER_INFO_3 *info, char *args)
        /* allocate the space; add one extra slot for a terminating NULL.
           Each filename is NULL terminated and the end contains a double
           NULL */
-       if ((info->dependentfiles=(uint16*)malloc((len+1)*sizeof(uint16))) == NULL)
+       if ((info->dependentfiles=(uint16*)talloc(mem_ctx, (len+1)*sizeof(uint16))) == NULL)
        {
                DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
                return False;
        }
        for (i=0; i<len; i++)
        {
-               info->dependentfiles[i] = (uint16)str2[i];
+               info->dependentfiles[i] = SSVAL(&info->dependentfiles[i], 0, str2[i]);
        }
-       info->dependentfiles[len+1] = '\0';
+       info->dependentfiles[len] = '\0';
 
        return True;
 }
 
-/*****************************************************************************
- free any dynamically allocated members
- ****************************************************************************/
-void free_drv_info_3 (DRIVER_INFO_3 *info)
+
+static NTSTATUS cmd_spoolss_addprinterdriver(struct cli_state *cli, 
+                                             TALLOC_CTX *mem_ctx,
+                                             int argc, char **argv)
 {
-       if (info->dependentfiles != NULL)
+       NTSTATUS                result;
+       uint32                  level = 3;
+       PRINTER_DRIVER_CTR      ctr;
+       DRIVER_INFO_3           info3;
+       fstring                 arch;
+       fstring                 driver_name;
+
+       /* parse the command arguements */
+       if (argc != 3)
        {
-               free(info->dependentfiles);
-               info->dependentfiles = NULL;
+               printf ("Usage: %s <Environment>\\\n", argv[0]);
+               printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
+               printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
+               printf ("\t<Default Data Type>:<Comma Separated list of Files>\n");
+
+               return NT_STATUS_OK;
+        }
+               
+       /* Fill in the DRIVER_INFO_3 struct */
+       ZERO_STRUCT(info3);
+       if (!get_short_archi(arch, argv[1]))
+       {
+               printf ("Error Unknown architechture [%s]\n", argv[1]);
+               return NT_STATUS_INVALID_PARAMETER;
        }
+       else
+               set_drv_info_3_env(&info3, arch);
+
+       if (!init_drv_info_3_members(mem_ctx, &info3, argv[2]))
+       {
+               printf ("Error Invalid parameter list - %s.\n", argv[2]);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+
+       ctr.info3 = &info3;
+       result = cli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       rpcstr_pull(driver_name, info3.name.buffer, sizeof(driver_name), 0, STR_TERMINATE);
+       printf ("Printer Driver %s successfully installed.\n", driver_name);
+
+       return result;
+}
+
+
+static NTSTATUS cmd_spoolss_addprinterex(struct cli_state *cli, 
+                                         TALLOC_CTX *mem_ctx, 
+                                         int argc, char **argv)
+{
+       NTSTATUS                result;
+       uint32                  level = 2;
+       PRINTER_INFO_CTR        ctr;
+       PRINTER_INFO_2          info2;
+       fstring                 servername;
        
-       return;
+       /* parse the command arguements */
+       if (argc != 5)
+       {
+               printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
+               return NT_STATUS_OK;
+        }
+       
+        slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+        strupper (servername);
+
+       /* Fill in the DRIVER_INFO_3 struct */
+       ZERO_STRUCT(info2);
+#if 0  /* JERRY */
+       init_unistr( &info2.servername,         servername);
+#endif
+       init_unistr( &info2.printername,        argv[1]);
+       init_unistr( &info2.sharename,          argv[2]);
+       init_unistr( &info2.drivername,         argv[3]);
+       init_unistr( &info2.portname,           argv[4]);
+       init_unistr( &info2.comment,            "Created by rpcclient");
+       init_unistr( &info2.printprocessor,     "winprint");
+       init_unistr( &info2.datatype,           "RAW");
+       info2.devmode =         NULL;
+       info2.secdesc =         NULL;
+       info2.attributes        = PRINTER_ATTRIBUTE_SHARED;
+       info2.priority          = 0;
+       info2.defaultpriority   = 0;
+       info2.starttime         = 0;
+       info2.untiltime         = 0;
+       
+       /* These three fields must not be used by AddPrinter() 
+          as defined in the MS Platform SDK documentation..  
+          --jerry
+       info2.status            = 0;
+       info2.cjobs             = 0;
+       info2.averageppm        = 0;
+       */
+
+       ctr.printers_2 = &info2;
+       result = cli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       printf ("Printer %s successfully installed.\n", argv[1]);
+
+       return result;
 }
 
+static NTSTATUS cmd_spoolss_setdriver(struct cli_state *cli, 
+                                      TALLOC_CTX *mem_ctx,
+                                      int argc, char **argv)
+{
+       POLICY_HND              pol;
+       WERROR                  result;
+       NTSTATUS                nt_status;
+       uint32                  level = 2;
+       BOOL                    opened_hnd = False;
+       PRINTER_INFO_CTR        ctr;
+       PRINTER_INFO_2          info2;
+       fstring                 servername,
+                               printername,
+                               user;
+       
+       /* parse the command arguements */
+       if (argc != 3)
+       {
+               printf ("Usage: %s <printer> <driver>\n", argv[0]);
+               return NT_STATUS_OK;
+        }
+
+       slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       strupper (servername);
+       slprintf (printername, sizeof(fstring)-1, "%s\\%s", servername, argv[1]);
+       fstrcpy  (user, cli->user_name);
+
+       /* Get a printer handle */
+
+       result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
+                                            MAXIMUM_ALLOWED_ACCESS, 
+                                            servername, user, &pol);
+
+       nt_status = werror_to_ntstatus(result);
+
+       if (!NT_STATUS_IS_OK(nt_status))
+               goto done;
+       opened_hnd = True;
+
+       /* Get printer info */
 
+       ZERO_STRUCT (info2);
+       ctr.printers_2 = &info2;
+
+       nt_status = cli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               printf ("Unable to retrieve printer information!\n");
+               goto done;
+       }
+
+       /* Set the printer driver */
+
+       init_unistr(&ctr.printers_2->drivername, argv[2]);
+
+       nt_status = cli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               printf("SetPrinter call failed!\n");
+               goto done;;
+       }
+
+       printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
+
+done:
+       /* Cleanup */
+
+       if (opened_hnd)
+               cli_spoolss_close_printer(cli, mem_ctx, &pol);
+       
+       return nt_status;               
+}
+
+
+static NTSTATUS cmd_spoolss_deletedriver(struct cli_state *cli, 
+                                         TALLOC_CTX *mem_ctx,
+                                         int argc, char **argv)
+{
+       NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
+       fstring                 servername;
+       int                     i;
+       
+       /* parse the command arguements */
+       if (argc != 2)
+       {
+               printf ("Usage: %s <driver>\n", argv[0]);
+               return NT_STATUS_OK;
+        }
+
+       slprintf (servername, sizeof(fstring)-1, "\\\\%s", cli->desthost);
+       strupper (servername);
+
+       /* delete the driver for all architectures */
+       for (i=0; archi_table[i].long_archi; i++)
+       {
+               /* make the call to remove the driver */
+               result = cli_spoolss_deleteprinterdriver(cli, mem_ctx, 
+                                                        archi_table[i].long_archi, argv[1]);
+               if (!NT_STATUS_IS_OK(result)) {
+                       printf ("Failed to remove driver %s for arch [%s] - error %s!\n", 
+                               argv[1], archi_table[i].long_archi, get_nt_error_msg(result));
+               }
+               else
+                       printf ("Driver %s removed for arch [%s].\n", argv[1], archi_table[i].long_archi);
+       }
+               
+       return NT_STATUS_OK;            
+}
+
+static NTSTATUS cmd_spoolss_getprintprocdir(struct cli_state *cli, 
+                                           TALLOC_CTX *mem_ctx,
+                                           int argc, char **argv)
+{
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       char *servername = NULL, *environment = NULL;
+       fstring procdir;
+       
+       /* parse the command arguements */
+       if (argc < 2 || argc > 3) {
+               printf ("Usage: %s <server> [environment]\n", argv[0]);
+               return NT_STATUS_OK;
+        }
+
+       if (asprintf(&servername, "\\\\%s", cli->desthost) < 0)
+               return NT_STATUS_NO_MEMORY;
+       strupper(servername);
+
+       if (asprintf(&environment, "%s", (argc == 3) ? argv[2] : 
+                                       PRINTER_DRIVER_ARCHITECTURE) < 0) {
+               SAFE_FREE(servername);
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       result = cli_spoolss_getprintprocessordirectory(
+               cli, mem_ctx, servername, environment, procdir);
+
+       if (NT_STATUS_IS_OK(result))
+               printf("%s", procdir);
+
+       SAFE_FREE(servername);
+       SAFE_FREE(environment);
+
+       return result;
+}
 
+/* List of commands exported by this module */
+struct cmd_set spoolss_commands[] = {
+
+       { "SPOOLSS"  },
+
+       { "adddriver",          cmd_spoolss_addprinterdriver,   PIPE_SPOOLSS, "Add a print driver",                  "" },
+       { "addprinter",         cmd_spoolss_addprinterex,       PIPE_SPOOLSS, "Add a printer",                       "" },
+       { "deldriver",          cmd_spoolss_deletedriver,       PIPE_SPOOLSS, "Delete a printer driver",             "" },
+       { "enumdata",           cmd_spoolss_not_implemented,    PIPE_SPOOLSS, "Enumerate printer data (*)",          "" },
+       { "enumjobs",           cmd_spoolss_not_implemented,    PIPE_SPOOLSS, "Enumerate print jobs (*)",            "" },
+       { "enumports",          cmd_spoolss_enum_ports,         PIPE_SPOOLSS, "Enumerate printer ports",             "" },
+       { "enumdrivers",        cmd_spoolss_enum_drivers,       PIPE_SPOOLSS, "Enumerate installed printer drivers", "" },
+       { "enumprinters",       cmd_spoolss_enum_printers,      PIPE_SPOOLSS, "Enumerate printers",                  "" },
+       { "getdata",            cmd_spoolss_not_implemented,    PIPE_SPOOLSS, "Get print driver data (*)",           "" },
+       { "getdriver",          cmd_spoolss_getdriver,          PIPE_SPOOLSS, "Get print driver information",        "" },
+       { "getdriverdir",       cmd_spoolss_getdriverdir,       PIPE_SPOOLSS, "Get print driver upload directory",   "" },
+       { "getprinter",         cmd_spoolss_getprinter,         PIPE_SPOOLSS, "Get printer info",                    "" },
+       { "openprinter",        cmd_spoolss_open_printer_ex,    PIPE_SPOOLSS, "Open printer handle",                 "" },
+       { "setdriver",          cmd_spoolss_setdriver,          PIPE_SPOOLSS, "Set printer driver",                  "" },
+       { "getprintprocdir",    cmd_spoolss_getprintprocdir, PIPE_SPOOLSS, "Get print processor directory",          "" },
+
+       { NULL }
+};