From f4ae39d53a62a8496cc20bc554fb7b791676bfdc Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 15 Mar 2001 07:13:27 +0000 Subject: 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) --- source3/libsmb/cli_spoolss.c | 225 ++++++++++++++++++++++- source3/rpc_client/cli_spoolss.c | 2 +- source3/rpcclient/cmd_spoolss.c | 381 ++++++++++++++++++++++++++++++++++++--- 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; iprs.data_offset=0; + + for (i=0; iprs.data_offset=0; + + for (i=0; idesthost); - 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 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 [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" }, -- cgit