summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGerald Carter <jerry@samba.org>2001-03-15 07:13:27 +0000
committerGerald Carter <jerry@samba.org>2001-03-15 07:13:27 +0000
commitf4ae39d53a62a8496cc20bc554fb7b791676bfdc (patch)
tree9e60eeea3280e3edc067fc91953f5a707927f9cb
parenta9dda48d653810b8f20b3b72f07cc060e2b2e3cd (diff)
downloadsamba-f4ae39d53a62a8496cc20bc554fb7b791676bfdc.tar.gz
samba-f4ae39d53a62a8496cc20bc554fb7b791676bfdc.tar.bz2
samba-f4ae39d53a62a8496cc20bc554fb7b791676bfdc.zip
added getdriver and enumdrivers commands. Also fixed
enumprinters so that it works as well. Couple of other misc fixes while we're working on rpcclient. (This used to be commit 83d6bc4454f0cda581d26de32a4fcaad42431b34)
-rw-r--r--source3/libsmb/cli_spoolss.c225
-rw-r--r--source3/rpc_client/cli_spoolss.c2
-rw-r--r--source3/rpcclient/cmd_spoolss.c381
3 files changed, 573 insertions, 35 deletions
diff --git a/source3/libsmb/cli_spoolss.c b/source3/libsmb/cli_spoolss.c
index 26ab99419a..c0ec4d0d9c 100644
--- a/source3/libsmb/cli_spoolss.c
+++ b/source3/libsmb/cli_spoolss.c
@@ -308,6 +308,59 @@ static void decode_port_info_2(NEW_BUFFER *buffer, uint32 returned,
*info=inf;
}
+static void decode_printer_driver_1(NEW_BUFFER *buffer, uint32 returned,
+ DRIVER_INFO_1 **info)
+{
+ uint32 i;
+ DRIVER_INFO_1 *inf;
+
+ inf=(DRIVER_INFO_1 *)malloc(returned*sizeof(DRIVER_INFO_1));
+
+ buffer->prs.data_offset=0;
+
+ for (i=0; i<returned; i++) {
+ new_smb_io_printer_driver_info_1("", buffer, &(inf[i]), 0);
+ }
+
+ *info=inf;
+}
+
+static void decode_printer_driver_2(NEW_BUFFER *buffer, uint32 returned,
+ DRIVER_INFO_2 **info)
+{
+ uint32 i;
+ DRIVER_INFO_2 *inf;
+
+ inf=(DRIVER_INFO_2 *)malloc(returned*sizeof(DRIVER_INFO_2));
+
+ buffer->prs.data_offset=0;
+
+ for (i=0; i<returned; i++) {
+ new_smb_io_printer_driver_info_2("", buffer, &(inf[i]), 0);
+ }
+
+ *info=inf;
+}
+
+static void decode_printer_driver_3(NEW_BUFFER *buffer, uint32 returned,
+ DRIVER_INFO_3 **info)
+{
+ uint32 i;
+ DRIVER_INFO_3 *inf;
+
+ inf=(DRIVER_INFO_3 *)malloc(returned*sizeof(DRIVER_INFO_3));
+
+ buffer->prs.data_offset=0;
+
+ for (i=0; i<returned; i++) {
+ new_smb_io_printer_driver_info_3("", buffer, &(inf[i]), 0);
+ }
+
+ *info=inf;
+}
+
+
+
/* Enumerate printers */
uint32 cli_spoolss_enum_printers(struct cli_state *cli, uint32 flags,
@@ -384,7 +437,6 @@ uint32 cli_spoolss_enum_printers(struct cli_state *cli, uint32 flags,
}
/* Enumerate printer ports */
-
uint32 cli_spoolss_enum_ports(struct cli_state *cli, uint32 level,
int *returned, PORT_INFO_CTR *ctr)
{
@@ -399,8 +451,8 @@ uint32 cli_spoolss_enum_ports(struct cli_state *cli, uint32 level,
ZERO_STRUCT(q);
ZERO_STRUCT(r);
- fstrcpy (server, cli->desthost);
- strupper (server);
+ slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
+ strupper (server);
do {
/* Initialise input parameters */
@@ -410,10 +462,7 @@ uint32 cli_spoolss_enum_ports(struct cli_state *cli, uint32 level,
prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
- /* NT4 will return NT_STATUS_CTL_FILE_NOT_SUPPORTED is we
- set the servername here in the query. Not sure why \
- --jerry */
- make_spoolss_q_enumports(&q, "", level, &buffer, needed);
+ make_spoolss_q_enumports(&q, server, level, &buffer, needed);
/* Marshall data and send request */
@@ -457,7 +506,6 @@ uint32 cli_spoolss_enum_ports(struct cli_state *cli, uint32 level,
}
/* Get printer info */
-
uint32 cli_spoolss_getprinter(struct cli_state *cli, POLICY_HND *pol,
uint32 level, PRINTER_INFO_CTR *ctr)
{
@@ -528,3 +576,164 @@ uint32 cli_spoolss_getprinter(struct cli_state *cli, POLICY_HND *pol,
return result;
}
+
+/**********************************************************************
+ * Get installed printer drivers for a given printer
+ */
+uint32 cli_spoolss_getprinterdriver (
+ struct cli_state *cli,
+ POLICY_HND *pol,
+ uint32 level,
+ char* env,
+ PRINTER_DRIVER_CTR *ctr
+)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_GETPRINTERDRIVER2 q;
+ SPOOL_R_GETPRINTERDRIVER2 r;
+ NEW_BUFFER buffer;
+ uint32 needed = 1024;
+ uint32 result;
+ fstring server;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ fstrcpy (server, cli->desthost);
+ strupper (server);
+
+ do
+ {
+ /* Initialise input parameters */
+
+ init_buffer(&buffer, needed, cli->mem_ctx);
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
+
+
+ /* write the request */
+ make_spoolss_q_getprinterdriver2(&q, pol, env, level, 2, 2, &buffer, needed);
+
+ /* Marshall data and send request */
+ if (!spoolss_io_q_getprinterdriver2 ("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req (cli, SPOOLSS_GETPRINTERDRIVER2, &qbuf, &rbuf))
+ {
+ result = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /* Unmarshall response */
+ if (spoolss_io_r_getprinterdriver2 ("", &r, &rbuf, 0))
+ {
+ needed = r.needed;
+ }
+
+ /* Return output parameters */
+ if ((result = r.status) == NT_STATUS_NOPROBLEMO)
+ {
+
+ switch (level)
+ {
+ case 1:
+ decode_printer_driver_1(r.buffer, 1, &ctr->info1);
+ break;
+ case 2:
+ decode_printer_driver_2(r.buffer, 1, &ctr->info2);
+ break;
+ case 3:
+ decode_printer_driver_3(r.buffer, 1, &ctr->info3);
+ break;
+ }
+ }
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ } while (result == ERROR_INSUFFICIENT_BUFFER);
+
+ return result;
+}
+
+/**********************************************************************
+ * Get installed printer drivers for a given printer
+ */
+uint32 cli_spoolss_enumprinterdrivers (
+ struct cli_state *cli,
+ uint32 level,
+ char* env,
+ uint32 *returned,
+ PRINTER_DRIVER_CTR *ctr
+)
+{
+ prs_struct qbuf, rbuf;
+ SPOOL_Q_ENUMPRINTERDRIVERS q;
+ SPOOL_R_ENUMPRINTERDRIVERS r;
+ NEW_BUFFER buffer;
+ uint32 needed = 0;
+ uint32 result;
+ fstring server;
+
+ ZERO_STRUCT(q);
+ ZERO_STRUCT(r);
+
+ slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
+ strupper (server);
+
+ do
+ {
+ /* Initialise input parameters */
+ init_buffer(&buffer, needed, cli->mem_ctx);
+
+ prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
+ prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
+
+
+ /* write the request */
+ make_spoolss_q_enumprinterdrivers(&q, server, env, level, &buffer, needed);
+
+ /* Marshall data and send request */
+ if (!spoolss_io_q_enumprinterdrivers ("", &q, &qbuf, 0) ||
+ !rpc_api_pipe_req (cli, SPOOLSS_ENUMPRINTERDRIVERS, &qbuf, &rbuf))
+ {
+ result = NT_STATUS_UNSUCCESSFUL;
+ goto done;
+ }
+
+ /* Unmarshall response */
+ if (spoolss_io_r_enumprinterdrivers ("", &r, &rbuf, 0))
+ {
+ needed = r.needed;
+ }
+
+ /* Return output parameters */
+ if (((result=r.status) == NT_STATUS_NOPROBLEMO) &&
+ (r.returned != 0))
+ {
+ *returned = r.returned;
+
+ switch (level)
+ {
+ case 1:
+ decode_printer_driver_1(r.buffer, r.returned, &ctr->info1);
+ break;
+ case 2:
+ decode_printer_driver_2(r.buffer, r.returned, &ctr->info2);
+ break;
+ case 3:
+ decode_printer_driver_3(r.buffer, r.returned, &ctr->info3);
+ break;
+ }
+ }
+
+ done:
+ prs_mem_free(&qbuf);
+ prs_mem_free(&rbuf);
+
+ } while (result == ERROR_INSUFFICIENT_BUFFER);
+
+ return result;
+}
+
+
diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c
index 7588ba152f..c17db2be85 100644
--- a/source3/rpc_client/cli_spoolss.c
+++ b/source3/rpc_client/cli_spoolss.c
@@ -69,7 +69,7 @@ uint32 spoolss_enum_printerdrivers(const char *srv_name, const char *environment
prs_set_offset(&buffer->prs, 0);
r_o.buffer=buffer;
- if(new_spoolss_io_r_enumprinterdrivers("", &r_o, &rbuf, 0))
+ if(spoolss_io_r_enumprinterdrivers("", &r_o, &rbuf, 0))
{
if (r_o.status != NT_STATUS_NOPROBLEMO)
{
diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c
index 8db769a8bd..0c101056f5 100644
--- a/source3/rpcclient/cmd_spoolss.c
+++ b/source3/rpcclient/cmd_spoolss.c
@@ -31,6 +31,22 @@ extern pstring global_myname;
extern pstring username, password;
extern pstring workgroup;
+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, "" }
+};
+
+
/**********************************************************************
* dummy function -- placeholder
*/
@@ -124,9 +140,9 @@ static uint32 cmd_spoolss_open_printer_ex(struct cli_state *cli, int argc, char
return NT_STATUS_UNSUCCESSFUL;
}
- /* Enumerate printers */
+ /* Open the printer handle */
result = cli_spoolss_open_printer_ex (cli, printername, "",
- PRINTER_ACCESS_USE, server, user, &hnd);
+ MAXIMUM_ALLOWED_ACCESS, server, user, &hnd);
if (result == NT_STATUS_NOPROBLEMO) {
printf ("Printer %s opened successfully\n", printername);
@@ -285,12 +301,15 @@ static void display_print_info_3(PRINTER_INFO_3 *i3)
static uint32 cmd_spoolss_enum_printers(struct cli_state *cli, int argc, char **argv)
{
- uint32 result = NT_STATUS_UNSUCCESSFUL, info_level = 1;
- PRINTER_INFO_CTR ctr;
- int returned;
+ uint32 result = NT_STATUS_UNSUCCESSFUL,
+ info_level = 1;
+ PRINTER_INFO_CTR ctr;
+ int returned;
+ uint32 i;
- if (argc > 2) {
- printf("Usage: enumprinters\n");
+ if (argc > 2)
+ {
+ printf("Usage: enumprinters [level]\n");
return NT_STATUS_NOPROBLEMO;
}
@@ -313,16 +332,24 @@ static uint32 cmd_spoolss_enum_printers(struct cli_state *cli, int argc, char **
if (result == NT_STATUS_NOPROBLEMO) {
switch(info_level) {
case 0:
- display_print_info_0(ctr.printers_0);
+ for (i=0; i<returned; i++) {
+ display_print_info_0(&(ctr.printers_0[i]));
+ }
break;
case 1:
- display_print_info_1(ctr.printers_1);
+ for (i=0; i<returned; i++) {
+ display_print_info_1(&(ctr.printers_1[i]));
+ }
break;
case 2:
- display_print_info_2(ctr.printers_2);
+ for (i=0; i<returned; i++) {
+ display_print_info_2(&(ctr.printers_2[i]));
+ }
break;
case 3:
- display_print_info_3(ctr.printers_3);
+ for (i=0; i<returned; i++) {
+ display_print_info_3(&(ctr.printers_3[i]));
+ }
break;
default:
printf("unknown info level %d\n", info_level);
@@ -368,11 +395,12 @@ static void display_port_info_2(PORT_INFO_2 *i2)
static uint32 cmd_spoolss_enum_ports(struct cli_state *cli, int argc, char **argv)
{
- uint32 result = NT_STATUS_UNSUCCESSFUL, info_level = 1;
- PORT_INFO_CTR ctr;
- int returned;
+ uint32 result = NT_STATUS_UNSUCCESSFUL,
+ info_level = 1;
+ PORT_INFO_CTR ctr;
+ int returned;
- if (argc == 1 || argc < 2) {
+ if (argc > 2) {
printf("Usage: enumports [level]\n");
return NT_STATUS_NOPROBLEMO;
}
@@ -420,11 +448,13 @@ static uint32 cmd_spoolss_enum_ports(struct cli_state *cli, int argc, char **arg
*/
static uint32 cmd_spoolss_getprinter(struct cli_state *cli, int argc, char **argv)
{
- POLICY_HND pol;
- uint32 result, info_level = 1;
- BOOL opened_hnd = False;
+ POLICY_HND pol;
+ uint32 result,
+ info_level = 1;
+ BOOL opened_hnd = False;
PRINTER_INFO_CTR ctr;
- fstring printer_name, station_name;
+ fstring printername,
+ servername;
if (argc == 1 || argc > 3) {
printf("Usage: %s printername [level]\n", argv[0]);
@@ -438,17 +468,17 @@ static uint32 cmd_spoolss_getprinter(struct cli_state *cli, int argc, char **arg
}
/* Open a printer handle */
-
if (argc == 3) {
info_level = atoi(argv[2]);
}
- slprintf(printer_name, sizeof(fstring), "\\\\%s\\%s", server, argv[1]);
-
- slprintf(station_name, sizeof(fstring), "\\\\%s", global_myname);
-
+ slprintf (printername, sizeof(fstring), "\\\\%s\\%s", server, argv[1]);
+ slprintf (servername, sizeof(fstring), "\\\\%s", cli->desthost);
+ strupper (servername);
+
+ /* get a printer handle */
if ((result = cli_spoolss_open_printer_ex(
- cli, printer_name, "", MAXIMUM_ALLOWED_ACCESS, station_name,
+ cli, printername, "", MAXIMUM_ALLOWED_ACCESS, servername,
username, &pol)) != NT_STATUS_NOPROBLEMO) {
goto done;
}
@@ -490,6 +520,304 @@ static uint32 cmd_spoolss_getprinter(struct cli_state *cli, int argc, char **arg
return result;
}
+/****************************************************************************
+printer info level 0 display function
+****************************************************************************/
+static void display_print_driver_1(DRIVER_INFO_1 *i1)
+{
+ fstring name;
+ if (i1 == NULL)
+ return;
+
+ unistr_to_ascii(name, i1->name.buffer, sizeof(name)-1);
+
+ printf ("Printer Driver Info 1:\n");
+ printf ("\tDriver Name: [%s]\n\n", name);
+
+ return;
+}
+
+/****************************************************************************
+printer info level 1 display function
+****************************************************************************/
+static void display_print_driver_2(DRIVER_INFO_2 *i1)
+{
+ fstring name;
+ fstring architecture;
+ fstring driverpath;
+ fstring datafile;
+ fstring configfile;
+ if (i1 == NULL)
+ return;
+
+ unistr_to_ascii(name, i1->name.buffer, sizeof(name)-1);
+ unistr_to_ascii(architecture, i1->architecture.buffer, sizeof(architecture)-1);
+ unistr_to_ascii(driverpath, i1->driverpath.buffer, sizeof(driverpath)-1);
+ unistr_to_ascii(datafile, i1->datafile.buffer, sizeof(datafile)-1);
+ unistr_to_ascii(configfile, i1->configfile.buffer, sizeof(configfile)-1);
+
+ 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);
+
+ return;
+}
+
+/****************************************************************************
+printer info level 2 display function
+****************************************************************************/
+static void display_print_driver_3(DRIVER_INFO_3 *i1)
+{
+ fstring name;
+ fstring architecture;
+ fstring driverpath;
+ fstring datafile;
+ fstring configfile;
+ fstring helpfile;
+ fstring dependentfiles;
+ fstring monitorname;
+ fstring defaultdatatype;
+
+ int length=0;
+ BOOL valid = True;
+
+ if (i1 == NULL)
+ return;
+
+ unistr_to_ascii(name, i1->name.buffer, sizeof(name)-1);
+ unistr_to_ascii(architecture, i1->architecture.buffer, sizeof(architecture)-1);
+ unistr_to_ascii(driverpath, i1->driverpath.buffer, sizeof(driverpath)-1);
+ unistr_to_ascii(datafile, i1->datafile.buffer, sizeof(datafile)-1);
+ unistr_to_ascii(configfile, i1->configfile.buffer, sizeof(configfile)-1);
+ unistr_to_ascii(helpfile, i1->helpfile.buffer, sizeof(helpfile)-1);
+
+ unistr_to_ascii(monitorname, i1->monitorname.buffer, sizeof(monitorname)-1);
+ unistr_to_ascii(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype)-1);
+
+ 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)
+ {
+ unistr_to_ascii(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles)-1);
+ length+=strlen(dependentfiles)+1;
+
+ if (strlen(dependentfiles) > 0)
+ {
+ printf ("\tDependentfiles: [%s]\n", dependentfiles);
+ }
+ else
+ {
+ valid = False;
+ }
+ }
+
+ printf ("\n");
+
+ printf ("\tMonitorname: [%s]\n", monitorname);
+ printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
+
+ return;
+}
+
+/***********************************************************************
+ * Get printer information
+ */
+static uint32 cmd_spoolss_getdriver(struct cli_state *cli, int argc, char **argv)
+{
+ POLICY_HND pol;
+ uint32 result,
+ info_level = 3;
+ BOOL opened_hnd = False;
+ PRINTER_DRIVER_CTR ctr;
+ fstring printername,
+ server,
+ user;
+ uint32 i;
+
+ if ((argc == 1) || (argc > 3))
+ {
+ printf("Usage: %s <printername> [level]\n", argv[0]);
+ return NT_STATUS_NOPROBLEMO;
+ }
+
+ /* Initialise RPC connection */
+ if (!cli_nt_session_open (cli, PIPE_SPOOLSS))
+ {
+ fprintf (stderr, "Could not initialize spoolss pipe!\n");
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* get the arguments need to open the printer handle */
+ slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
+ strupper (server);
+ fstrcpy (user, cli->user_name);
+ fstrcpy (printername, argv[1]);
+ if (argc == 3)
+ info_level = atoi(argv[2]);
+
+ /* Open a printer handle */
+ if ((result=cli_spoolss_open_printer_ex (cli, printername, "",
+ MAXIMUM_ALLOWED_ACCESS, server, user, &pol)) != NT_STATUS_NO_PROBLEMO)
+ {
+ printf ("Error opening printer handle for %s!\n", printername);
+ return result;
+ }
+
+ opened_hnd = True;
+
+ /* loop through and print driver info level for each architecture */
+ for (i=0; archi_table[i].long_archi!=NULL; i++)
+ {
+ result = cli_spoolss_getprinterdriver (cli, &pol, info_level,
+ archi_table[i].long_archi, &ctr);
+
+ switch (result)
+ {
+ case NT_STATUS_NO_PROBLEMO:
+ break;
+
+ case ERROR_UNKNOWN_PRINTER_DRIVER:
+ continue;
+
+ default:
+ printf ("Error getting driver for %s [%s] - %s\n", printername,
+ archi_table[i].long_archi, get_nt_error_msg(result));
+ 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;
+ }
+
+
+ }
+
+
+ /* cleanup */
+ if (opened_hnd)
+ cli_spoolss_close_printer (cli, &pol);
+ cli_nt_session_close (cli);
+
+ if (result==ERROR_UNKNOWN_PRINTER_DRIVER)
+ return NT_STATUS_NO_PROBLEMO;
+ else
+ return result;
+
+}
+
+/***********************************************************************
+ * Get printer information
+ */
+static uint32 cmd_spoolss_enum_drivers(struct cli_state *cli, int argc, char **argv)
+{
+ uint32 result,
+ info_level = 1;
+ PRINTER_DRIVER_CTR ctr;
+ fstring server;
+ uint32 i, j,
+ returned;
+
+ if (argc > 2)
+ {
+ printf("Usage: enumdrivers [level]\n");
+ return NT_STATUS_NOPROBLEMO;
+ }
+
+ /* Initialise RPC connection */
+ if (!cli_nt_session_open (cli, PIPE_SPOOLSS))
+ {
+ fprintf (stderr, "Could not initialize spoolss pipe!\n");
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ /* get the arguments need to open the printer handle */
+ slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
+ strupper (server);
+ 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++)
+ {
+ returned = 0;
+ result = cli_spoolss_enumprinterdrivers (cli, info_level,
+ archi_table[i].long_archi, &returned, &ctr);
+
+ if (returned == 0)
+ continue;
+
+
+ if (result != NT_STATUS_NO_PROBLEMO)
+ {
+ printf ("Error getting driver for environment [%s] - %s\n",
+ archi_table[i].long_archi, get_nt_error_msg(result));
+ continue;
+ }
+
+ printf ("\n[%s]\n", archi_table[i].long_archi);
+ switch (info_level)
+ {
+
+ case 1:
+ for (j=0; j < returned; j++) {
+ display_print_driver_1 (&(ctr.info1[j]));
+ }
+ break;
+ case 2:
+ for (j=0; j < returned; j++) {
+ display_print_driver_2 (&(ctr.info2[j]));
+ }
+ break;
+ case 3:
+ for (j=0; j < returned; j++) {
+ display_print_driver_3 (&(ctr.info3[j]));
+ }
+ break;
+ default:
+ printf("unknown info level %d\n", info_level);
+ break;
+ }
+ }
+
+
+ /* cleanup */
+ cli_nt_session_close (cli);
+
+ if (result==ERROR_UNKNOWN_PRINTER_DRIVER)
+ return NT_STATUS_NO_PROBLEMO;
+ else
+ return result;
+
+}
+
+
/* List of commands exported by this module */
struct cmd_set spoolss_commands[] = {
@@ -500,8 +828,9 @@ struct cmd_set spoolss_commands[] = {
{ "enumjobs", cmd_spoolss_not_implemented, "Enumerate print jobs (*)" },
{ "enumports", cmd_spoolss_enum_ports, "Enumerate printer ports" },
{ "enumprinters", cmd_spoolss_enum_printers, "Enumerate printers" },
+ { "enumdrivers", cmd_spoolss_enum_drivers, "Enumerate installed printer drivers" },
{ "getdata", cmd_spoolss_not_implemented, "Get print driver data (*)" },
- { "getdriver", cmd_spoolss_not_implemented, "Get print driver information (*)" },
+ { "getdriver", cmd_spoolss_getdriver, "Get print driver information" },
{ "getdriverdir", cmd_spoolss_not_implemented, "Get print driver upload directory (*)" },
{ "getprinter", cmd_spoolss_getprinter, "Get printer info" },
{ "openprinter", cmd_spoolss_open_printer_ex, "Open printer handle" },