LCOV - code coverage report
Current view: top level - source3/rpcclient - cmd_spoolss.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 23 1858 1.2 %
Date: 2023-11-21 12:31:41 Functions: 2 81 2.5 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    RPC pipe client
       4             : 
       5             :    Copyright (C) Gerald Carter                2001-2005
       6             :    Copyright (C) Tim Potter                        2000
       7             :    Copyright (C) Andrew Tridgell              1992-1999
       8             :    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
       9             :    Copyright (C) Guenther Deschner                 2009
      10             : 
      11             :    This program is free software; you can redistribute it and/or modify
      12             :    it under the terms of the GNU General Public License as published by
      13             :    the Free Software Foundation; either version 3 of the License, or
      14             :    (at your option) any later version.
      15             : 
      16             :    This program is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :    GNU General Public License for more details.
      20             : 
      21             :    You should have received a copy of the GNU General Public License
      22             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include "includes.h"
      26             : #include "rpcclient.h"
      27             : #include "../librpc/gen_ndr/ndr_spoolss_c.h"
      28             : #include "../librpc/gen_ndr/ndr_spoolss.h"
      29             : #include "rpc_client/cli_spoolss.h"
      30             : #include "rpc_client/init_spoolss.h"
      31             : #include "nt_printing.h"
      32             : #include "../libcli/security/display_sec.h"
      33             : #include "../libcli/security/security_descriptor.h"
      34             : #include "../libcli/registry/util_reg.h"
      35             : #include "libsmb/libsmb.h"
      36             : #include "lib/util/smb_strtox.h"
      37             : #include "lib/util/string_wrappers.h"
      38             : #include "lib/cmdline/cmdline.h"
      39             : 
      40             : #define RPCCLIENT_PRINTERNAME(_printername, _cli, _arg) \
      41             : { \
      42             :         _printername = talloc_asprintf_strupper_m(mem_ctx, "%s\\%s", \
      43             :                 _cli->srv_name_slash, _arg); \
      44             :         W_ERROR_HAVE_NO_MEMORY(_printername); \
      45             : }
      46             : 
      47             : 
      48             : /**
      49             :  * @file
      50             :  *
      51             :  * rpcclient module for SPOOLSS rpc pipe.
      52             :  *
      53             :  * This generally just parses and checks command lines, and then calls
      54             :  * a cli_spoolss function.
      55             :  **/
      56             : 
      57             : /****************************************************************************
      58             :  function to do the mapping between the long architecture name and
      59             :  the short one.
      60             : ****************************************************************************/
      61             : 
      62           0 : static const char *cmd_spoolss_get_short_archi(const char *long_archi)
      63             : {
      64           0 :         int i=-1;
      65             : 
      66           0 :         DEBUG(107,("Getting architecture dependent directory\n"));
      67             :         do {
      68           0 :                 i++;
      69           0 :         } while ( (archi_table[i].long_archi!=NULL ) &&
      70           0 :                   strcasecmp_m(long_archi, archi_table[i].long_archi) );
      71             : 
      72           0 :         if (archi_table[i].long_archi==NULL) {
      73           0 :                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
      74           0 :                 return NULL;
      75             :         }
      76             : 
      77             :         /* this might be client code - but shouldn't this be an fstrcpy etc? */
      78             : 
      79             : 
      80           0 :         DEBUGADD(108,("index: [%d]\n", i));
      81           0 :         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
      82           0 :         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
      83             : 
      84           0 :         return archi_table[i].short_archi;
      85             : }
      86             : 
      87             : /****************************************************************************
      88             : ****************************************************************************/
      89             : 
      90           0 : static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli,
      91             :                                             TALLOC_CTX *mem_ctx,
      92             :                                             int argc, const char **argv)
      93             : {
      94             :         WERROR          werror;
      95             :         struct policy_handle    hnd;
      96           0 :         uint32_t access_mask = PRINTER_ALL_ACCESS;
      97           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
      98             : 
      99           0 :         if (argc < 2) {
     100           0 :                 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
     101           0 :                 return WERR_OK;
     102             :         }
     103             : 
     104           0 :         if (argc >= 3) {
     105           0 :                 sscanf(argv[2], "%x", &access_mask);
     106             :         }
     107             : 
     108             :         /* Open the printer handle */
     109             : 
     110           0 :         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
     111           0 :                                                argv[1],
     112             :                                                access_mask,
     113             :                                                &hnd);
     114           0 :         if (W_ERROR_IS_OK(werror)) {
     115           0 :                 printf("Printer %s opened successfully\n", argv[1]);
     116           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
     117             : 
     118           0 :                 if (!W_ERROR_IS_OK(werror)) {
     119           0 :                         printf("Error closing printer handle! (%s)\n",
     120             :                                 get_dos_error_msg(werror));
     121             :                 }
     122             :         }
     123             : 
     124           0 :         return werror;
     125             : }
     126             : 
     127             : /****************************************************************************
     128             : ****************************************************************************/
     129             : 
     130           0 : static WERROR cmd_spoolss_open_printer(struct rpc_pipe_client *cli,
     131             :                                        TALLOC_CTX *mem_ctx,
     132             :                                        int argc, const char **argv)
     133             : {
     134             :         WERROR          werror;
     135             :         struct policy_handle    hnd;
     136           0 :         uint32_t access_mask = PRINTER_ALL_ACCESS;
     137             :         NTSTATUS status;
     138             :         struct spoolss_DevmodeContainer devmode_ctr;
     139           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
     140             : 
     141           0 :         ZERO_STRUCT(devmode_ctr);
     142             : 
     143           0 :         if (argc < 2) {
     144           0 :                 printf("Usage: %s <printername> [access_mask]\n", argv[0]);
     145           0 :                 return WERR_OK;
     146             :         }
     147             : 
     148           0 :         if (argc >= 3) {
     149           0 :                 sscanf(argv[2], "%x", &access_mask);
     150             :         }
     151             : 
     152             :         /* Open the printer handle */
     153             : 
     154           0 :         status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
     155           0 :                                             argv[1],
     156             :                                             NULL,
     157             :                                             devmode_ctr,
     158             :                                             access_mask,
     159             :                                             &hnd,
     160             :                                             &werror);
     161           0 :         if (!NT_STATUS_IS_OK(status)) {
     162           0 :                 return ntstatus_to_werror(status);
     163             :         }
     164           0 :         if (W_ERROR_IS_OK(werror)) {
     165           0 :                 printf("Printer %s opened successfully\n", argv[1]);
     166           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &werror);
     167             : 
     168           0 :                 if (!W_ERROR_IS_OK(werror)) {
     169           0 :                         printf("Error closing printer handle! (%s)\n",
     170             :                                 get_dos_error_msg(werror));
     171             :                 }
     172             :         }
     173             : 
     174           0 :         return werror;
     175             : }
     176             : 
     177             : /****************************************************************************
     178             : ****************************************************************************/
     179             : 
     180           0 : static void display_print_info0(struct spoolss_PrinterInfo0 *r)
     181             : {
     182           0 :         if (!r)
     183           0 :                 return;
     184             : 
     185           0 :         printf("\tprintername:[%s]\n", r->printername);
     186           0 :         printf("\tservername:[%s]\n", r->servername);
     187           0 :         printf("\tcjobs:[0x%x]\n", r->cjobs);
     188           0 :         printf("\ttotal_jobs:[0x%x]\n", r->total_jobs);
     189           0 :         printf("\ttotal_bytes:[0x%x]\n", r->total_bytes);
     190           0 :         printf("\t:date: [%d]-[%d]-[%d] (%d)\n", r->time.year, r->time.month,
     191           0 :                r->time.day, r->time.day_of_week);
     192           0 :         printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", r->time.hour, r->time.minute,
     193           0 :                r->time.second, r->time.millisecond);
     194             : 
     195           0 :         printf("\tglobal_counter:[0x%x]\n", r->global_counter);
     196           0 :         printf("\ttotal_pages:[0x%x]\n", r->total_pages);
     197             : 
     198           0 :         printf("\tversion:[0x%x]\n", r->version);
     199           0 :         printf("\tfree_build:[0x%x]\n", r->free_build);
     200           0 :         printf("\tspooling:[0x%x]\n", r->spooling);
     201           0 :         printf("\tmax_spooling:[0x%x]\n", r->max_spooling);
     202           0 :         printf("\tsession_counter:[0x%x]\n", r->session_counter);
     203           0 :         printf("\tnum_error_out_of_paper:[0x%x]\n", r->num_error_out_of_paper);
     204           0 :         printf("\tnum_error_not_ready:[0x%x]\n", r->num_error_not_ready);
     205           0 :         printf("\tjob_error:[0x%x]\n", r->job_error);
     206           0 :         printf("\tnumber_of_processors:[0x%x]\n", r->number_of_processors);
     207           0 :         printf("\tprocessor_type:[0x%x]\n", r->processor_type);
     208           0 :         printf("\thigh_part_total_bytes:[0x%x]\n", r->high_part_total_bytes);
     209           0 :         printf("\tchange_id:[0x%x]\n", r->change_id);
     210           0 :         printf("\tlast_error: %s\n", win_errstr(r->last_error));
     211           0 :         printf("\tstatus:[0x%x]\n", r->status);
     212           0 :         printf("\tenumerate_network_printers:[0x%x]\n", r->enumerate_network_printers);
     213           0 :         printf("\tc_setprinter:[0x%x]\n", r->c_setprinter);
     214           0 :         printf("\tprocessor_architecture:[0x%x]\n", r->processor_architecture);
     215           0 :         printf("\tprocessor_level:[0x%x]\n", r->processor_level);
     216           0 :         printf("\tref_ic:[0x%x]\n", r->ref_ic);
     217           0 :         printf("\treserved2:[0x%x]\n", r->reserved2);
     218           0 :         printf("\treserved3:[0x%x]\n", r->reserved3);
     219             : 
     220           0 :         printf("\n");
     221             : }
     222             : 
     223             : /****************************************************************************
     224             : ****************************************************************************/
     225             : 
     226           0 : static void display_print_info1(struct spoolss_PrinterInfo1 *r)
     227             : {
     228           0 :         printf("\tflags:[0x%x]\n", r->flags);
     229           0 :         printf("\tname:[%s]\n", r->name);
     230           0 :         printf("\tdescription:[%s]\n", r->description);
     231           0 :         printf("\tcomment:[%s]\n", r->comment);
     232             : 
     233           0 :         printf("\n");
     234           0 : }
     235             : 
     236             : /****************************************************************************
     237             : ****************************************************************************/
     238             : 
     239           0 : static void display_print_info2(struct spoolss_PrinterInfo2 *r)
     240             : {
     241           0 :         printf("\tservername:[%s]\n", r->servername);
     242           0 :         printf("\tprintername:[%s]\n", r->printername);
     243           0 :         printf("\tsharename:[%s]\n", r->sharename);
     244           0 :         printf("\tportname:[%s]\n", r->portname);
     245           0 :         printf("\tdrivername:[%s]\n", r->drivername);
     246           0 :         printf("\tcomment:[%s]\n", r->comment);
     247           0 :         printf("\tlocation:[%s]\n", r->location);
     248           0 :         printf("\tsepfile:[%s]\n", r->sepfile);
     249           0 :         printf("\tprintprocessor:[%s]\n", r->printprocessor);
     250           0 :         printf("\tdatatype:[%s]\n", r->datatype);
     251           0 :         printf("\tparameters:[%s]\n", r->parameters);
     252           0 :         printf("\tattributes:[0x%x]\n", r->attributes);
     253           0 :         printf("\tpriority:[0x%x]\n", r->priority);
     254           0 :         printf("\tdefaultpriority:[0x%x]\n", r->defaultpriority);
     255           0 :         printf("\tstarttime:[0x%x]\n", r->starttime);
     256           0 :         printf("\tuntiltime:[0x%x]\n", r->untiltime);
     257           0 :         printf("\tstatus:[0x%x]\n", r->status);
     258           0 :         printf("\tcjobs:[0x%x]\n", r->cjobs);
     259           0 :         printf("\taverageppm:[0x%x]\n", r->averageppm);
     260             : 
     261           0 :         if (r->secdesc)
     262           0 :                 display_sec_desc(r->secdesc);
     263             : 
     264           0 :         printf("\n");
     265           0 : }
     266             : 
     267             : /****************************************************************************
     268             : ****************************************************************************/
     269             : 
     270           0 : static void display_print_info3(struct spoolss_PrinterInfo3 *r)
     271             : {
     272           0 :         display_sec_desc(r->secdesc);
     273             : 
     274           0 :         printf("\n");
     275           0 : }
     276             : 
     277             : /****************************************************************************
     278             : ****************************************************************************/
     279             : 
     280           0 : static void display_print_info4(struct spoolss_PrinterInfo4 *r)
     281             : {
     282           0 :         printf("\tservername:[%s]\n", r->servername);
     283           0 :         printf("\tprintername:[%s]\n", r->printername);
     284           0 :         printf("\tattributes:[0x%x]\n", r->attributes);
     285           0 :         printf("\n");
     286           0 : }
     287             : 
     288             : /****************************************************************************
     289             : ****************************************************************************/
     290             : 
     291           0 : static void display_print_info5(struct spoolss_PrinterInfo5 *r)
     292             : {
     293           0 :         printf("\tprintername:[%s]\n", r->printername);
     294           0 :         printf("\tportname:[%s]\n", r->portname);
     295           0 :         printf("\tattributes:[0x%x]\n", r->attributes);
     296           0 :         printf("\tdevice_not_selected_timeout:[0x%x]\n", r->device_not_selected_timeout);
     297           0 :         printf("\ttransmission_retry_timeout:[0x%x]\n", r->transmission_retry_timeout);
     298           0 :         printf("\n");
     299           0 : }
     300             : 
     301             : /****************************************************************************
     302             : ****************************************************************************/
     303             : 
     304           0 : static void display_print_info6(struct spoolss_PrinterInfo6 *r)
     305             : {
     306           0 :         printf("\tstatus:[0x%x]\n", r->status);
     307           0 :         printf("\n");
     308           0 : }
     309             : 
     310             : /****************************************************************************
     311             : ****************************************************************************/
     312             : 
     313           0 : static void display_print_info7(struct spoolss_PrinterInfo7 *r)
     314             : {
     315           0 :         printf("\tguid:[%s]\n", r->guid);
     316           0 :         printf("\taction:[0x%x]\n", r->action);
     317           0 :         printf("\n");
     318           0 : }
     319             : 
     320             : /****************************************************************************
     321             : ****************************************************************************/
     322             : 
     323           0 : static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli,
     324             :                                         TALLOC_CTX *mem_ctx,
     325             :                                         int argc, const char **argv)
     326             : {
     327             :         WERROR                  result;
     328           0 :         uint32_t                level = 1;
     329             :         union spoolss_PrinterInfo *info;
     330             :         uint32_t                i, count;
     331             :         const char *name;
     332           0 :         uint32_t flags = PRINTER_ENUM_LOCAL;
     333             : 
     334           0 :         if (argc > 4) {
     335           0 :                 printf("Usage: %s [level] [name] [flags]\n", argv[0]);
     336           0 :                 return WERR_OK;
     337             :         }
     338             : 
     339           0 :         if (argc >= 2) {
     340           0 :                 level = atoi(argv[1]);
     341             :         }
     342             : 
     343           0 :         if (argc >= 3) {
     344           0 :                 name = argv[2];
     345             :         } else {
     346           0 :                 name = cli->srv_name_slash;
     347             :         }
     348             : 
     349           0 :         if (argc == 4) {
     350           0 :                 flags = atoi(argv[3]);
     351             :         }
     352             : 
     353           0 :         result = rpccli_spoolss_enumprinters(cli, mem_ctx,
     354             :                                              flags,
     355             :                                              name,
     356             :                                              level,
     357             :                                              0,
     358             :                                              &count,
     359             :                                              &info);
     360           0 :         if (W_ERROR_IS_OK(result)) {
     361             : 
     362           0 :                 if (!count) {
     363           0 :                         printf ("No printers returned.\n");
     364           0 :                         goto done;
     365             :                 }
     366             : 
     367           0 :                 for (i = 0; i < count; i++) {
     368           0 :                         switch (level) {
     369           0 :                         case 0:
     370           0 :                                 display_print_info0(&info[i].info0);
     371           0 :                                 break;
     372           0 :                         case 1:
     373           0 :                                 display_print_info1(&info[i].info1);
     374           0 :                                 break;
     375           0 :                         case 2:
     376           0 :                                 display_print_info2(&info[i].info2);
     377           0 :                                 break;
     378           0 :                         case 3:
     379           0 :                                 display_print_info3(&info[i].info3);
     380           0 :                                 break;
     381           0 :                         case 4:
     382           0 :                                 display_print_info4(&info[i].info4);
     383           0 :                                 break;
     384           0 :                         case 5:
     385           0 :                                 display_print_info5(&info[i].info5);
     386           0 :                                 break;
     387           0 :                         case 6:
     388           0 :                                 display_print_info6(&info[i].info6);
     389           0 :                                 break;
     390           0 :                         default:
     391           0 :                                 printf("unknown info level %d\n", level);
     392           0 :                                 goto done;
     393             :                         }
     394             :                 }
     395             :         }
     396           0 :  done:
     397             : 
     398           0 :         return result;
     399             : }
     400             : 
     401             : /****************************************************************************
     402             : ****************************************************************************/
     403             : 
     404           0 : static void display_port_info_1(struct spoolss_PortInfo1 *r)
     405             : {
     406           0 :         printf("\tPort Name:\t[%s]\n", r->port_name);
     407           0 : }
     408             : 
     409             : /****************************************************************************
     410             : ****************************************************************************/
     411             : 
     412           0 : static void display_port_info_2(struct spoolss_PortInfo2 *r)
     413             : {
     414           0 :         printf("\tPort Name:\t[%s]\n", r->port_name);
     415           0 :         printf("\tMonitor Name:\t[%s]\n", r->monitor_name);
     416           0 :         printf("\tDescription:\t[%s]\n", r->description);
     417           0 :         printf("\tPort Type:\t" );
     418           0 :         if (r->port_type) {
     419           0 :                 int comma = 0; /* hack */
     420           0 :                 printf( "[" );
     421           0 :                 if (r->port_type & SPOOLSS_PORT_TYPE_READ) {
     422           0 :                         printf( "Read" );
     423           0 :                         comma = 1;
     424             :                 }
     425           0 :                 if (r->port_type & SPOOLSS_PORT_TYPE_WRITE) {
     426           0 :                         printf( "%sWrite", comma ? ", " : "" );
     427           0 :                         comma = 1;
     428             :                 }
     429             :                 /* These two have slightly different interpretations
     430             :                  on 95/98/ME but I'm disregarding that for now */
     431           0 :                 if (r->port_type & SPOOLSS_PORT_TYPE_REDIRECTED) {
     432           0 :                         printf( "%sRedirected", comma ? ", " : "" );
     433           0 :                         comma = 1;
     434             :                 }
     435           0 :                 if (r->port_type & SPOOLSS_PORT_TYPE_NET_ATTACHED) {
     436           0 :                         printf( "%sNet-Attached", comma ? ", " : "" );
     437             :                 }
     438           0 :                 printf( "]\n" );
     439             :         } else {
     440           0 :                 printf( "[Unset]\n" );
     441             :         }
     442           0 :         printf("\tReserved:\t[%d]\n", r->reserved);
     443           0 :         printf("\n");
     444           0 : }
     445             : 
     446             : /****************************************************************************
     447             : ****************************************************************************/
     448             : 
     449           0 : static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli,
     450             :                                        TALLOC_CTX *mem_ctx, int argc,
     451             :                                        const char **argv)
     452             : {
     453             :         WERROR                  result;
     454           0 :         uint32_t                level = 1;
     455             :         uint32_t                count;
     456             :         union spoolss_PortInfo *info;
     457             : 
     458           0 :         if (argc > 2) {
     459           0 :                 printf("Usage: %s [level]\n", argv[0]);
     460           0 :                 return WERR_OK;
     461             :         }
     462             : 
     463           0 :         if (argc == 2) {
     464           0 :                 level = atoi(argv[1]);
     465             :         }
     466             : 
     467             :         /* Enumerate ports */
     468             : 
     469           0 :         result = rpccli_spoolss_enumports(cli, mem_ctx,
     470           0 :                                           cli->srv_name_slash,
     471             :                                           level,
     472             :                                           0,
     473             :                                           &count,
     474             :                                           &info);
     475           0 :         if (W_ERROR_IS_OK(result)) {
     476             :                 int i;
     477             : 
     478           0 :                 for (i = 0; i < count; i++) {
     479           0 :                         switch (level) {
     480           0 :                         case 1:
     481           0 :                                 display_port_info_1(&info[i].info1);
     482           0 :                                 break;
     483           0 :                         case 2:
     484           0 :                                 display_port_info_2(&info[i].info2);
     485           0 :                                 break;
     486           0 :                         default:
     487           0 :                                 printf("unknown info level %d\n", level);
     488           0 :                                 break;
     489             :                         }
     490             :                 }
     491             :         }
     492             : 
     493           0 :         return result;
     494             : }
     495             : 
     496             : /****************************************************************************
     497             : ****************************************************************************/
     498             : 
     499           0 : static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
     500             :                                        TALLOC_CTX *mem_ctx,
     501             :                                        int argc, const char **argv)
     502             : {
     503             :         struct policy_handle pol;
     504             :         WERROR          result;
     505             :         NTSTATUS        status;
     506           0 :         uint32_t        info_level = 2;
     507             :         union spoolss_PrinterInfo info;
     508             :         struct spoolss_SetPrinterInfoCtr info_ctr;
     509             :         struct spoolss_SetPrinterInfo2 info2;
     510           0 :         const char      *printername, *comment = NULL;
     511             :         struct spoolss_DevmodeContainer devmode_ctr;
     512             :         struct sec_desc_buf secdesc_ctr;
     513           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
     514             : 
     515           0 :         if (argc == 1 || argc > 3) {
     516           0 :                 printf("Usage: %s printername comment\n", argv[0]);
     517             : 
     518           0 :                 return WERR_OK;
     519             :         }
     520             : 
     521             :         /* Open a printer handle */
     522           0 :         if (argc == 3) {
     523           0 :                 comment = argv[2];
     524             :         }
     525             : 
     526           0 :         ZERO_STRUCT(devmode_ctr);
     527           0 :         ZERO_STRUCT(secdesc_ctr);
     528             : 
     529           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
     530             : 
     531             :         /* get a printer handle */
     532           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
     533             :                                                printername,
     534             :                                                PRINTER_ALL_ACCESS,
     535             :                                                &pol);
     536           0 :         if (!W_ERROR_IS_OK(result))
     537           0 :                 goto done;
     538             : 
     539             :         /* Get printer info */
     540           0 :         result = rpccli_spoolss_getprinter(cli, mem_ctx,
     541             :                                            &pol,
     542             :                                            info_level,
     543             :                                            0,
     544             :                                            &info);
     545           0 :         if (!W_ERROR_IS_OK(result))
     546           0 :                 goto done;
     547             : 
     548             : 
     549             :         /* Modify the comment. */
     550           0 :         spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
     551           0 :         info2.comment = comment;
     552             : 
     553           0 :         info_ctr.level = 2;
     554           0 :         info_ctr.info.info2 = &info2;
     555             : 
     556           0 :         status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
     557             :                                            &pol,
     558             :                                            &info_ctr,
     559             :                                            &devmode_ctr,
     560             :                                            &secdesc_ctr,
     561             :                                            0, /* command */
     562             :                                            &result);
     563           0 :         if (!NT_STATUS_IS_OK(status)) {
     564           0 :                 result = ntstatus_to_werror(status);
     565           0 :                 goto done;
     566             :         }
     567           0 :         if (W_ERROR_IS_OK(result))
     568           0 :                 printf("Success in setting comment.\n");
     569             : 
     570           0 :  done:
     571           0 :         if (is_valid_policy_hnd(&pol)) {
     572             :                 WERROR _result;
     573           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
     574             :         }
     575             : 
     576           0 :         return result;
     577             : }
     578             : 
     579             : /****************************************************************************
     580             : ****************************************************************************/
     581             : 
     582           0 : static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
     583             :                                        TALLOC_CTX *mem_ctx,
     584             :                                        int argc, const char **argv)
     585             : {
     586             :         struct policy_handle pol;
     587             :         WERROR          result;
     588             :         NTSTATUS        status;
     589           0 :         uint32_t        info_level = 2;
     590             :         union spoolss_PrinterInfo info;
     591             :         const char      *printername,
     592           0 :                         *new_printername = NULL;
     593             :         struct spoolss_SetPrinterInfoCtr info_ctr;
     594             :         struct spoolss_SetPrinterInfo2 info2;
     595             :         struct spoolss_DevmodeContainer devmode_ctr;
     596             :         struct sec_desc_buf secdesc_ctr;
     597           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
     598             : 
     599           0 :         ZERO_STRUCT(devmode_ctr);
     600           0 :         ZERO_STRUCT(secdesc_ctr);
     601             : 
     602           0 :         if (argc == 1 || argc > 3) {
     603           0 :                 printf("Usage: %s printername new_printername\n", argv[0]);
     604             : 
     605           0 :                 return WERR_OK;
     606             :         }
     607             : 
     608             :         /* Open a printer handle */
     609           0 :         if (argc == 3) {
     610           0 :                 new_printername = argv[2];
     611             :         }
     612             : 
     613           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
     614             : 
     615             :         /* get a printer handle */
     616           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
     617             :                                                printername,
     618             :                                                PRINTER_ALL_ACCESS,
     619             :                                                &pol);
     620           0 :         if (!W_ERROR_IS_OK(result))
     621           0 :                 goto done;
     622             : 
     623             :         /* Get printer info */
     624           0 :         result = rpccli_spoolss_getprinter(cli, mem_ctx,
     625             :                                            &pol,
     626             :                                            info_level,
     627             :                                            0,
     628             :                                            &info);
     629           0 :         if (!W_ERROR_IS_OK(result))
     630           0 :                 goto done;
     631             : 
     632             :         /* Modify the printername. */
     633           0 :         spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
     634           0 :         info2.printername = new_printername;
     635             : 
     636           0 :         info_ctr.level = 2;
     637           0 :         info_ctr.info.info2 = &info2;
     638             : 
     639           0 :         status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
     640             :                                            &pol,
     641             :                                            &info_ctr,
     642             :                                            &devmode_ctr,
     643             :                                            &secdesc_ctr,
     644             :                                            0, /* command */
     645             :                                            &result);
     646           0 :         if (!NT_STATUS_IS_OK(status)) {
     647           0 :                 result = ntstatus_to_werror(status);
     648           0 :                 goto done;
     649             :         }
     650           0 :         if (W_ERROR_IS_OK(result))
     651           0 :                 printf("Success in setting printername.\n");
     652             : 
     653           0 :  done:
     654           0 :         if (is_valid_policy_hnd(&pol)) {
     655             :                 WERROR _result;
     656           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
     657             :         }
     658             : 
     659           0 :         return result;
     660             : }
     661             : 
     662             : /****************************************************************************
     663             : ****************************************************************************/
     664             : 
     665           0 : static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
     666             :                                        TALLOC_CTX *mem_ctx,
     667             :                                        int argc, const char **argv)
     668             : {
     669             :         struct policy_handle pol;
     670             :         WERROR          result;
     671           0 :         uint32_t        level = 1;
     672             :         const char      *printername;
     673             :         union spoolss_PrinterInfo info;
     674           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
     675             : 
     676           0 :         if (argc == 1 || argc > 3) {
     677           0 :                 printf("Usage: %s <printername> [level]\n", argv[0]);
     678           0 :                 return WERR_OK;
     679             :         }
     680             : 
     681             :         /* Open a printer handle */
     682           0 :         if (argc == 3) {
     683           0 :                 level = atoi(argv[2]);
     684             :         }
     685             : 
     686           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
     687             : 
     688             :         /* get a printer handle */
     689             : 
     690           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
     691             :                                                printername,
     692             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
     693             :                                                &pol);
     694           0 :         if (!W_ERROR_IS_OK(result)) {
     695           0 :                 goto done;
     696             :         }
     697             : 
     698             :         /* Get printer info */
     699             : 
     700           0 :         result = rpccli_spoolss_getprinter(cli, mem_ctx,
     701             :                                            &pol,
     702             :                                            level,
     703             :                                            0,
     704             :                                            &info);
     705           0 :         if (!W_ERROR_IS_OK(result)) {
     706           0 :                 goto done;
     707             :         }
     708             : 
     709             :         /* Display printer info */
     710           0 :         switch (level) {
     711           0 :         case 0:
     712           0 :                 display_print_info0(&info.info0);
     713           0 :                 break;
     714           0 :         case 1:
     715           0 :                 display_print_info1(&info.info1);
     716           0 :                 break;
     717           0 :         case 2:
     718           0 :                 display_print_info2(&info.info2);
     719           0 :                 break;
     720           0 :         case 3:
     721           0 :                 display_print_info3(&info.info3);
     722           0 :                 break;
     723           0 :         case 4:
     724           0 :                 display_print_info4(&info.info4);
     725           0 :                 break;
     726           0 :         case 5:
     727           0 :                 display_print_info5(&info.info5);
     728           0 :                 break;
     729           0 :         case 6:
     730           0 :                 display_print_info6(&info.info6);
     731           0 :                 break;
     732           0 :         case 7:
     733           0 :                 display_print_info7(&info.info7);
     734           0 :                 break;
     735           0 :         default:
     736           0 :                 printf("unknown info level %d\n", level);
     737           0 :                 break;
     738             :         }
     739           0 :  done:
     740           0 :         if (is_valid_policy_hnd(&pol)) {
     741             :                 WERROR _result;
     742           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
     743             :         }
     744             : 
     745           0 :         return result;
     746             : }
     747             : 
     748             : /****************************************************************************
     749             : ****************************************************************************/
     750             : 
     751           0 : static void display_reg_value(const char *name, enum winreg_Type type, DATA_BLOB blob)
     752             : {
     753           0 :         const char *text = NULL;
     754             : 
     755           0 :         switch(type) {
     756           0 :         case REG_DWORD:
     757           0 :                 if (blob.length >= sizeof(uint32_t)) {
     758           0 :                         printf("%s: REG_DWORD: 0x%08x\n", name, IVAL(blob.data,0));
     759             :                 } else {
     760           0 :                         printf("%s: REG_DWORD: <invalid>\n", name);
     761             :                 }
     762           0 :                 break;
     763           0 :         case REG_SZ:
     764           0 :                 pull_reg_sz(talloc_tos(), &blob, &text);
     765           0 :                 printf("%s: REG_SZ: %s\n", name, text ? text : "");
     766           0 :                 break;
     767           0 :         case REG_BINARY: {
     768           0 :                 char *hex = hex_encode_talloc(NULL, blob.data, blob.length);
     769             :                 size_t i, len;
     770           0 :                 printf("%s: REG_BINARY:", name);
     771           0 :                 len = strlen(hex);
     772           0 :                 for (i=0; i<len; i++) {
     773           0 :                         if (hex[i] == '\0') {
     774           0 :                                 break;
     775             :                         }
     776           0 :                         if (i%40 == 0) {
     777           0 :                                 putchar('\n');
     778             :                         }
     779           0 :                         putchar(hex[i]);
     780             :                 }
     781           0 :                 TALLOC_FREE(hex);
     782           0 :                 putchar('\n');
     783           0 :                 break;
     784             :         }
     785           0 :         case REG_MULTI_SZ: {
     786             :                 uint32_t i;
     787             :                 const char **values;
     788             : 
     789           0 :                 if (!pull_reg_multi_sz(NULL, &blob, &values)) {
     790           0 :                         d_printf("pull_reg_multi_sz failed\n");
     791           0 :                         break;
     792             :                 }
     793             : 
     794           0 :                 printf("%s: REG_MULTI_SZ: \n", name);
     795           0 :                 for (i=0; values[i] != NULL; i++) {
     796           0 :                         d_printf("%s\n", values[i]);
     797             :                 }
     798           0 :                 TALLOC_FREE(values);
     799           0 :                 break;
     800             :         }
     801           0 :         default:
     802           0 :                 printf("%s: unknown type %d\n", name, type);
     803             :         }
     804             : 
     805           0 : }
     806             : 
     807             : /****************************************************************************
     808             : ****************************************************************************/
     809             : 
     810           0 : static void display_printer_data(const char *v,
     811             :                                  enum winreg_Type type,
     812             :                                  uint8_t *data,
     813             :                                  uint32_t length)
     814             : {
     815             :         int i;
     816             :         union spoolss_PrinterData r;
     817           0 :         DATA_BLOB blob = data_blob_const(data, length);
     818             :         WERROR result;
     819             :         enum ndr_err_code ndr_err;
     820             : 
     821           0 :         result = pull_spoolss_PrinterData(talloc_tos(), &blob, &r, type);
     822           0 :         if (!W_ERROR_IS_OK(result)) {
     823           0 :                 return;
     824             :         }
     825             : 
     826           0 :         switch (type) {
     827           0 :         case REG_DWORD:
     828           0 :                 printf("%s: REG_DWORD: 0x%08x\n", v, r.value);
     829           0 :                 break;
     830           0 :         case REG_SZ:
     831           0 :                 printf("%s: REG_SZ: %s\n", v, r.string);
     832           0 :                 break;
     833           0 :         case REG_BINARY: {
     834           0 :                 char *hex = hex_encode_talloc(NULL,
     835           0 :                         r.binary.data, r.binary.length);
     836             :                 size_t len;
     837           0 :                 printf("%s: REG_BINARY:", v);
     838           0 :                 len = strlen(hex);
     839           0 :                 for (i=0; i<len; i++) {
     840           0 :                         if (hex[i] == '\0') {
     841           0 :                                 break;
     842             :                         }
     843           0 :                         if (i%40 == 0) {
     844           0 :                                 putchar('\n');
     845             :                         }
     846           0 :                         putchar(hex[i]);
     847             :                 }
     848           0 :                 TALLOC_FREE(hex);
     849           0 :                 putchar('\n');
     850           0 :                 putchar('\n');
     851             : 
     852           0 :                 if (strequal(v, "OsVersion")) {
     853             :                         struct spoolss_OSVersion os;
     854           0 :                         ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
     855             :                                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersion);
     856           0 :                         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     857             :                                 // add output here;
     858           0 :                                 printf("OsMajor: %u\n", os.major);
     859           0 :                                 printf("OsMinor: %u\n", os.minor);
     860           0 :                                 printf("OsBuild: %u\n", os.build);
     861           0 :                                 NDR_PRINT_DEBUG(spoolss_OSVersion, &os);
     862             :                         }
     863             :                 }
     864           0 :                 if (strequal(v, "OsVersionEx")) {
     865             :                         struct spoolss_OSVersionEx os;
     866           0 :                         ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &os,
     867             :                                 (ndr_pull_flags_fn_t)ndr_pull_spoolss_OSVersionEx);
     868           0 :                         if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     869           0 :                                 printf("OsMajor: %u\n", os.major);
     870           0 :                                 printf("OsMinor: %u\n", os.minor);
     871           0 :                                 printf("OsBuild: %u\n", os.build);
     872           0 :                                 printf("ServicePackMajor: %u\n", os.service_pack_major);
     873           0 :                                 printf("ServicePackMinor: %u\n", os.service_pack_minor);
     874           0 :                                 NDR_PRINT_DEBUG(spoolss_OSVersionEx, &os);
     875             :                         }
     876             :                 }
     877           0 :                 break;
     878             :         }
     879           0 :         case REG_MULTI_SZ:
     880           0 :                 printf("%s: REG_MULTI_SZ: ", v);
     881           0 :                 for (i=0; r.string_array[i] != NULL; i++) {
     882           0 :                         printf("%s ", r.string_array[i]);
     883             :                 }
     884           0 :                 printf("\n");
     885           0 :                 break;
     886           0 :         default:
     887           0 :                 printf("%s: unknown type 0x%02x:\n", v, type);
     888           0 :                 break;
     889             :         }
     890             : }
     891             : 
     892             : /****************************************************************************
     893             : ****************************************************************************/
     894             : 
     895           0 : static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
     896             :                                            TALLOC_CTX *mem_ctx,
     897             :                                            int argc, const char **argv)
     898             : {
     899             :         struct policy_handle pol;
     900             :         WERROR          result;
     901             :         fstring         printername;
     902             :         const char *valuename;
     903             :         enum winreg_Type type;
     904             :         uint8_t *data;
     905             :         uint32_t needed;
     906           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
     907             : 
     908           0 :         if (argc != 3) {
     909           0 :                 printf("Usage: %s <printername> <valuename>\n", argv[0]);
     910           0 :                 printf("<printername> of . queries print server\n");
     911           0 :                 return WERR_OK;
     912             :         }
     913           0 :         valuename = argv[2];
     914             : 
     915             :         /* Open a printer handle */
     916             : 
     917           0 :         if (strncmp(argv[1], ".", sizeof(".")) == 0)
     918           0 :                 fstrcpy(printername, cli->srv_name_slash);
     919             :         else
     920           0 :                 slprintf(printername, sizeof(printername)-1, "%s\\%s",
     921           0 :                           cli->srv_name_slash, argv[1]);
     922             : 
     923             :         /* get a printer handle */
     924             : 
     925           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
     926             :                                                printername,
     927             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
     928             :                                                &pol);
     929           0 :         if (!W_ERROR_IS_OK(result))
     930           0 :                 goto done;
     931             : 
     932             :         /* Get printer info */
     933             : 
     934           0 :         result = rpccli_spoolss_getprinterdata(cli, mem_ctx,
     935             :                                                &pol,
     936             :                                                valuename,
     937             :                                                0,
     938             :                                                &type,
     939             :                                                &needed,
     940             :                                                &data);
     941           0 :         if (!W_ERROR_IS_OK(result))
     942           0 :                 goto done;
     943             : 
     944             :         /* Display printer data */
     945             : 
     946           0 :         display_printer_data(valuename, type, data, needed);
     947             : 
     948           0 :  done:
     949           0 :         if (is_valid_policy_hnd(&pol)) {
     950             :                 WERROR _result;
     951           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
     952             :         }
     953             : 
     954           0 :         return result;
     955             : }
     956             : 
     957             : /****************************************************************************
     958             : ****************************************************************************/
     959             : 
     960           0 : static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
     961             :                                              TALLOC_CTX *mem_ctx,
     962             :                                              int argc, const char **argv)
     963             : {
     964             :         struct policy_handle pol;
     965             :         WERROR          result;
     966             :         NTSTATUS        status;
     967             :         fstring         printername;
     968             :         const char *valuename, *keyname;
     969             : 
     970             :         enum winreg_Type type;
     971           0 :         uint8_t *data = NULL;
     972           0 :         uint32_t offered = 0;
     973             :         uint32_t needed;
     974           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
     975             : 
     976           0 :         if (argc != 4) {
     977           0 :                 printf("Usage: %s <printername> <keyname> <valuename>\n",
     978             :                        argv[0]);
     979           0 :                 printf("<printername> of . queries print server\n");
     980           0 :                 return WERR_OK;
     981             :         }
     982           0 :         valuename = argv[3];
     983           0 :         keyname = argv[2];
     984             : 
     985             :         /* Open a printer handle */
     986             : 
     987           0 :         if (strncmp(argv[1], ".", sizeof(".")) == 0)
     988           0 :                 fstrcpy(printername, cli->srv_name_slash);
     989             :         else
     990           0 :                 slprintf(printername, sizeof(printername)-1, "%s\\%s",
     991           0 :                           cli->srv_name_slash, argv[1]);
     992             : 
     993             :         /* get a printer handle */
     994             : 
     995           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
     996             :                                                printername,
     997             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
     998             :                                                &pol);
     999           0 :         if (!W_ERROR_IS_OK(result))
    1000           0 :                 goto done;
    1001             : 
    1002             :         /* Get printer info */
    1003             : 
    1004           0 :         data = talloc_zero_array(mem_ctx, uint8_t, offered);
    1005           0 :         if (!data) {
    1006           0 :                 goto done;
    1007             :         }
    1008             : 
    1009           0 :         status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
    1010             :                                                  &pol,
    1011             :                                                  keyname,
    1012             :                                                  valuename,
    1013             :                                                  &type,
    1014             :                                                  data,
    1015             :                                                  offered,
    1016             :                                                  &needed,
    1017             :                                                  &result);
    1018           0 :         if (!NT_STATUS_IS_OK(status)) {
    1019           0 :                 result = ntstatus_to_werror(status);
    1020           0 :                 goto done;
    1021             :         }
    1022           0 :         if (W_ERROR_EQUAL(result, WERR_MORE_DATA)) {
    1023           0 :                 offered = needed;
    1024           0 :                 data = talloc_zero_array(mem_ctx, uint8_t, offered);
    1025           0 :                 if (!data) {
    1026           0 :                         goto done;
    1027             :                 }
    1028           0 :                 status = dcerpc_spoolss_GetPrinterDataEx(b, mem_ctx,
    1029             :                                                          &pol,
    1030             :                                                          keyname,
    1031             :                                                          valuename,
    1032             :                                                          &type,
    1033             :                                                          data,
    1034             :                                                          offered,
    1035             :                                                          &needed,
    1036             :                                                          &result);
    1037             :         }
    1038             : 
    1039           0 :         if (!NT_STATUS_IS_OK(status)) {
    1040           0 :                 result = ntstatus_to_werror(status);
    1041           0 :                 goto done;
    1042             :         }
    1043             : 
    1044           0 :         if (!W_ERROR_IS_OK(result))
    1045           0 :                 goto done;
    1046             : 
    1047             :         /* Display printer data */
    1048             : 
    1049           0 :         display_printer_data(valuename, type, data, needed);
    1050             : 
    1051             : 
    1052           0 :  done:
    1053           0 :         if (is_valid_policy_hnd(&pol)) {
    1054             :                 WERROR _result;
    1055           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
    1056             :         }
    1057             : 
    1058           0 :         return result;
    1059             : }
    1060             : 
    1061             : /****************************************************************************
    1062             : ****************************************************************************/
    1063             : 
    1064           0 : static void display_print_driver1(struct spoolss_DriverInfo1 *r)
    1065             : {
    1066           0 :         if (!r) {
    1067           0 :                 return;
    1068             :         }
    1069             : 
    1070           0 :         printf("Printer Driver Info 1:\n");
    1071           0 :         printf("\tDriver Name: [%s]\n", r->driver_name);
    1072           0 :         printf("\n");
    1073             : }
    1074             : 
    1075             : /****************************************************************************
    1076             : ****************************************************************************/
    1077             : 
    1078           0 : static void display_print_driver2(struct spoolss_DriverInfo2 *r)
    1079             : {
    1080           0 :         if (!r) {
    1081           0 :                 return;
    1082             :         }
    1083             : 
    1084           0 :         printf("Printer Driver Info 2:\n");
    1085           0 :         printf("\tVersion: [%x]\n", r->version);
    1086           0 :         printf("\tDriver Name: [%s]\n", r->driver_name);
    1087           0 :         printf("\tArchitecture: [%s]\n", r->architecture);
    1088           0 :         printf("\tDriver Path: [%s]\n", r->driver_path);
    1089           0 :         printf("\tDatafile: [%s]\n", r->data_file);
    1090           0 :         printf("\tConfigfile: [%s]\n", r->config_file);
    1091           0 :         printf("\n");
    1092             : }
    1093             : 
    1094             : /****************************************************************************
    1095             : ****************************************************************************/
    1096             : 
    1097           0 : static void display_print_driver3(struct spoolss_DriverInfo3 *r)
    1098             : {
    1099             :         int i;
    1100             : 
    1101           0 :         if (!r) {
    1102           0 :                 return;
    1103             :         }
    1104             : 
    1105           0 :         printf("Printer Driver Info 3:\n");
    1106           0 :         printf("\tVersion: [%x]\n", r->version);
    1107           0 :         printf("\tDriver Name: [%s]\n", r->driver_name);
    1108           0 :         printf("\tArchitecture: [%s]\n", r->architecture);
    1109           0 :         printf("\tDriver Path: [%s]\n", r->driver_path);
    1110           0 :         printf("\tDatafile: [%s]\n", r->data_file);
    1111           0 :         printf("\tConfigfile: [%s]\n", r->config_file);
    1112           0 :         printf("\tHelpfile: [%s]\n", r->help_file);
    1113             : 
    1114           0 :         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
    1115           0 :                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
    1116             :         }
    1117             : 
    1118           0 :         printf("\tMonitorname: [%s]\n", r->monitor_name);
    1119           0 :         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
    1120           0 :         printf("\n");
    1121             : }
    1122             : 
    1123             : /****************************************************************************
    1124             : ****************************************************************************/
    1125             : 
    1126           0 : static void display_print_driver4(struct spoolss_DriverInfo4 *r)
    1127             : {
    1128             :         int i;
    1129             : 
    1130           0 :         if (!r) {
    1131           0 :                 return;
    1132             :         }
    1133             : 
    1134           0 :         printf("Printer Driver Info 4:\n");
    1135           0 :         printf("\tVersion: [%x]\n", r->version);
    1136           0 :         printf("\tDriver Name: [%s]\n", r->driver_name);
    1137           0 :         printf("\tArchitecture: [%s]\n", r->architecture);
    1138           0 :         printf("\tDriver Path: [%s]\n", r->driver_path);
    1139           0 :         printf("\tDatafile: [%s]\n", r->data_file);
    1140           0 :         printf("\tConfigfile: [%s]\n", r->config_file);
    1141           0 :         printf("\tHelpfile: [%s]\n", r->help_file);
    1142             : 
    1143           0 :         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
    1144           0 :                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
    1145             :         }
    1146             : 
    1147           0 :         printf("\tMonitorname: [%s]\n", r->monitor_name);
    1148           0 :         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
    1149             : 
    1150           0 :         for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
    1151           0 :                 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
    1152             :         }
    1153           0 :         printf("\n");
    1154             : }
    1155             : 
    1156             : /****************************************************************************
    1157             : ****************************************************************************/
    1158             : 
    1159           0 : static void display_print_driver5(struct spoolss_DriverInfo5 *r)
    1160             : {
    1161           0 :         if (!r) {
    1162           0 :                 return;
    1163             :         }
    1164             : 
    1165           0 :         printf("Printer Driver Info 5:\n");
    1166           0 :         printf("\tVersion: [%x]\n", r->version);
    1167           0 :         printf("\tDriver Name: [%s]\n", r->driver_name);
    1168           0 :         printf("\tArchitecture: [%s]\n", r->architecture);
    1169           0 :         printf("\tDriver Path: [%s]\n", r->driver_path);
    1170           0 :         printf("\tDatafile: [%s]\n", r->data_file);
    1171           0 :         printf("\tConfigfile: [%s]\n", r->config_file);
    1172           0 :         printf("\tDriver Attributes: [0x%x]\n", r->driver_attributes);
    1173           0 :         printf("\tConfig Version: [0x%x]\n", r->config_version);
    1174           0 :         printf("\tDriver Version: [0x%x]\n", r->driver_version);
    1175           0 :         printf("\n");
    1176             : }
    1177             : 
    1178             : /****************************************************************************
    1179             : ****************************************************************************/
    1180             : 
    1181           0 : static void display_print_driver6(struct spoolss_DriverInfo6 *r)
    1182             : {
    1183             :         int i;
    1184             : 
    1185           0 :         if (!r) {
    1186           0 :                 return;
    1187             :         }
    1188             : 
    1189           0 :         printf("Printer Driver Info 6:\n");
    1190           0 :         printf("\tVersion: [%x]\n", r->version);
    1191           0 :         printf("\tDriver Name: [%s]\n", r->driver_name);
    1192           0 :         printf("\tArchitecture: [%s]\n", r->architecture);
    1193           0 :         printf("\tDriver Path: [%s]\n", r->driver_path);
    1194           0 :         printf("\tDatafile: [%s]\n", r->data_file);
    1195           0 :         printf("\tConfigfile: [%s]\n", r->config_file);
    1196           0 :         printf("\tHelpfile: [%s]\n", r->help_file);
    1197             : 
    1198           0 :         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
    1199           0 :                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
    1200             :         }
    1201             : 
    1202           0 :         printf("\tMonitorname: [%s]\n", r->monitor_name);
    1203           0 :         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
    1204             : 
    1205           0 :         for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
    1206           0 :                 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
    1207             :         }
    1208             : 
    1209           0 :         printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
    1210           0 :         printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
    1211           0 :         printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
    1212           0 :         printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
    1213           0 :         printf("\tHardware ID: [%s]\n", r->hardware_id);
    1214           0 :         printf("\tProvider: [%s]\n", r->provider);
    1215             : 
    1216           0 :         printf("\n");
    1217             : }
    1218             : 
    1219             : /****************************************************************************
    1220             : ****************************************************************************/
    1221             : 
    1222           0 : static void display_print_driver8(struct spoolss_DriverInfo8 *r)
    1223             : {
    1224             :         int i;
    1225             : 
    1226           0 :         if (!r) {
    1227           0 :                 return;
    1228             :         }
    1229             : 
    1230           0 :         printf("Printer Driver Info 8:\n");
    1231           0 :         printf("\tVersion: [%x]\n", r->version);
    1232           0 :         printf("\tDriver Name: [%s]\n", r->driver_name);
    1233           0 :         printf("\tArchitecture: [%s]\n", r->architecture);
    1234           0 :         printf("\tDriver Path: [%s]\n", r->driver_path);
    1235           0 :         printf("\tDatafile: [%s]\n", r->data_file);
    1236           0 :         printf("\tConfigfile: [%s]\n", r->config_file);
    1237           0 :         printf("\tHelpfile: [%s]\n", r->help_file);
    1238           0 :         printf("\tMonitorname: [%s]\n", r->monitor_name);
    1239           0 :         printf("\tDefaultdatatype: [%s]\n", r->default_datatype);
    1240             : 
    1241           0 :         for (i=0; r->dependent_files && r->dependent_files[i] != NULL; i++) {
    1242           0 :                 printf("\tDependentfiles: [%s]\n", r->dependent_files[i]);
    1243             :         }
    1244             : 
    1245           0 :         for (i=0; r->previous_names && r->previous_names[i] != NULL; i++) {
    1246           0 :                 printf("\tPrevious Names: [%s]\n", r->previous_names[i]);
    1247             :         }
    1248             : 
    1249           0 :         printf("\tDriver Date: [%s]\n", nt_time_string(talloc_tos(), r->driver_date));
    1250           0 :         printf("\tDriver Version: [0x%016llx]\n", (long long unsigned int)r->driver_version);
    1251           0 :         printf("\tManufacturer Name: [%s]\n", r->manufacturer_name);
    1252           0 :         printf("\tManufacturer Url: [%s]\n", r->manufacturer_url);
    1253           0 :         printf("\tHardware ID: [%s]\n", r->hardware_id);
    1254           0 :         printf("\tProvider: [%s]\n", r->provider);
    1255           0 :         printf("\tPrint Processor: [%s]\n", r->print_processor);
    1256           0 :         printf("\tVendor Setup: [%s]\n", r->vendor_setup);
    1257           0 :         for (i=0; r->color_profiles && r->color_profiles[i] != NULL; i++) {
    1258           0 :                 printf("\tColor Profiles: [%s]\n", r->color_profiles[i]);
    1259             :         }
    1260           0 :         printf("\tInf Path: [%s]\n", r->inf_path);
    1261           0 :         printf("\tPrinter Driver Attributes: [0x%x]\n", r->printer_driver_attributes);
    1262           0 :         for (i=0; r->core_driver_dependencies && r->core_driver_dependencies[i] != NULL; i++) {
    1263           0 :                 printf("\tCore Driver Dependencies: [%s]\n", r->core_driver_dependencies[i]);
    1264             :         }
    1265           0 :         printf("\tMin Driver Inbox Driver Version Date: [%s]\n", nt_time_string(talloc_tos(), r->min_inbox_driver_ver_date));
    1266           0 :         printf("\tMin Driver Inbox Driver Version Version: [0x%016llx]\n",
    1267           0 :                 (long long unsigned int)r->min_inbox_driver_ver_version);
    1268             : 
    1269           0 :         printf("\n");
    1270             : }
    1271             : 
    1272             : /****************************************************************************
    1273             : ****************************************************************************/
    1274             : 
    1275           0 : static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli,
    1276             :                                     TALLOC_CTX *mem_ctx,
    1277             :                                     int argc, const char **argv)
    1278             : {
    1279             :         struct policy_handle pol;
    1280             :         WERROR          werror;
    1281           0 :         uint32_t        level = 3;
    1282             :         const char      *printername;
    1283             :         uint32_t        i;
    1284           0 :         bool            success = false;
    1285             :         union spoolss_DriverInfo info;
    1286             :         uint32_t server_major_version;
    1287             :         uint32_t server_minor_version;
    1288           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    1289             : 
    1290           0 :         if ((argc == 1) || (argc > 3)) {
    1291           0 :                 printf("Usage: %s <printername> [level]\n", argv[0]);
    1292           0 :                 return WERR_OK;
    1293             :         }
    1294             : 
    1295             :         /* get the arguments need to open the printer handle */
    1296             : 
    1297           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    1298             : 
    1299           0 :         if (argc == 3) {
    1300           0 :                 level = atoi(argv[2]);
    1301             :         }
    1302             : 
    1303             :         /* Open a printer handle */
    1304             : 
    1305           0 :         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    1306             :                                                printername,
    1307             :                                                PRINTER_ACCESS_USE,
    1308             :                                                &pol);
    1309           0 :         if (!W_ERROR_IS_OK(werror)) {
    1310           0 :                 printf("Error opening printer handle for %s!\n", printername);
    1311           0 :                 return werror;
    1312             :         }
    1313             : 
    1314             :         /* loop through and print driver info level for each architecture */
    1315             : 
    1316           0 :         for (i=0; archi_table[i].long_archi!=NULL; i++) {
    1317             : 
    1318           0 :                 werror = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
    1319             :                                                           &pol,
    1320           0 :                                                           archi_table[i].long_archi,
    1321             :                                                           level,
    1322             :                                                           0, /* offered */
    1323           0 :                                                           archi_table[i].version,
    1324             :                                                           2,
    1325             :                                                           &info,
    1326             :                                                           &server_major_version,
    1327             :                                                           &server_minor_version);
    1328           0 :                 if (!W_ERROR_IS_OK(werror)) {
    1329           0 :                         continue;
    1330             :                 }
    1331             : 
    1332             :                 /* need at least one success */
    1333             : 
    1334           0 :                 success = true;
    1335             : 
    1336           0 :                 printf("\n[%s]\n", archi_table[i].long_archi);
    1337             : 
    1338           0 :                 switch (level) {
    1339           0 :                 case 1:
    1340           0 :                         display_print_driver1(&info.info1);
    1341           0 :                         break;
    1342           0 :                 case 2:
    1343           0 :                         display_print_driver2(&info.info2);
    1344           0 :                         break;
    1345           0 :                 case 3:
    1346           0 :                         display_print_driver3(&info.info3);
    1347           0 :                         break;
    1348           0 :                 case 4:
    1349           0 :                         display_print_driver4(&info.info4);
    1350           0 :                         break;
    1351           0 :                 case 5:
    1352           0 :                         display_print_driver5(&info.info5);
    1353           0 :                         break;
    1354           0 :                 case 6:
    1355           0 :                         display_print_driver6(&info.info6);
    1356           0 :                         break;
    1357           0 :                 case 8:
    1358           0 :                         display_print_driver8(&info.info8);
    1359           0 :                         break;
    1360           0 :                 default:
    1361           0 :                         printf("unknown info level %d\n", level);
    1362           0 :                         break;
    1363             :                 }
    1364             :         }
    1365             : 
    1366             :         /* Cleanup */
    1367             : 
    1368           0 :         if (is_valid_policy_hnd(&pol)) {
    1369             :                 WERROR _result;
    1370           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
    1371             :         }
    1372             : 
    1373           0 :         if (success) {
    1374           0 :                 werror = WERR_OK;
    1375             :         }
    1376             : 
    1377           0 :         return werror;
    1378             : }
    1379             : 
    1380             : /****************************************************************************
    1381             : ****************************************************************************/
    1382             : 
    1383           0 : static WERROR enum_driver_by_architecture(struct rpc_pipe_client *cli,
    1384             :                                           TALLOC_CTX *mem_ctx,
    1385             :                                           const char *architecture,
    1386             :                                           uint32_t level)
    1387             : {
    1388             :         WERROR werror;
    1389           0 :         uint32_t count = 0;
    1390           0 :         union spoolss_DriverInfo *info = NULL;
    1391             :         uint32_t j;
    1392             : 
    1393           0 :         werror = rpccli_spoolss_enumprinterdrivers(cli, mem_ctx,
    1394           0 :                                                    cli->srv_name_slash,
    1395             :                                                    architecture,
    1396             :                                                    level,
    1397             :                                                    0,
    1398             :                                                    &count,
    1399             :                                                    &info);
    1400             : 
    1401           0 :         if (W_ERROR_EQUAL(werror, WERR_INVALID_ENVIRONMENT)) {
    1402           0 :                 printf("Server does not support environment [%s]\n",
    1403             :                         architecture);
    1404           0 :                 return WERR_OK;
    1405             :         }
    1406             : 
    1407           0 :         if (count == 0) {
    1408           0 :                 return WERR_OK;
    1409             :         }
    1410             : 
    1411           0 :         if (!W_ERROR_IS_OK(werror)) {
    1412           0 :                 printf("Error getting driver for environment [%s] - %s\n",
    1413             :                         architecture, win_errstr(werror));
    1414           0 :                 return werror;
    1415             :         }
    1416             : 
    1417           0 :         printf("\n[%s]\n", architecture);
    1418             : 
    1419           0 :         switch (level) {
    1420           0 :         case 1:
    1421           0 :                 for (j=0; j < count; j++) {
    1422           0 :                         display_print_driver1(&info[j].info1);
    1423             :                 }
    1424           0 :                 break;
    1425           0 :         case 2:
    1426           0 :                 for (j=0; j < count; j++) {
    1427           0 :                         display_print_driver2(&info[j].info2);
    1428             :                 }
    1429           0 :                 break;
    1430           0 :         case 3:
    1431           0 :                 for (j=0; j < count; j++) {
    1432           0 :                         display_print_driver3(&info[j].info3);
    1433             :                 }
    1434           0 :                 break;
    1435           0 :         case 4:
    1436           0 :                 for (j=0; j < count; j++) {
    1437           0 :                         display_print_driver4(&info[j].info4);
    1438             :                 }
    1439           0 :                 break;
    1440           0 :         case 5:
    1441           0 :                 for (j=0; j < count; j++) {
    1442           0 :                         display_print_driver5(&info[j].info5);
    1443             :                 }
    1444           0 :                 break;
    1445           0 :         case 6:
    1446           0 :                 for (j=0; j < count; j++) {
    1447           0 :                         display_print_driver6(&info[j].info6);
    1448             :                 }
    1449           0 :                 break;
    1450           0 :         case 8:
    1451           0 :                 for (j=0; j < count; j++) {
    1452           0 :                         display_print_driver8(&info[j].info8);
    1453             :                 }
    1454           0 :                 break;
    1455           0 :         default:
    1456           0 :                 printf("unknown info level %d\n", level);
    1457           0 :                 return WERR_INVALID_LEVEL;
    1458             :         }
    1459             : 
    1460           0 :         return werror;
    1461             : }
    1462             : 
    1463           0 : static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli,
    1464             :                                          TALLOC_CTX *mem_ctx,
    1465             :                                          int argc, const char **argv)
    1466             : {
    1467           0 :         WERROR werror = WERR_OK;
    1468           0 :         uint32_t        level = 1;
    1469             :         uint32_t        i;
    1470           0 :         const char *architecture = NULL;
    1471             : 
    1472           0 :         if (argc > 3) {
    1473           0 :                 printf("Usage: enumdrivers [level] [architecture]\n");
    1474           0 :                 return WERR_OK;
    1475             :         }
    1476             : 
    1477           0 :         if (argc >= 2) {
    1478           0 :                 level = atoi(argv[1]);
    1479             :         }
    1480             : 
    1481           0 :         if (argc == 3) {
    1482           0 :                 architecture = argv[2];
    1483             :         }
    1484             : 
    1485           0 :         if (architecture) {
    1486           0 :                 return enum_driver_by_architecture(cli, mem_ctx,
    1487             :                                                    architecture,
    1488             :                                                    level);
    1489             :         }
    1490             : 
    1491             :         /* loop through and print driver info level for each architecture */
    1492           0 :         for (i=0; archi_table[i].long_archi!=NULL; i++) {
    1493             :                 /* check to see if we already asked for this architecture string */
    1494             : 
    1495           0 :                 if (i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi)) {
    1496           0 :                         continue;
    1497             :                 }
    1498             : 
    1499           0 :                 werror = enum_driver_by_architecture(cli, mem_ctx,
    1500           0 :                                                      archi_table[i].long_archi,
    1501             :                                                      level);
    1502           0 :                 if (!W_ERROR_IS_OK(werror)) {
    1503           0 :                         break;
    1504             :                 }
    1505             :         }
    1506             : 
    1507           0 :         return werror;
    1508             : }
    1509             : 
    1510             : /****************************************************************************
    1511             : ****************************************************************************/
    1512             : 
    1513           0 : static void display_printdriverdir_1(struct spoolss_DriverDirectoryInfo1 *r)
    1514             : {
    1515           0 :         printf("\tDirectory Name:[%s]\n", r->directory_name);
    1516           0 : }
    1517             : 
    1518             : /****************************************************************************
    1519             : ****************************************************************************/
    1520             : 
    1521           0 : static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli,
    1522             :                                          TALLOC_CTX *mem_ctx,
    1523             :                                          int argc, const char **argv)
    1524             : {
    1525             :         WERROR result;
    1526             :         NTSTATUS status;
    1527           0 :         const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
    1528             :         DATA_BLOB buffer;
    1529             :         uint32_t offered;
    1530             :         union spoolss_DriverDirectoryInfo info;
    1531             :         uint32_t needed;
    1532           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    1533             : 
    1534           0 :         if (argc > 2) {
    1535           0 :                 printf("Usage: %s [environment]\n", argv[0]);
    1536           0 :                 return WERR_OK;
    1537             :         }
    1538             : 
    1539             :         /* Get the arguments need to open the printer handle */
    1540             : 
    1541           0 :         if (argc == 2) {
    1542           0 :                 env = argv[1];
    1543             :         }
    1544             : 
    1545             :         /* Get the directory.  Only use Info level 1 */
    1546             : 
    1547           0 :         status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
    1548           0 :                                                           cli->srv_name_slash,
    1549             :                                                           env,
    1550             :                                                           1,
    1551             :                                                           NULL, /* buffer */
    1552             :                                                           0, /* offered */
    1553             :                                                           NULL, /* info */
    1554             :                                                           &needed,
    1555             :                                                           &result);
    1556           0 :         if (!NT_STATUS_IS_OK(status)) {
    1557           0 :                 return ntstatus_to_werror(status);
    1558             :         }
    1559           0 :         if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
    1560           0 :                 offered = needed;
    1561           0 :                 buffer = data_blob_talloc_zero(mem_ctx, needed);
    1562             : 
    1563           0 :                 status = dcerpc_spoolss_GetPrinterDriverDirectory(b, mem_ctx,
    1564           0 :                                                                   cli->srv_name_slash,
    1565             :                                                                   env,
    1566             :                                                                   1,
    1567             :                                                                   &buffer,
    1568             :                                                                   offered,
    1569             :                                                                   &info,
    1570             :                                                                   &needed,
    1571             :                                                                   &result);
    1572           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1573           0 :                         return ntstatus_to_werror(status);
    1574             :                 }
    1575             :         }
    1576             : 
    1577           0 :         if (W_ERROR_IS_OK(result)) {
    1578           0 :                 display_printdriverdir_1(&info.info1);
    1579             :         }
    1580             : 
    1581           0 :         return result;
    1582             : }
    1583             : 
    1584             : /****************************************************************************
    1585             : ****************************************************************************/
    1586             : 
    1587           0 : static WERROR cmd_spoolss_getdriverpackagepath(struct rpc_pipe_client *cli,
    1588             :                                                TALLOC_CTX *mem_ctx,
    1589             :                                                int argc, const char **argv)
    1590             : {
    1591             :         HRESULT hresult;
    1592             :         NTSTATUS status;
    1593           0 :         const char *env = SPOOLSS_ARCHITECTURE_NT_X86;
    1594             :         uint32_t offered;
    1595             :         uint32_t needed;
    1596           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    1597           0 :         const char *package_id = "";
    1598           0 :         const char *cab = NULL;
    1599             : 
    1600           0 :         if (argc > 4) {
    1601           0 :                 printf("Usage: %s [environment] [package_id]\n", argv[0]);
    1602           0 :                 return WERR_OK;
    1603             :         }
    1604             : 
    1605             :         /* Get the arguments need to open the printer handle */
    1606             : 
    1607           0 :         if (argc >= 2) {
    1608           0 :                 env = argv[1];
    1609             :         }
    1610             : 
    1611           0 :         if (argc == 3) {
    1612           0 :                 package_id = argv[2];
    1613             :         }
    1614             : 
    1615           0 :         offered = 1;
    1616           0 :         cab = talloc_zero_array(mem_ctx, char, offered);
    1617           0 :         if (cab == NULL) {
    1618           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    1619             :         }
    1620           0 :         status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
    1621           0 :                                                             cli->srv_name_slash,
    1622             :                                                             env,
    1623             :                                                             NULL,
    1624             :                                                             package_id,
    1625             :                                                             cab,
    1626             :                                                             offered,
    1627             :                                                             &needed,
    1628             :                                                             &hresult);
    1629           0 :         if (!NT_STATUS_IS_OK(status)) {
    1630           0 :                 return ntstatus_to_werror(status);
    1631             :         }
    1632             : 
    1633           0 :         if (W_ERROR_EQUAL(W_ERROR(WIN32_FROM_HRESULT(hresult)), WERR_INSUFFICIENT_BUFFER)) {
    1634           0 :                 offered = needed;
    1635           0 :                 cab = talloc_zero_array(mem_ctx, char, offered);
    1636           0 :                 if (cab == NULL) {
    1637           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    1638             :                 }
    1639           0 :                 status = dcerpc_spoolss_GetPrinterDriverPackagePath(b, mem_ctx,
    1640           0 :                                                                     cli->srv_name_slash,
    1641             :                                                                     env,
    1642             :                                                                     NULL,
    1643             :                                                                     package_id,
    1644             :                                                                     cab,
    1645             :                                                                     offered,
    1646             :                                                                     &needed,
    1647             :                                                                     &hresult);
    1648           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1649           0 :                         return ntstatus_to_werror(status);
    1650             :                 }
    1651             :         }
    1652             : 
    1653           0 :         return W_ERROR(WIN32_FROM_HRESULT(hresult));
    1654             : }
    1655             : 
    1656             : 
    1657             : /****************************************************************************
    1658             : ****************************************************************************/
    1659             : 
    1660           0 : static void set_drv_info_3_env(TALLOC_CTX *mem_ctx,
    1661             :                                struct spoolss_AddDriverInfo3 *info,
    1662             :                                const char *arch)
    1663             : {
    1664             : 
    1665             :         int i;
    1666             : 
    1667           0 :         for (i=0; archi_table[i].long_archi != NULL; i++)
    1668             :         {
    1669           0 :                 if (strcmp(arch, archi_table[i].short_archi) == 0)
    1670             :                 {
    1671           0 :                         info->version = archi_table[i].version;
    1672           0 :                         info->architecture = talloc_strdup(mem_ctx, archi_table[i].long_archi);
    1673           0 :                         break;
    1674             :                 }
    1675             :         }
    1676             : 
    1677           0 :         if (archi_table[i].long_archi == NULL)
    1678             :         {
    1679           0 :                 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
    1680             :         }
    1681             : 
    1682           0 :         return;
    1683             : }
    1684             : 
    1685             : 
    1686             : /**************************************************************************
    1687             :  wrapper for strtok to get the next parameter from a delimited list.
    1688             :  Needed to handle the empty parameter string denoted by "NULL"
    1689             :  *************************************************************************/
    1690             : 
    1691           0 : static char *get_driver_3_param(TALLOC_CTX *mem_ctx, char *str,
    1692             :                                 const char *delim, const char **dest,
    1693             :                                 char **saveptr)
    1694             : {
    1695             :         char    *ptr;
    1696             : 
    1697             :         /* get the next token */
    1698           0 :         ptr = strtok_r(str, delim, saveptr);
    1699             : 
    1700             :         /* a string of 'NULL' is used to represent an empty
    1701             :            parameter because two consecutive delimiters
    1702             :            will not return an empty string.  See man strtok(3)
    1703             :            for details */
    1704           0 :         if (ptr && (strcasecmp_m(ptr, "NULL") == 0)) {
    1705           0 :                 ptr = NULL;
    1706             :         }
    1707             : 
    1708           0 :         if (dest != NULL) {
    1709           0 :                 *dest = talloc_strdup(mem_ctx, ptr);
    1710             :         }
    1711             : 
    1712           0 :         return ptr;
    1713             : }
    1714             : 
    1715             : /********************************************************************************
    1716             :  fill in the members of a spoolss_AddDriverInfo3 struct using a character
    1717             :  string in the form of
    1718             :          <Long Driver Name>:<Driver File Name>:<Data File Name>:\
    1719             :              <Config File Name>:<Help File Name>:<Language Monitor Name>:\
    1720             :              <Default Data Type>:<Comma Separated list of Files>
    1721             :  *******************************************************************************/
    1722             : 
    1723           0 : static bool init_drv_info_3_members(TALLOC_CTX *mem_ctx, struct spoolss_AddDriverInfo3 *r,
    1724             :                                     char *args)
    1725             : {
    1726             :         char    *str, *str2;
    1727           0 :         size_t count = 0;
    1728           0 :         char *saveptr = NULL;
    1729             :         struct spoolss_StringArray *deps;
    1730           0 :         const char **file_array = NULL;
    1731             :         int i;
    1732             : 
    1733             :         /* fill in the UNISTR fields */
    1734           0 :         str = get_driver_3_param(mem_ctx, args, ":", &r->driver_name, &saveptr);
    1735           0 :         str = get_driver_3_param(mem_ctx, NULL, ":", &r->driver_path, &saveptr);
    1736           0 :         str = get_driver_3_param(mem_ctx, NULL, ":", &r->data_file, &saveptr);
    1737           0 :         str = get_driver_3_param(mem_ctx, NULL, ":", &r->config_file, &saveptr);
    1738           0 :         str = get_driver_3_param(mem_ctx, NULL, ":", &r->help_file, &saveptr);
    1739           0 :         str = get_driver_3_param(mem_ctx, NULL, ":", &r->monitor_name, &saveptr);
    1740           0 :         str = get_driver_3_param(mem_ctx, NULL, ":", &r->default_datatype, &saveptr);
    1741             : 
    1742             :         /* <Comma Separated List of Dependent Files> */
    1743             :         /* save the beginning of the string */
    1744           0 :         str2 = get_driver_3_param(mem_ctx, NULL, ":", NULL, &saveptr);
    1745           0 :         str = str2;
    1746             : 
    1747             :         /* begin to strip out each filename */
    1748           0 :         str = strtok_r(str, ",", &saveptr);
    1749             : 
    1750             :         /* no dependent files, we are done */
    1751           0 :         if (!str) {
    1752           0 :                 return true;
    1753             :         }
    1754             : 
    1755           0 :         deps = talloc_zero(mem_ctx, struct spoolss_StringArray);
    1756           0 :         if (!deps) {
    1757           0 :                 return false;
    1758             :         }
    1759             : 
    1760           0 :         while (str != NULL) {
    1761             :                 bool ok;
    1762           0 :                 ok = add_string_to_array(deps, str, &file_array, &count);
    1763           0 :                 if (!ok) {
    1764           0 :                         return false;
    1765             :                 }
    1766           0 :                 str = strtok_r(NULL, ",", &saveptr);
    1767             :         }
    1768             : 
    1769           0 :         deps->string = talloc_zero_array(deps, const char *, count + 1);
    1770           0 :         if (!deps->string) {
    1771           0 :                 return false;
    1772             :         }
    1773             : 
    1774           0 :         for (i=0; i < count; i++) {
    1775           0 :                 deps->string[i] = file_array[i];
    1776             :         }
    1777             : 
    1778           0 :         r->dependent_files = deps;
    1779             : 
    1780           0 :         return true;
    1781             : }
    1782             : 
    1783             : /****************************************************************************
    1784             : ****************************************************************************/
    1785             : 
    1786           0 : static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli,
    1787             :                                              TALLOC_CTX *mem_ctx,
    1788             :                                              int argc, const char **argv)
    1789             : {
    1790             :         WERROR result;
    1791             :         NTSTATUS status;
    1792           0 :         uint32_t                  level = 3;
    1793             :         struct spoolss_AddDriverInfoCtr info_ctr;
    1794             :         struct spoolss_AddDriverInfo3 info3;
    1795             :         const char              *arch;
    1796             :         char                    *driver_args;
    1797           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    1798             : 
    1799             :         /* parse the command arguments */
    1800           0 :         if (argc != 3 && argc != 4)
    1801             :         {
    1802           0 :                 printf ("Usage: %s <Environment> \\\n", argv[0]);
    1803           0 :                 printf ("\t<Long Driver Name>:<Driver File Name>:<Data File Name>:\\\n");
    1804           0 :                 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
    1805           0 :                 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
    1806           0 :                 printf ("\t[version]\n");
    1807             : 
    1808           0 :             return WERR_OK;
    1809             :         }
    1810             : 
    1811             :         /* Fill in the spoolss_AddDriverInfo3 struct */
    1812           0 :         ZERO_STRUCT(info3);
    1813             : 
    1814           0 :         arch = cmd_spoolss_get_short_archi(argv[1]);
    1815           0 :         if (!arch) {
    1816           0 :                 printf ("Error Unknown architecture [%s]\n", argv[1]);
    1817           0 :                 return WERR_INVALID_PARAMETER;
    1818             :         }
    1819             : 
    1820           0 :         set_drv_info_3_env(mem_ctx, &info3, arch);
    1821             : 
    1822           0 :         driver_args = talloc_strdup( mem_ctx, argv[2] );
    1823           0 :         if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
    1824             :         {
    1825           0 :                 printf ("Error Invalid parameter list - %s.\n", argv[2]);
    1826           0 :                 return WERR_INVALID_PARAMETER;
    1827             :         }
    1828             : 
    1829             :         /* if printer driver version specified, override the default version
    1830             :          * used by the architecture.  This allows installation of Windows
    1831             :          * 2000 (version 3) printer drivers. */
    1832           0 :         if (argc == 4)
    1833             :         {
    1834           0 :                 info3.version = atoi(argv[3]);
    1835             :         }
    1836             : 
    1837             : 
    1838           0 :         info_ctr.level          = level;
    1839           0 :         info_ctr.info.info3     = &info3;
    1840             : 
    1841           0 :         status = dcerpc_spoolss_AddPrinterDriver(b, mem_ctx,
    1842           0 :                                                  cli->srv_name_slash,
    1843             :                                                  &info_ctr,
    1844             :                                                  &result);
    1845           0 :         if (!NT_STATUS_IS_OK(status)) {
    1846           0 :                 return ntstatus_to_werror(status);
    1847             :         }
    1848           0 :         if (W_ERROR_IS_OK(result)) {
    1849           0 :                 printf ("Printer Driver %s successfully installed.\n",
    1850             :                         info3.driver_name);
    1851             :         }
    1852             : 
    1853           0 :         return result;
    1854             : }
    1855             : 
    1856             : 
    1857             : /****************************************************************************
    1858             : ****************************************************************************/
    1859             : 
    1860           0 : static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli,
    1861             :                                          TALLOC_CTX *mem_ctx,
    1862             :                                          int argc, const char **argv)
    1863             : {
    1864             :         WERROR result;
    1865             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    1866             :         struct spoolss_SetPrinterInfo2 info2;
    1867             : 
    1868             :         /* parse the command arguments */
    1869           0 :         if (argc != 5)
    1870             :         {
    1871           0 :                 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
    1872           0 :                 return WERR_OK;
    1873             :         }
    1874             : 
    1875             :         /* Fill in the DRIVER_INFO_2 struct */
    1876           0 :         ZERO_STRUCT(info2);
    1877             : 
    1878           0 :         info2.printername       = argv[1];
    1879           0 :         info2.drivername        = argv[3];
    1880           0 :         info2.sharename         = argv[2];
    1881           0 :         info2.portname          = argv[4];
    1882           0 :         info2.comment           = "Created by rpcclient";
    1883           0 :         info2.printprocessor    = "winprint";
    1884           0 :         info2.datatype          = "RAW";
    1885           0 :         info2.devmode_ptr       = 0;
    1886           0 :         info2.secdesc_ptr       = 0;
    1887           0 :         info2.attributes        = PRINTER_ATTRIBUTE_SHARED;
    1888           0 :         info2.priority          = 0;
    1889           0 :         info2.defaultpriority   = 0;
    1890           0 :         info2.starttime         = 0;
    1891           0 :         info2.untiltime         = 0;
    1892             : 
    1893             :         /* These three fields must not be used by AddPrinter()
    1894             :            as defined in the MS Platform SDK documentation..
    1895             :            --jerry
    1896             :         info2.status            = 0;
    1897             :         info2.cjobs             = 0;
    1898             :         info2.averageppm        = 0;
    1899             :         */
    1900             : 
    1901           0 :         info_ctr.level = 2;
    1902           0 :         info_ctr.info.info2 = &info2;
    1903             : 
    1904           0 :         result = rpccli_spoolss_addprinterex(cli, mem_ctx,
    1905             :                                              &info_ctr);
    1906           0 :         if (W_ERROR_IS_OK(result))
    1907           0 :                 printf ("Printer %s successfully installed.\n", argv[1]);
    1908             : 
    1909           0 :         return result;
    1910             : }
    1911             : 
    1912             : /****************************************************************************
    1913             : ****************************************************************************/
    1914             : 
    1915           0 : static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli,
    1916             :                                       TALLOC_CTX *mem_ctx,
    1917             :                                       int argc, const char **argv)
    1918             : {
    1919             :         struct policy_handle    pol;
    1920             :         WERROR                  result;
    1921             :         NTSTATUS                status;
    1922           0 :         uint32_t                level = 2;
    1923             :         const char              *printername;
    1924             :         union spoolss_PrinterInfo info;
    1925             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    1926             :         struct spoolss_SetPrinterInfo2 info2;
    1927             :         struct spoolss_DevmodeContainer devmode_ctr;
    1928             :         struct sec_desc_buf secdesc_ctr;
    1929           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    1930             : 
    1931           0 :         ZERO_STRUCT(devmode_ctr);
    1932           0 :         ZERO_STRUCT(secdesc_ctr);
    1933             : 
    1934             :         /* parse the command arguments */
    1935           0 :         if (argc != 3)
    1936             :         {
    1937           0 :                 printf ("Usage: %s <printer> <driver>\n", argv[0]);
    1938           0 :                 return WERR_OK;
    1939             :         }
    1940             : 
    1941           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    1942             : 
    1943             :         /* Get a printer handle */
    1944             : 
    1945           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    1946             :                                                printername,
    1947             :                                                PRINTER_ALL_ACCESS,
    1948             :                                                &pol);
    1949           0 :         if (!W_ERROR_IS_OK(result))
    1950           0 :                 goto done;
    1951             : 
    1952             :         /* Get printer info */
    1953             : 
    1954           0 :         result = rpccli_spoolss_getprinter(cli, mem_ctx,
    1955             :                                            &pol,
    1956             :                                            level,
    1957             :                                            0,
    1958             :                                            &info);
    1959           0 :         if (!W_ERROR_IS_OK(result)) {
    1960           0 :                 printf ("Unable to retrieve printer information!\n");
    1961           0 :                 goto done;
    1962             :         }
    1963             : 
    1964             :         /* Set the printer driver */
    1965             : 
    1966           0 :         spoolss_printerinfo2_to_setprinterinfo2(&info.info2, &info2);
    1967           0 :         info2.drivername = argv[2];
    1968             : 
    1969           0 :         info_ctr.level = 2;
    1970           0 :         info_ctr.info.info2 = &info2;
    1971             : 
    1972           0 :         status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
    1973             :                                            &pol,
    1974             :                                            &info_ctr,
    1975             :                                            &devmode_ctr,
    1976             :                                            &secdesc_ctr,
    1977             :                                            0, /* command */
    1978             :                                            &result);
    1979           0 :         if (!NT_STATUS_IS_OK(status)) {
    1980           0 :                 result = ntstatus_to_werror(status);
    1981           0 :                 goto done;
    1982             :         }
    1983           0 :         if (!W_ERROR_IS_OK(result)) {
    1984           0 :                 printf("SetPrinter call failed!\n");
    1985           0 :                 goto done;
    1986             :         }
    1987             : 
    1988           0 :         printf("Successfully set %s to driver %s.\n", argv[1], argv[2]);
    1989             : 
    1990           0 : done:
    1991             :         /* Cleanup */
    1992             : 
    1993           0 :         if (is_valid_policy_hnd(&pol)) {
    1994             :                 WERROR _result;
    1995           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
    1996             :         }
    1997             : 
    1998           0 :         return result;
    1999             : }
    2000             : 
    2001             : 
    2002             : /****************************************************************************
    2003             : ****************************************************************************/
    2004             : 
    2005           0 : static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli,
    2006             :                                          TALLOC_CTX *mem_ctx,
    2007             :                                          int argc, const char **argv)
    2008             : {
    2009           0 :         WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
    2010             :         NTSTATUS status;
    2011           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    2012             : 
    2013             :         int   i;
    2014           0 :         int vers = -1;
    2015             : 
    2016           0 :         const char *arch = NULL;
    2017           0 :         uint32_t delete_flags = 0;
    2018             : 
    2019             :         /* parse the command arguments */
    2020           0 :         if (argc < 2 || argc > 5) {
    2021           0 :                 printf("Usage: %s <driver> [arch] [version] [flags]\n", argv[0]);
    2022           0 :                 return WERR_OK;
    2023             :         }
    2024             : 
    2025           0 :         if (argc >= 3)
    2026           0 :                 arch = argv[2];
    2027           0 :         if (argc >= 4) {
    2028           0 :                 vers = atoi(argv[3]);
    2029           0 :                 delete_flags |= DPD_DELETE_SPECIFIC_VERSION;
    2030             :         }
    2031           0 :         if (argc == 5)
    2032           0 :                 delete_flags = atoi(argv[4]);
    2033             : 
    2034             :         /* delete the driver for all architectures */
    2035           0 :         for (i=0; archi_table[i].long_archi; i++) {
    2036             : 
    2037           0 :                 if (arch && !strequal(archi_table[i].long_archi, arch))
    2038           0 :                         continue;
    2039             : 
    2040           0 :                 if (vers >= 0 && archi_table[i].version != vers)
    2041           0 :                         continue;
    2042             : 
    2043             :                 /* make the call to remove the driver */
    2044           0 :                 status = dcerpc_spoolss_DeletePrinterDriverEx(b, mem_ctx,
    2045           0 :                                                               cli->srv_name_slash,
    2046           0 :                                                               archi_table[i].long_archi,
    2047           0 :                                                               argv[1],
    2048             :                                                               delete_flags,
    2049           0 :                                                               archi_table[i].version,
    2050             :                                                               &result);
    2051           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2052           0 :                         return ntstatus_to_werror(status);
    2053             :                 }
    2054           0 :                 if ( !W_ERROR_IS_OK(result) )
    2055             :                 {
    2056           0 :                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
    2057           0 :                                 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n",
    2058           0 :                                         argv[1], archi_table[i].long_archi, archi_table[i].version, win_errstr(result));
    2059             :                         }
    2060             :                 }
    2061             :                 else
    2062             :                 {
    2063           0 :                         printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1],
    2064           0 :                         archi_table[i].long_archi, archi_table[i].version);
    2065           0 :                         ret = WERR_OK;
    2066             :                 }
    2067             :         }
    2068             : 
    2069           0 :         return ret;
    2070             : }
    2071             : 
    2072             : 
    2073             : /****************************************************************************
    2074             : ****************************************************************************/
    2075             : 
    2076           0 : static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli,
    2077             :                                          TALLOC_CTX *mem_ctx,
    2078             :                                          int argc, const char **argv)
    2079             : {
    2080           0 :         WERROR result = WERR_OK;
    2081             :         NTSTATUS status;
    2082             :         int                     i;
    2083           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    2084             : 
    2085             :         /* parse the command arguments */
    2086           0 :         if (argc != 2) {
    2087           0 :                 printf ("Usage: %s <driver>\n", argv[0]);
    2088           0 :                 return WERR_OK;
    2089             :         }
    2090             : 
    2091             :         /* delete the driver for all architectures */
    2092           0 :         for (i=0; archi_table[i].long_archi; i++) {
    2093           0 :                 result = WERR_OK;
    2094             : 
    2095             :                 /* make the call to remove the driver */
    2096           0 :                 status = dcerpc_spoolss_DeletePrinterDriver(b, mem_ctx,
    2097           0 :                                                             cli->srv_name_slash,
    2098           0 :                                                             archi_table[i].long_archi,
    2099           0 :                                                             argv[1],
    2100             :                                                             &result);
    2101           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2102           0 :                         result = ntstatus_to_werror(status);
    2103           0 :                         continue;
    2104             :                 }
    2105           0 :                 if ( !W_ERROR_IS_OK(result) ) {
    2106           0 :                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
    2107           0 :                                 printf ("Failed to remove driver %s for arch [%s] - error %s!\n",
    2108           0 :                                         argv[1], archi_table[i].long_archi,
    2109             :                                         win_errstr(result));
    2110             :                         }
    2111             :                 } else {
    2112           0 :                         printf ("Driver %s removed for arch [%s].\n", argv[1],
    2113           0 :                                 archi_table[i].long_archi);
    2114             :                 }
    2115             :         }
    2116             : 
    2117           0 :         return result;
    2118             : }
    2119             : 
    2120             : /****************************************************************************
    2121             : ****************************************************************************/
    2122             : 
    2123           0 : static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli,
    2124             :                                             TALLOC_CTX *mem_ctx,
    2125             :                                             int argc, const char **argv)
    2126             : {
    2127             :         WERROR result;
    2128             :         NTSTATUS status;
    2129           0 :         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
    2130             :         DATA_BLOB buffer;
    2131             :         uint32_t offered;
    2132           0 :         union spoolss_PrintProcessorDirectoryInfo info = {};
    2133             :         uint32_t needed;
    2134           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    2135             : 
    2136             :         /* parse the command arguments */
    2137           0 :         if (argc > 2) {
    2138           0 :                 printf ("Usage: %s [environment]\n", argv[0]);
    2139           0 :                 return WERR_OK;
    2140             :         }
    2141             : 
    2142           0 :         if (argc == 2) {
    2143           0 :                 environment = argv[1];
    2144             :         }
    2145             : 
    2146           0 :         status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
    2147           0 :                                                            cli->srv_name_slash,
    2148             :                                                            environment,
    2149             :                                                            1,
    2150             :                                                            NULL, /* buffer */
    2151             :                                                            0, /* offered */
    2152             :                                                            NULL, /* info */
    2153             :                                                            &needed,
    2154             :                                                            &result);
    2155           0 :         if (!NT_STATUS_IS_OK(status)) {
    2156           0 :                 return ntstatus_to_werror(status);
    2157             :         }
    2158           0 :         if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
    2159           0 :                 offered = needed;
    2160           0 :                 buffer = data_blob_talloc_zero(mem_ctx, needed);
    2161             : 
    2162           0 :                 status = dcerpc_spoolss_GetPrintProcessorDirectory(b, mem_ctx,
    2163           0 :                                                                    cli->srv_name_slash,
    2164             :                                                                    environment,
    2165             :                                                                    1,
    2166             :                                                                    &buffer,
    2167             :                                                                    offered,
    2168             :                                                                    &info,
    2169             :                                                                    &needed,
    2170             :                                                                    &result);
    2171           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2172           0 :                         return ntstatus_to_werror(status);
    2173             :                 }
    2174             :         }
    2175             : 
    2176           0 :         if (W_ERROR_IS_OK(result) && info.info1.directory_name != NULL) {
    2177           0 :                 printf("%s\n", info.info1.directory_name);
    2178             :         }
    2179             : 
    2180           0 :         return result;
    2181             : }
    2182             : 
    2183             : /****************************************************************************
    2184             : ****************************************************************************/
    2185             : 
    2186           0 : static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
    2187             :                                     int argc, const char **argv)
    2188             : {
    2189             :         struct policy_handle handle;
    2190             :         WERROR werror;
    2191             :         NTSTATUS status;
    2192             :         const char *printername;
    2193             :         struct spoolss_AddFormInfoCtr info_ctr;
    2194             :         struct spoolss_AddFormInfo1 info1;
    2195             :         struct spoolss_AddFormInfo2 info2;
    2196           0 :         uint32_t level = 1;
    2197           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    2198             : 
    2199             :         /* Parse the command arguments */
    2200             : 
    2201           0 :         if (argc < 3 || argc > 5) {
    2202           0 :                 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
    2203           0 :                 return WERR_OK;
    2204             :         }
    2205             : 
    2206             :         /* Get a printer handle */
    2207             : 
    2208           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    2209             : 
    2210           0 :         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    2211             :                                                printername,
    2212             :                                                PRINTER_ALL_ACCESS,
    2213             :                                                &handle);
    2214           0 :         if (!W_ERROR_IS_OK(werror))
    2215           0 :                 goto done;
    2216             : 
    2217             :         /* Dummy up some values for the form data */
    2218             : 
    2219           0 :         if (argc == 4) {
    2220           0 :                 level = atoi(argv[3]);
    2221             :         }
    2222             : 
    2223           0 :         switch (level) {
    2224           0 :         case 1:
    2225           0 :                 info1.flags             = SPOOLSS_FORM_USER;
    2226           0 :                 info1.form_name         = argv[2];
    2227           0 :                 info1.size.width        = 100;
    2228           0 :                 info1.size.height       = 100;
    2229           0 :                 info1.area.left         = 0;
    2230           0 :                 info1.area.top          = 10;
    2231           0 :                 info1.area.right        = 20;
    2232           0 :                 info1.area.bottom       = 30;
    2233             : 
    2234           0 :                 info_ctr.level          = 1;
    2235           0 :                 info_ctr.info.info1     = &info1;
    2236             : 
    2237           0 :                 break;
    2238           0 :         case 2:
    2239           0 :                 info2.flags             = SPOOLSS_FORM_USER;
    2240           0 :                 info2.form_name         = argv[2];
    2241           0 :                 info2.size.width        = 100;
    2242           0 :                 info2.size.height       = 100;
    2243           0 :                 info2.area.left         = 0;
    2244           0 :                 info2.area.top          = 10;
    2245           0 :                 info2.area.right        = 20;
    2246           0 :                 info2.area.bottom       = 30;
    2247           0 :                 info2.keyword           = argv[2];
    2248           0 :                 info2.string_type       = SPOOLSS_FORM_STRING_TYPE_NONE;
    2249           0 :                 info2.mui_dll           = NULL;
    2250           0 :                 info2.ressource_id      = 0;
    2251           0 :                 info2.display_name      = argv[2];
    2252           0 :                 info2.lang_id           = 0;
    2253             : 
    2254           0 :                 info_ctr.level          = 2;
    2255           0 :                 info_ctr.info.info2     = &info2;
    2256             : 
    2257           0 :                 break;
    2258           0 :         default:
    2259           0 :                 werror = WERR_INVALID_PARAMETER;
    2260           0 :                 goto done;
    2261             :         }
    2262             : 
    2263             :         /* Add the form */
    2264             : 
    2265           0 :         status = dcerpc_spoolss_AddForm(b, mem_ctx,
    2266             :                                         &handle,
    2267             :                                         &info_ctr,
    2268             :                                         &werror);
    2269           0 :         if (!NT_STATUS_IS_OK(status)) {
    2270           0 :                 werror = ntstatus_to_werror(status);
    2271           0 :                 goto done;
    2272             :         }
    2273           0 :  done:
    2274           0 :         if (is_valid_policy_hnd(&handle)) {
    2275             :                 WERROR _result;
    2276           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
    2277             :         }
    2278             : 
    2279           0 :         return werror;
    2280             : }
    2281             : 
    2282             : /****************************************************************************
    2283             : ****************************************************************************/
    2284             : 
    2285           0 : static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
    2286             :                                     int argc, const char **argv)
    2287             : {
    2288             :         struct policy_handle handle;
    2289             :         WERROR werror;
    2290             :         NTSTATUS status;
    2291             :         const char *printername;
    2292             :         struct spoolss_AddFormInfoCtr info_ctr;
    2293             :         struct spoolss_AddFormInfo1 info1;
    2294           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    2295             : 
    2296             :         /* Parse the command arguments */
    2297             : 
    2298           0 :         if (argc != 3) {
    2299           0 :                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
    2300           0 :                 return WERR_OK;
    2301             :         }
    2302             : 
    2303             :         /* Get a printer handle */
    2304             : 
    2305           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    2306             : 
    2307           0 :         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    2308             :                                                printername,
    2309             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    2310             :                                                &handle);
    2311           0 :         if (!W_ERROR_IS_OK(werror))
    2312           0 :                 goto done;
    2313             : 
    2314             :         /* Dummy up some values for the form data */
    2315             : 
    2316           0 :         info1.flags             = SPOOLSS_FORM_PRINTER;
    2317           0 :         info1.size.width        = 100;
    2318           0 :         info1.size.height       = 100;
    2319           0 :         info1.area.left         = 0;
    2320           0 :         info1.area.top          = 1000;
    2321           0 :         info1.area.right        = 2000;
    2322           0 :         info1.area.bottom       = 3000;
    2323           0 :         info1.form_name         = argv[2];
    2324             : 
    2325           0 :         info_ctr.info.info1 = &info1;
    2326           0 :         info_ctr.level = 1;
    2327             : 
    2328             :         /* Set the form */
    2329             : 
    2330           0 :         status = dcerpc_spoolss_SetForm(b, mem_ctx,
    2331             :                                         &handle,
    2332           0 :                                         argv[2],
    2333             :                                         &info_ctr,
    2334             :                                         &werror);
    2335           0 :         if (!NT_STATUS_IS_OK(status)) {
    2336           0 :                 werror = ntstatus_to_werror(status);
    2337           0 :                 goto done;
    2338             :         }
    2339           0 :  done:
    2340           0 :         if (is_valid_policy_hnd(&handle)) {
    2341             :                 WERROR _result;
    2342           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
    2343             :         }
    2344             : 
    2345           0 :         return werror;
    2346             : }
    2347             : 
    2348             : /****************************************************************************
    2349             : ****************************************************************************/
    2350             : 
    2351           0 : static const char *get_form_flag(int form_flag)
    2352             : {
    2353           0 :         switch (form_flag) {
    2354           0 :         case SPOOLSS_FORM_USER:
    2355           0 :                 return "FORM_USER";
    2356           0 :         case SPOOLSS_FORM_BUILTIN:
    2357           0 :                 return "FORM_BUILTIN";
    2358           0 :         case SPOOLSS_FORM_PRINTER:
    2359           0 :                 return "FORM_PRINTER";
    2360           0 :         default:
    2361           0 :                 return "unknown";
    2362             :         }
    2363             : }
    2364             : 
    2365             : /****************************************************************************
    2366             : ****************************************************************************/
    2367             : 
    2368           0 : static void display_form_info1(struct spoolss_FormInfo1 *r)
    2369             : {
    2370           0 :         printf("%s\n" \
    2371             :                 "\tflag: %s (%d)\n" \
    2372             :                 "\twidth: %d, length: %d\n" \
    2373             :                 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n",
    2374           0 :                 r->form_name, get_form_flag(r->flags), r->flags,
    2375             :                 r->size.width, r->size.height,
    2376             :                 r->area.left, r->area.right,
    2377             :                 r->area.top, r->area.bottom);
    2378           0 : }
    2379             : 
    2380             : /****************************************************************************
    2381             : ****************************************************************************/
    2382             : 
    2383           0 : static void display_form_info2(struct spoolss_FormInfo2 *r)
    2384             : {
    2385           0 :         printf("%s\n" \
    2386             :                 "\tflag: %s (%d)\n" \
    2387             :                 "\twidth: %d, length: %d\n" \
    2388             :                 "\tleft: %d, right: %d, top: %d, bottom: %d\n",
    2389           0 :                 r->form_name, get_form_flag(r->flags), r->flags,
    2390             :                 r->size.width, r->size.height,
    2391             :                 r->area.left, r->area.right,
    2392             :                 r->area.top, r->area.bottom);
    2393           0 :         printf("\tkeyword: %s\n", r->keyword);
    2394           0 :         printf("\tstring_type: 0x%08x\n", r->string_type);
    2395           0 :         printf("\tmui_dll: %s\n", r->mui_dll);
    2396           0 :         printf("\tressource_id: 0x%08x\n", r->ressource_id);
    2397           0 :         printf("\tdisplay_name: %s\n", r->display_name);
    2398           0 :         printf("\tlang_id: %d\n", r->lang_id);
    2399           0 :         printf("\n");
    2400           0 : }
    2401             : 
    2402             : /****************************************************************************
    2403             : ****************************************************************************/
    2404             : 
    2405           0 : static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
    2406             :                                     int argc, const char **argv)
    2407             : {
    2408             :         struct policy_handle handle;
    2409             :         WERROR werror;
    2410             :         NTSTATUS status;
    2411             :         const char *printername;
    2412             :         DATA_BLOB buffer;
    2413           0 :         uint32_t offered = 0;
    2414             :         union spoolss_FormInfo info;
    2415             :         uint32_t needed;
    2416           0 :         uint32_t level = 1;
    2417           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    2418             : 
    2419             :         /* Parse the command arguments */
    2420             : 
    2421           0 :         if (argc < 3 || argc > 5) {
    2422           0 :                 printf ("Usage: %s <printer> <formname> [level]\n", argv[0]);
    2423           0 :                 return WERR_OK;
    2424             :         }
    2425             : 
    2426             :         /* Get a printer handle */
    2427             : 
    2428           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    2429             : 
    2430           0 :         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    2431             :                                                printername,
    2432             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    2433             :                                                &handle);
    2434           0 :         if (!W_ERROR_IS_OK(werror))
    2435           0 :                 goto done;
    2436             : 
    2437           0 :         if (argc == 4) {
    2438           0 :                 level = atoi(argv[3]);
    2439             :         }
    2440             : 
    2441             :         /* Get the form */
    2442             : 
    2443           0 :         status = dcerpc_spoolss_GetForm(b, mem_ctx,
    2444             :                                         &handle,
    2445           0 :                                         argv[2],
    2446             :                                         level,
    2447             :                                         NULL,
    2448             :                                         offered,
    2449             :                                         &info,
    2450             :                                         &needed,
    2451             :                                         &werror);
    2452           0 :         if (!NT_STATUS_IS_OK(status)) {
    2453           0 :                 werror = ntstatus_to_werror(status);
    2454           0 :                 goto done;
    2455             :         }
    2456           0 :         if (W_ERROR_EQUAL(werror, WERR_INSUFFICIENT_BUFFER)) {
    2457           0 :                 buffer = data_blob_talloc_zero(mem_ctx, needed);
    2458           0 :                 offered = needed;
    2459           0 :                 status = dcerpc_spoolss_GetForm(b, mem_ctx,
    2460             :                                                 &handle,
    2461           0 :                                                 argv[2],
    2462             :                                                 level,
    2463             :                                                 &buffer,
    2464             :                                                 offered,
    2465             :                                                 &info,
    2466             :                                                 &needed,
    2467             :                                                 &werror);
    2468           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2469           0 :                         werror = ntstatus_to_werror(status);
    2470           0 :                         goto done;
    2471             :                 }
    2472             :         }
    2473             : 
    2474           0 :         if (!W_ERROR_IS_OK(werror)) {
    2475           0 :                 goto done;
    2476             :         }
    2477             : 
    2478           0 :         switch (level) {
    2479           0 :         case 1:
    2480           0 :                 display_form_info1(&info.info1);
    2481           0 :                 break;
    2482           0 :         case 2:
    2483           0 :                 display_form_info2(&info.info2);
    2484           0 :                 break;
    2485             :         }
    2486             : 
    2487           0 :  done:
    2488           0 :         if (is_valid_policy_hnd(&handle)) {
    2489             :                 WERROR _result;
    2490           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
    2491             :         }
    2492             : 
    2493           0 :         return werror;
    2494             : }
    2495             : 
    2496             : /****************************************************************************
    2497             : ****************************************************************************/
    2498             : 
    2499           0 : static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli,
    2500             :                                        TALLOC_CTX *mem_ctx, int argc,
    2501             :                                        const char **argv)
    2502             : {
    2503             :         struct policy_handle handle;
    2504             :         WERROR werror;
    2505             :         NTSTATUS status;
    2506             :         const char *printername;
    2507           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    2508             : 
    2509             :         /* Parse the command arguments */
    2510             : 
    2511           0 :         if (argc != 3) {
    2512           0 :                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
    2513           0 :                 return WERR_OK;
    2514             :         }
    2515             : 
    2516             :         /* Get a printer handle */
    2517             : 
    2518           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    2519             : 
    2520           0 :         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    2521             :                                                printername,
    2522             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    2523             :                                                &handle);
    2524           0 :         if (!W_ERROR_IS_OK(werror))
    2525           0 :                 goto done;
    2526             : 
    2527             :         /* Delete the form */
    2528             : 
    2529           0 :         status = dcerpc_spoolss_DeleteForm(b, mem_ctx,
    2530             :                                            &handle,
    2531           0 :                                            argv[2],
    2532             :                                            &werror);
    2533           0 :         if (!NT_STATUS_IS_OK(status)) {
    2534           0 :                 werror = ntstatus_to_werror(status);
    2535           0 :                 goto done;
    2536             :         }
    2537             : 
    2538           0 :  done:
    2539           0 :         if (is_valid_policy_hnd(&handle)) {
    2540             :                 WERROR _result;
    2541           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
    2542             :         }
    2543             : 
    2544           0 :         return werror;
    2545             : }
    2546             : 
    2547             : /****************************************************************************
    2548             : ****************************************************************************/
    2549             : 
    2550           0 : static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli,
    2551             :                                        TALLOC_CTX *mem_ctx, int argc,
    2552             :                                        const char **argv)
    2553             : {
    2554             :         struct policy_handle handle;
    2555             :         WERROR werror;
    2556             :         const char *printername;
    2557           0 :         uint32_t num_forms, level = 1, i;
    2558             :         union spoolss_FormInfo *forms;
    2559           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    2560             : 
    2561             :         /* Parse the command arguments */
    2562             : 
    2563           0 :         if (argc < 2 || argc > 4) {
    2564           0 :                 printf ("Usage: %s <printer> [level]\n", argv[0]);
    2565           0 :                 return WERR_OK;
    2566             :         }
    2567             : 
    2568             :         /* Get a printer handle */
    2569             : 
    2570           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    2571             : 
    2572           0 :         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    2573             :                                                printername,
    2574             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    2575             :                                                &handle);
    2576           0 :         if (!W_ERROR_IS_OK(werror))
    2577           0 :                 goto done;
    2578             : 
    2579           0 :         if (argc == 3) {
    2580           0 :                 level = atoi(argv[2]);
    2581             :         }
    2582             : 
    2583             :         /* Enumerate forms */
    2584             : 
    2585           0 :         werror = rpccli_spoolss_enumforms(cli, mem_ctx,
    2586             :                                           &handle,
    2587             :                                           level,
    2588             :                                           0,
    2589             :                                           &num_forms,
    2590             :                                           &forms);
    2591             : 
    2592           0 :         if (!W_ERROR_IS_OK(werror))
    2593           0 :                 goto done;
    2594             : 
    2595             :         /* Display output */
    2596             : 
    2597           0 :         for (i = 0; i < num_forms; i++) {
    2598           0 :                 switch (level) {
    2599           0 :                 case 1:
    2600           0 :                         display_form_info1(&forms[i].info1);
    2601           0 :                         break;
    2602           0 :                 case 2:
    2603           0 :                         display_form_info2(&forms[i].info2);
    2604           0 :                         break;
    2605             :                 }
    2606             :         }
    2607             : 
    2608           0 :  done:
    2609           0 :         if (is_valid_policy_hnd(&handle)) {
    2610             :                 WERROR _result;
    2611           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
    2612             :         }
    2613             : 
    2614           0 :         return werror;
    2615             : }
    2616             : 
    2617             : /****************************************************************************
    2618             : ****************************************************************************/
    2619             : 
    2620           0 : static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
    2621             :                                             TALLOC_CTX *mem_ctx,
    2622             :                                             int argc, const char **argv)
    2623             : {
    2624             :         WERROR result;
    2625             :         NTSTATUS status;
    2626             :         const char *printername;
    2627           0 :         struct policy_handle pol = { 0, };
    2628             :         union spoolss_PrinterInfo info;
    2629             :         enum winreg_Type type;
    2630             :         union spoolss_PrinterData data;
    2631             :         DATA_BLOB blob;
    2632           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    2633           0 :         int error = 0;
    2634             : 
    2635             :         /* parse the command arguments */
    2636           0 :         if (argc < 5) {
    2637           0 :                 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
    2638             :                         " <value> <data>\n",
    2639             :                         argv[0]);
    2640           0 :                 return WERR_OK;
    2641             :         }
    2642             : 
    2643           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    2644             : 
    2645           0 :         type = REG_NONE;
    2646             : 
    2647           0 :         if (strequal(argv[2], "string")) {
    2648           0 :                 type = REG_SZ;
    2649             :         }
    2650             : 
    2651           0 :         if (strequal(argv[2], "binary")) {
    2652           0 :                 type = REG_BINARY;
    2653             :         }
    2654             : 
    2655           0 :         if (strequal(argv[2], "dword")) {
    2656           0 :                 type = REG_DWORD;
    2657             :         }
    2658             : 
    2659           0 :         if (strequal(argv[2], "multistring")) {
    2660           0 :                 type = REG_MULTI_SZ;
    2661             :         }
    2662             : 
    2663           0 :         if (type == REG_NONE) {
    2664           0 :                 printf("Unknown data type: %s\n", argv[2]);
    2665           0 :                 result =  WERR_INVALID_PARAMETER;
    2666           0 :                 goto done;
    2667             :         }
    2668             : 
    2669             :         /* get a printer handle */
    2670             : 
    2671           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    2672             :                                                printername,
    2673             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    2674             :                                                &pol);
    2675           0 :         if (!W_ERROR_IS_OK(result)) {
    2676           0 :                 goto done;
    2677             :         }
    2678             : 
    2679           0 :         result = rpccli_spoolss_getprinter(cli, mem_ctx,
    2680             :                                            &pol,
    2681             :                                            0,
    2682             :                                            0,
    2683             :                                            &info);
    2684           0 :         if (!W_ERROR_IS_OK(result)) {
    2685           0 :                 goto done;
    2686             :         }
    2687             : 
    2688           0 :         printf("%s\n", current_timestring(mem_ctx, true));
    2689           0 :         printf("\tchange_id (before set)\t:[0x%x]\n", info.info0.change_id);
    2690             : 
    2691             :         /* Set the printer data */
    2692             : 
    2693           0 :         switch (type) {
    2694           0 :         case REG_SZ:
    2695           0 :                 data.string = talloc_strdup(mem_ctx, argv[4]);
    2696           0 :                 W_ERROR_HAVE_NO_MEMORY(data.string);
    2697           0 :                 break;
    2698           0 :         case REG_DWORD:
    2699           0 :                 data.value = smb_strtoul(argv[4],
    2700             :                                          NULL,
    2701             :                                          10,
    2702             :                                          &error,
    2703             :                                          SMB_STR_STANDARD);
    2704           0 :                 if (error != 0) {
    2705           0 :                         result = WERR_INVALID_PARAMETER;
    2706           0 :                         goto done;
    2707             :                 }
    2708             : 
    2709           0 :                 break;
    2710           0 :         case REG_BINARY:
    2711           0 :                 data.binary = strhex_to_data_blob(mem_ctx, argv[4]);
    2712           0 :                 break;
    2713           0 :         case REG_MULTI_SZ: {
    2714             :                 int i;
    2715             :                 size_t num_strings;
    2716           0 :                 const char **strings = NULL;
    2717             : 
    2718           0 :                 num_strings = 0;
    2719             : 
    2720           0 :                 for (i=4; i<argc; i++) {
    2721           0 :                         if (strcmp(argv[i], "NULL") == 0) {
    2722           0 :                                 argv[i] = "";
    2723             :                         }
    2724           0 :                         if (!add_string_to_array(mem_ctx, argv[i],
    2725             :                                                  &strings,
    2726             :                                                  &num_strings)) {
    2727           0 :                                 result = WERR_NOT_ENOUGH_MEMORY;
    2728           0 :                                 goto done;
    2729             :                         }
    2730             :                 }
    2731           0 :                 data.string_array = talloc_zero_array(mem_ctx, const char *, num_strings + 1);
    2732           0 :                 if (!data.string_array) {
    2733           0 :                         result = WERR_NOT_ENOUGH_MEMORY;
    2734           0 :                         goto done;
    2735             :                 }
    2736           0 :                 for (i=0; i < num_strings; i++) {
    2737           0 :                         data.string_array[i] = strings[i];
    2738             :                 }
    2739           0 :                 break;
    2740             :                 }
    2741           0 :         default:
    2742           0 :                 printf("Unknown data type: %s\n", argv[2]);
    2743           0 :                 result = WERR_INVALID_PARAMETER;
    2744           0 :                 goto done;
    2745             :         }
    2746             : 
    2747           0 :         result = push_spoolss_PrinterData(mem_ctx, &blob, type, &data);
    2748           0 :         if (!W_ERROR_IS_OK(result)) {
    2749           0 :                 goto done;
    2750             :         }
    2751             : 
    2752           0 :         status = dcerpc_spoolss_SetPrinterData(b, mem_ctx,
    2753             :                                                &pol,
    2754           0 :                                                argv[3], /* value_name */
    2755             :                                                type,
    2756             :                                                blob.data,
    2757           0 :                                                blob.length,
    2758             :                                                &result);
    2759           0 :         if (!NT_STATUS_IS_OK(status)) {
    2760           0 :                 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
    2761           0 :                 result = ntstatus_to_werror(status);
    2762           0 :                 goto done;
    2763             :         }
    2764           0 :         if (!W_ERROR_IS_OK(result)) {
    2765           0 :                 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
    2766           0 :                 goto done;
    2767             :         }
    2768           0 :         printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
    2769             : 
    2770           0 :         result = rpccli_spoolss_getprinter(cli, mem_ctx,
    2771             :                                            &pol,
    2772             :                                            0,
    2773             :                                            0,
    2774             :                                            &info);
    2775           0 :         if (!W_ERROR_IS_OK(result)) {
    2776           0 :                 goto done;
    2777             :         }
    2778             : 
    2779           0 :         printf("%s\n", current_timestring(mem_ctx, true));
    2780           0 :         printf("\tchange_id (after set)\t:[0x%x]\n", info.info0.change_id);
    2781             : 
    2782           0 : done:
    2783             :         /* cleanup */
    2784           0 :         if (is_valid_policy_hnd(&pol)) {
    2785             :                 WERROR _result;
    2786           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &_result);
    2787             :         }
    2788             : 
    2789           0 :         return result;
    2790             : }
    2791             : 
    2792             : /****************************************************************************
    2793             : ****************************************************************************/
    2794             : 
    2795           0 : static void display_job_info1(struct spoolss_JobInfo1 *r)
    2796             : {
    2797           0 :         printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", r->position, r->job_id,
    2798             :                r->user_name, r->document_name, r->text_status, r->pages_printed,
    2799             :                r->total_pages);
    2800           0 : }
    2801             : 
    2802             : /****************************************************************************
    2803             : ****************************************************************************/
    2804             : 
    2805           3 : static void display_job_info2(struct spoolss_JobInfo2 *r)
    2806             : {
    2807           3 :         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n",
    2808             :                r->position, r->job_id,
    2809             :                r->user_name, r->document_name, r->text_status, r->pages_printed,
    2810             :                r->total_pages, r->size);
    2811           3 : }
    2812             : 
    2813             : /****************************************************************************
    2814             : ****************************************************************************/
    2815             : 
    2816           0 : static void display_job_info3(struct spoolss_JobInfo3 *r)
    2817             : {
    2818           0 :         printf("jobid[%d], next_jobid[%d]\n",
    2819             :                 r->job_id, r->next_job_id);
    2820           0 : }
    2821             : 
    2822             : /****************************************************************************
    2823             : ****************************************************************************/
    2824             : 
    2825           0 : static void display_job_info4(struct spoolss_JobInfo4 *r)
    2826             : {
    2827           0 :         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d/%d bytes\n",
    2828             :                r->position, r->job_id,
    2829             :                r->user_name, r->document_name, r->text_status, r->pages_printed,
    2830             :                r->total_pages, r->size, r->size_high);
    2831           0 : }
    2832             : 
    2833             : /****************************************************************************
    2834             : ****************************************************************************/
    2835             : 
    2836           6 : static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli,
    2837             :                                       TALLOC_CTX *mem_ctx, int argc,
    2838             :                                       const char **argv)
    2839             : {
    2840             :         WERROR result;
    2841           6 :         uint32_t level = 1, count, i;
    2842             :         const char *printername;
    2843             :         struct policy_handle hnd;
    2844             :         union spoolss_JobInfo *info;
    2845           6 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    2846             : 
    2847           6 :         if (argc < 2 || argc > 3) {
    2848           0 :                 printf("Usage: %s printername [level]\n", argv[0]);
    2849           0 :                 return WERR_OK;
    2850             :         }
    2851             : 
    2852           6 :         if (argc == 3) {
    2853           6 :                 level = atoi(argv[2]);
    2854             :         }
    2855             : 
    2856             :         /* Open printer handle */
    2857             : 
    2858           6 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    2859             : 
    2860           6 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    2861             :                                                printername,
    2862             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    2863             :                                                &hnd);
    2864           6 :         if (!W_ERROR_IS_OK(result))
    2865           0 :                 goto done;
    2866             : 
    2867             :         /* Enumerate ports */
    2868             : 
    2869           6 :         result = rpccli_spoolss_enumjobs(cli, mem_ctx,
    2870             :                                          &hnd,
    2871             :                                          0, /* firstjob */
    2872             :                                          1000, /* numjobs */
    2873             :                                          level,
    2874             :                                          0,
    2875             :                                          &count,
    2876             :                                          &info);
    2877           6 :         if (!W_ERROR_IS_OK(result)) {
    2878           0 :                 goto done;
    2879             :         }
    2880             : 
    2881           9 :         for (i = 0; i < count; i++) {
    2882           3 :                 switch (level) {
    2883           0 :                 case 1:
    2884           0 :                         display_job_info1(&info[i].info1);
    2885           0 :                         break;
    2886           3 :                 case 2:
    2887           3 :                         display_job_info2(&info[i].info2);
    2888           3 :                         break;
    2889           0 :                 default:
    2890           0 :                         d_printf("unknown info level %d\n", level);
    2891           0 :                         break;
    2892             :                 }
    2893             :         }
    2894             : 
    2895           6 : done:
    2896           6 :         if (is_valid_policy_hnd(&hnd)) {
    2897             :                 WERROR _result;
    2898           6 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
    2899             :         }
    2900             : 
    2901           6 :         return result;
    2902             : }
    2903             : 
    2904             : /****************************************************************************
    2905             : ****************************************************************************/
    2906             : 
    2907           0 : static WERROR cmd_spoolss_get_job(struct rpc_pipe_client *cli,
    2908             :                                   TALLOC_CTX *mem_ctx, int argc,
    2909             :                                   const char **argv)
    2910             : {
    2911             :         WERROR result;
    2912             :         const char *printername;
    2913             :         struct policy_handle hnd;
    2914             :         uint32_t job_id;
    2915           0 :         uint32_t level = 1;
    2916             :         union spoolss_JobInfo info;
    2917           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    2918             : 
    2919           0 :         if (argc < 3 || argc > 4) {
    2920           0 :                 printf("Usage: %s printername job_id [level]\n", argv[0]);
    2921           0 :                 return WERR_OK;
    2922             :         }
    2923             : 
    2924           0 :         job_id = atoi(argv[2]);
    2925             : 
    2926           0 :         if (argc == 4) {
    2927           0 :                 level = atoi(argv[3]);
    2928             :         }
    2929             : 
    2930             :         /* Open printer handle */
    2931             : 
    2932           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    2933             : 
    2934           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    2935             :                                                printername,
    2936             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    2937             :                                                &hnd);
    2938           0 :         if (!W_ERROR_IS_OK(result)) {
    2939           0 :                 goto done;
    2940             :         }
    2941             : 
    2942             :         /* Enumerate ports */
    2943             : 
    2944           0 :         result = rpccli_spoolss_getjob(cli, mem_ctx,
    2945             :                                        &hnd,
    2946             :                                        job_id,
    2947             :                                        level,
    2948             :                                        0,
    2949             :                                        &info);
    2950             : 
    2951           0 :         if (!W_ERROR_IS_OK(result)) {
    2952           0 :                 goto done;
    2953             :         }
    2954             : 
    2955           0 :         switch (level) {
    2956           0 :         case 1:
    2957           0 :                 display_job_info1(&info.info1);
    2958           0 :                 break;
    2959           0 :         case 2:
    2960           0 :                 display_job_info2(&info.info2);
    2961           0 :                 break;
    2962           0 :         case 3:
    2963           0 :                 display_job_info3(&info.info3);
    2964           0 :                 break;
    2965           0 :         case 4:
    2966           0 :                 display_job_info4(&info.info4);
    2967           0 :                 break;
    2968           0 :         default:
    2969           0 :                 d_printf("unknown info level %d\n", level);
    2970           0 :                 break;
    2971             :         }
    2972             : 
    2973           0 : done:
    2974           0 :         if (is_valid_policy_hnd(&hnd)) {
    2975             :                 WERROR _result;
    2976           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
    2977             :         }
    2978             : 
    2979           0 :         return result;
    2980             : }
    2981             : 
    2982             : /****************************************************************************
    2983             : ****************************************************************************/
    2984             : 
    2985             : static struct {
    2986             :         const char *name;
    2987             :         enum spoolss_JobControl val;
    2988             : } cmdvals[] = {
    2989             :         {"PAUSE", SPOOLSS_JOB_CONTROL_PAUSE},
    2990             :         {"RESUME", SPOOLSS_JOB_CONTROL_RESUME},
    2991             :         {"CANCEL", SPOOLSS_JOB_CONTROL_CANCEL},
    2992             :         {"RESTART", SPOOLSS_JOB_CONTROL_RESTART},
    2993             :         {"DELETE", SPOOLSS_JOB_CONTROL_DELETE},
    2994             :         {"SEND_TO_PRINTER", SPOOLSS_JOB_CONTROL_SEND_TO_PRINTER},
    2995             :         {"EJECTED", SPOOLSS_JOB_CONTROL_LAST_PAGE_EJECTED},
    2996             :         {"RETAIN", SPOOLSS_JOB_CONTROL_RETAIN},
    2997             :         {"RELEASE", SPOOLSS_JOB_CONTROL_RELEASE}
    2998             : };
    2999             : 
    3000           0 : static enum spoolss_JobControl parse_setjob_command(const char *cmd)
    3001             : {
    3002             :         int i;
    3003             : 
    3004           0 :         for (i = 0; i < sizeof(cmdvals)/sizeof(cmdvals[0]); i++) {
    3005           0 :                 if (strequal(cmdvals[i].name, cmd)) {
    3006           0 :                         return cmdvals[i].val;
    3007             :                 }
    3008             :         }
    3009           0 :         return (enum spoolss_JobControl)atoi(cmd);
    3010             : }
    3011             : 
    3012           0 : static WERROR cmd_spoolss_set_job(struct rpc_pipe_client *cli,
    3013             :                                   TALLOC_CTX *mem_ctx, int argc,
    3014             :                                   const char **argv)
    3015             : {
    3016             :         WERROR result;
    3017             :         NTSTATUS status;
    3018             :         const char *printername;
    3019             :         struct policy_handle hnd;
    3020             :         uint32_t job_id;
    3021             :         enum spoolss_JobControl command;
    3022           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    3023             : 
    3024           0 :         if (argc != 4) {
    3025           0 :                 printf("Usage: %s printername job_id command\n", argv[0]);
    3026           0 :                 printf("command = [PAUSE|RESUME|CANCEL|RESTART|DELETE|"
    3027             :                         "SEND_TO_PRINTER|EJECTED|RETAIN|RELEASE]\n");
    3028           0 :                 return WERR_OK;
    3029             :         }
    3030             : 
    3031           0 :         job_id = atoi(argv[2]);
    3032           0 :         command = parse_setjob_command(argv[3]);
    3033             : 
    3034             :         /* Open printer handle */
    3035             : 
    3036           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    3037             : 
    3038           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    3039             :                                                printername,
    3040             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    3041             :                                                &hnd);
    3042           0 :         if (!W_ERROR_IS_OK(result)) {
    3043           0 :                 goto done;
    3044             :         }
    3045             : 
    3046             :         /* Set Job */
    3047             : 
    3048           0 :         status = dcerpc_spoolss_SetJob(b, mem_ctx,
    3049             :                                        &hnd,
    3050             :                                        job_id,
    3051             :                                        NULL,
    3052             :                                        command,
    3053             :                                        &result);
    3054           0 :         if (!NT_STATUS_IS_OK(status)) {
    3055           0 :                 result = ntstatus_to_werror(status);
    3056           0 :                 goto done;
    3057             :         }
    3058           0 :         if (!W_ERROR_IS_OK(result)) {
    3059           0 :                 goto done;
    3060             :         }
    3061             : 
    3062           0 : done:
    3063           0 :         if (is_valid_policy_hnd(&hnd)) {
    3064             :                 WERROR _result;
    3065           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
    3066             :         }
    3067             : 
    3068           0 :         return result;
    3069             : }
    3070             : 
    3071             : /****************************************************************************
    3072             : ****************************************************************************/
    3073             : 
    3074           0 : static WERROR cmd_spoolss_enum_data(struct rpc_pipe_client *cli,
    3075             :                                     TALLOC_CTX *mem_ctx, int argc,
    3076             :                                     const char **argv)
    3077             : {
    3078             :         WERROR result;
    3079             :         NTSTATUS status;
    3080             :         const char *printername;
    3081             :         struct policy_handle hnd;
    3082             :         uint32_t value_needed;
    3083             :         enum winreg_Type type;
    3084             :         uint32_t data_needed;
    3085           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    3086             :         struct spoolss_EnumPrinterData r;
    3087             : 
    3088           0 :         if (argc != 2) {
    3089           0 :                 printf("Usage: %s printername\n", argv[0]);
    3090           0 :                 return WERR_OK;
    3091             :         }
    3092             : 
    3093             :         /* Open printer handle */
    3094             : 
    3095           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    3096             : 
    3097           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    3098             :                                                printername,
    3099             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    3100             :                                                &hnd);
    3101           0 :         if (!W_ERROR_IS_OK(result)) {
    3102           0 :                 goto done;
    3103             :         }
    3104             : 
    3105             :         /* Enumerate data */
    3106             : 
    3107           0 :         r.in.handle = &hnd;
    3108           0 :         r.in.enum_index = 0;
    3109           0 :         r.in.value_offered = 0;
    3110           0 :         r.in.data_offered = 0;
    3111           0 :         r.out.value_name = NULL;
    3112           0 :         r.out.value_needed = &value_needed;
    3113           0 :         r.out.type = &type;
    3114           0 :         r.out.data = NULL;
    3115           0 :         r.out.data_needed = &data_needed;
    3116             : 
    3117           0 :         status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
    3118           0 :         if (!NT_STATUS_IS_OK(status)) {
    3119           0 :                 result = ntstatus_to_werror(status);
    3120           0 :                 goto done;
    3121             :         }
    3122             : 
    3123           0 :         if (!W_ERROR_IS_OK(r.out.result)) {
    3124           0 :                 result = r.out.result;
    3125           0 :                 goto done;
    3126             :         }
    3127             : 
    3128           0 :         r.in.data_offered       = *r.out.data_needed;
    3129           0 :         r.in.value_offered      = *r.out.value_needed;
    3130           0 :         r.out.data              = talloc_zero_array(mem_ctx, uint8_t, r.in.data_offered);
    3131           0 :         r.out.value_name        = talloc_zero_array(mem_ctx, char, r.in.value_offered);
    3132             : 
    3133             :         do {
    3134             : 
    3135           0 :                 status = dcerpc_spoolss_EnumPrinterData_r(b, mem_ctx, &r);
    3136           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3137           0 :                         result = ntstatus_to_werror(status);
    3138           0 :                         goto done;
    3139             :                 }
    3140             : 
    3141           0 :                 if (W_ERROR_EQUAL(r.out.result, WERR_NO_MORE_ITEMS)) {
    3142           0 :                         result = WERR_OK;
    3143           0 :                         break;
    3144             :                 }
    3145             : 
    3146           0 :                 r.in.enum_index++;
    3147             : 
    3148           0 :                 display_reg_value(r.out.value_name, *r.out.type,
    3149           0 :                                   data_blob_const(r.out.data, r.in.data_offered));
    3150             : 
    3151           0 :         } while (W_ERROR_IS_OK(r.out.result));
    3152             : 
    3153           0 : done:
    3154           0 :         if (is_valid_policy_hnd(&hnd)) {
    3155             :                 WERROR _result;
    3156           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
    3157             :         }
    3158             : 
    3159           0 :         return result;
    3160             : }
    3161             : 
    3162             : /****************************************************************************
    3163             : ****************************************************************************/
    3164             : 
    3165           0 : static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli,
    3166             :                                           TALLOC_CTX *mem_ctx, int argc,
    3167             :                                           const char **argv)
    3168             : {
    3169             :         WERROR result;
    3170             :         uint32_t i;
    3171             :         const char *printername;
    3172             :         struct policy_handle hnd;
    3173             :         uint32_t count;
    3174             :         struct spoolss_PrinterEnumValues *info;
    3175           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    3176             : 
    3177           0 :         if (argc != 3) {
    3178           0 :                 printf("Usage: %s printername <keyname>\n", argv[0]);
    3179           0 :                 return WERR_OK;
    3180             :         }
    3181             : 
    3182             :         /* Open printer handle */
    3183             : 
    3184           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    3185             : 
    3186           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    3187             :                                                printername,
    3188             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    3189             :                                                &hnd);
    3190           0 :         if (!W_ERROR_IS_OK(result)) {
    3191           0 :                 goto done;
    3192             :         }
    3193             : 
    3194             :         /* Enumerate subkeys */
    3195             : 
    3196           0 :         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx,
    3197             :                                                   &hnd,
    3198           0 :                                                   argv[2],
    3199             :                                                   0,
    3200             :                                                   &count,
    3201             :                                                   &info);
    3202           0 :         if (!W_ERROR_IS_OK(result)) {
    3203           0 :                 goto done;
    3204             :         }
    3205             : 
    3206           0 :         for (i=0; i < count; i++) {
    3207           0 :                 display_printer_data(info[i].value_name,
    3208           0 :                                      info[i].type,
    3209           0 :                                      info[i].data->data,
    3210           0 :                                      info[i].data->length);
    3211             :         }
    3212             : 
    3213           0 :  done:
    3214           0 :         if (is_valid_policy_hnd(&hnd)) {
    3215             :                 WERROR _result;
    3216           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
    3217             :         }
    3218             : 
    3219           0 :         return result;
    3220             : }
    3221             : 
    3222             : /****************************************************************************
    3223             : ****************************************************************************/
    3224             : 
    3225           0 : static WERROR cmd_spoolss_enum_printerkey(struct rpc_pipe_client *cli,
    3226             :                                           TALLOC_CTX *mem_ctx, int argc,
    3227             :                                           const char **argv)
    3228             : {
    3229             :         WERROR result;
    3230             :         const char *printername;
    3231           0 :         const char *keyname = NULL;
    3232             :         struct policy_handle hnd;
    3233           0 :         const char **key_buffer = NULL;
    3234             :         int i;
    3235           0 :         uint32_t offered = 0;
    3236           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    3237             : 
    3238           0 :         if (argc < 2 || argc > 4) {
    3239           0 :                 printf("Usage: %s printername [keyname] [offered]\n", argv[0]);
    3240           0 :                 return WERR_OK;
    3241             :         }
    3242             : 
    3243           0 :         if (argc >= 3) {
    3244           0 :                 keyname = argv[2];
    3245             :         } else {
    3246           0 :                 keyname = "";
    3247             :         }
    3248             : 
    3249           0 :         if (argc == 4) {
    3250           0 :                 offered = atoi(argv[3]);
    3251             :         }
    3252             : 
    3253             :         /* Open printer handle */
    3254             : 
    3255           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    3256             : 
    3257           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    3258             :                                                printername,
    3259             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    3260             :                                                &hnd);
    3261           0 :         if (!W_ERROR_IS_OK(result)) {
    3262           0 :                 goto done;
    3263             :         }
    3264             : 
    3265             :         /* Enumerate subkeys */
    3266             : 
    3267           0 :         result = rpccli_spoolss_enumprinterkey(cli, mem_ctx,
    3268             :                                                &hnd,
    3269             :                                                keyname,
    3270             :                                                &key_buffer,
    3271             :                                                offered);
    3272             : 
    3273           0 :         if (!W_ERROR_IS_OK(result)) {
    3274           0 :                 goto done;
    3275             :         }
    3276             : 
    3277           0 :         for (i=0; key_buffer && key_buffer[i]; i++) {
    3278           0 :                 printf("%s\n", key_buffer[i]);
    3279             :         }
    3280             : 
    3281           0 :  done:
    3282             : 
    3283           0 :         if (is_valid_policy_hnd(&hnd)) {
    3284             :                 WERROR _result;
    3285           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
    3286             :         }
    3287             : 
    3288           0 :         return result;
    3289             : }
    3290             : 
    3291             : /****************************************************************************
    3292             : ****************************************************************************/
    3293             : 
    3294           0 : static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli,
    3295             :                                      TALLOC_CTX *mem_ctx, int argc,
    3296             :                                      const char **argv)
    3297             : {
    3298             :         const char *printername;
    3299             :         const char *clientname;
    3300           0 :         struct policy_handle hnd = { 0, };
    3301             :         WERROR result;
    3302             :         NTSTATUS status;
    3303             :         struct spoolss_NotifyOption option;
    3304           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    3305             : 
    3306           0 :         if (argc != 2) {
    3307           0 :                 printf("Usage: %s printername\n", argv[0]);
    3308           0 :                 result = WERR_OK;
    3309           0 :                 goto done;
    3310             :         }
    3311             : 
    3312             :         /* Open printer */
    3313             : 
    3314           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    3315             : 
    3316           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    3317             :                                                printername,
    3318             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    3319             :                                                &hnd);
    3320           0 :         if (!W_ERROR_IS_OK(result)) {
    3321           0 :                 printf("Error opening %s\n", argv[1]);
    3322           0 :                 goto done;
    3323             :         }
    3324             : 
    3325             :         /* Create spool options */
    3326             : 
    3327           0 :         option.version = 2;
    3328           0 :         option.count = 2;
    3329             : 
    3330           0 :         option.types = talloc_array(mem_ctx, struct spoolss_NotifyOptionType, 2);
    3331           0 :         if (option.types == NULL) {
    3332           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3333           0 :                 goto done;
    3334             :         }
    3335             : 
    3336           0 :         option.types[0].type = PRINTER_NOTIFY_TYPE;
    3337           0 :         option.types[0].count = 1;
    3338           0 :         option.types[0].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
    3339           0 :         if (option.types[0].fields == NULL) {
    3340           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3341           0 :                 goto done;
    3342             :         }
    3343           0 :         option.types[0].fields[0].field = PRINTER_NOTIFY_FIELD_SERVER_NAME;
    3344             : 
    3345           0 :         option.types[1].type = JOB_NOTIFY_TYPE;
    3346           0 :         option.types[1].count = 1;
    3347           0 :         option.types[1].fields = talloc_array(mem_ctx, union spoolss_Field, 1);
    3348           0 :         if (option.types[1].fields == NULL) {
    3349           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3350           0 :                 goto done;
    3351             :         }
    3352           0 :         option.types[1].fields[0].field = JOB_NOTIFY_FIELD_PRINTER_NAME;
    3353             : 
    3354           0 :         clientname = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name());
    3355           0 :         if (!clientname) {
    3356           0 :                 result = WERR_NOT_ENOUGH_MEMORY;
    3357           0 :                 goto done;
    3358             :         }
    3359             : 
    3360             :         /* Send rffpcnex */
    3361             : 
    3362           0 :         status = dcerpc_spoolss_RemoteFindFirstPrinterChangeNotifyEx(b, mem_ctx,
    3363             :                                                                      &hnd,
    3364             :                                                                      0,
    3365             :                                                                      0,
    3366             :                                                                      clientname,
    3367             :                                                                      123,
    3368             :                                                                      &option,
    3369             :                                                                      &result);
    3370           0 :         if (!NT_STATUS_IS_OK(status)) {
    3371           0 :                 result = ntstatus_to_werror(status);
    3372           0 :                 goto done;
    3373             :         }
    3374           0 :         if (!W_ERROR_IS_OK(result)) {
    3375           0 :                 printf("Error rffpcnex %s\n", argv[1]);
    3376           0 :                 goto done;
    3377             :         }
    3378             : 
    3379           0 : done:
    3380           0 :         if (is_valid_policy_hnd(&hnd)) {
    3381             :                 WERROR _result;
    3382           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &hnd, &_result);
    3383             :         }
    3384             : 
    3385           0 :         return result;
    3386             : }
    3387             : 
    3388             : /****************************************************************************
    3389             : ****************************************************************************/
    3390             : 
    3391           0 : static bool compare_printer( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
    3392             :                              struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
    3393             : {
    3394             :         union spoolss_PrinterInfo info1, info2;
    3395             :         WERROR werror;
    3396           0 :         TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
    3397             : 
    3398           0 :         printf("Retrieving printer propertiesfor %s...", cli1->desthost);
    3399           0 :         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
    3400             :                                            hnd1,
    3401             :                                            2,
    3402             :                                            0,
    3403             :                                            &info1);
    3404           0 :         if ( !W_ERROR_IS_OK(werror) ) {
    3405           0 :                 printf("failed (%s)\n", win_errstr(werror));
    3406           0 :                 talloc_destroy(mem_ctx);
    3407           0 :                 return false;
    3408             :         }
    3409           0 :         printf("ok\n");
    3410             : 
    3411           0 :         printf("Retrieving printer properties for %s...", cli2->desthost);
    3412           0 :         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
    3413             :                                            hnd2,
    3414             :                                            2,
    3415             :                                            0,
    3416             :                                            &info2);
    3417           0 :         if ( !W_ERROR_IS_OK(werror) ) {
    3418           0 :                 printf("failed (%s)\n", win_errstr(werror));
    3419           0 :                 talloc_destroy(mem_ctx);
    3420           0 :                 return false;
    3421             :         }
    3422           0 :         printf("ok\n");
    3423             : 
    3424           0 :         talloc_destroy(mem_ctx);
    3425             : 
    3426           0 :         return true;
    3427             : }
    3428             : 
    3429             : /****************************************************************************
    3430             : ****************************************************************************/
    3431             : 
    3432           0 : static bool compare_printer_secdesc( struct rpc_pipe_client *cli1, struct policy_handle *hnd1,
    3433             :                                      struct rpc_pipe_client *cli2, struct policy_handle *hnd2 )
    3434             : {
    3435             :         union spoolss_PrinterInfo info1, info2;
    3436             :         WERROR werror;
    3437           0 :         TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
    3438             :         struct security_descriptor *sd1, *sd2;
    3439           0 :         bool result = true;
    3440             : 
    3441             : 
    3442           0 :         printf("Retrieving printer security for %s...", cli1->desthost);
    3443           0 :         werror = rpccli_spoolss_getprinter(cli1, mem_ctx,
    3444             :                                            hnd1,
    3445             :                                            3,
    3446             :                                            0,
    3447             :                                            &info1);
    3448           0 :         if ( !W_ERROR_IS_OK(werror) ) {
    3449           0 :                 printf("failed (%s)\n", win_errstr(werror));
    3450           0 :                 result = false;
    3451           0 :                 goto done;
    3452             :         }
    3453           0 :         printf("ok\n");
    3454             : 
    3455           0 :         printf("Retrieving printer security for %s...", cli2->desthost);
    3456           0 :         werror = rpccli_spoolss_getprinter(cli2, mem_ctx,
    3457             :                                            hnd2,
    3458             :                                            3,
    3459             :                                            0,
    3460             :                                            &info2);
    3461           0 :         if ( !W_ERROR_IS_OK(werror) ) {
    3462           0 :                 printf("failed (%s)\n", win_errstr(werror));
    3463           0 :                 result = false;
    3464           0 :                 goto done;
    3465             :         }
    3466           0 :         printf("ok\n");
    3467             : 
    3468             : 
    3469           0 :         printf("++ ");
    3470             : 
    3471           0 :         sd1 = info1.info3.secdesc;
    3472           0 :         sd2 = info2.info3.secdesc;
    3473             : 
    3474           0 :         if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
    3475           0 :                 printf("NULL secdesc!\n");
    3476           0 :                 result = false;
    3477           0 :                 goto done;
    3478             :         }
    3479             : 
    3480           0 :         if (!security_descriptor_equal( sd1, sd2 ) ) {
    3481           0 :                 printf("Security Descriptors *not* equal!\n");
    3482           0 :                 result = false;
    3483           0 :                 goto done;
    3484             :         }
    3485             : 
    3486           0 :         printf("Security descriptors match\n");
    3487             : 
    3488           0 : done:
    3489           0 :         talloc_destroy(mem_ctx);
    3490           0 :         return result;
    3491             : }
    3492             : 
    3493             : 
    3494             : /****************************************************************************
    3495             : ****************************************************************************/
    3496             : 
    3497           0 : static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli,
    3498             :                                      TALLOC_CTX *mem_ctx, int argc,
    3499             :                                      const char **argv)
    3500             : {
    3501             :         const char *printername;
    3502           0 :         char *printername_path = NULL;
    3503           0 :         struct cli_state *cli_server2 = NULL;
    3504           0 :         struct rpc_pipe_client *cli2 = NULL;
    3505             :         struct policy_handle hPrinter1, hPrinter2;
    3506             :         NTSTATUS nt_status;
    3507             :         WERROR werror;
    3508           0 :         struct cli_credentials *creds = samba_cmdline_get_creds();
    3509             : 
    3510           0 :         if ( argc != 3 )  {
    3511           0 :                 printf("Usage: %s <printer> <server>\n", argv[0]);
    3512           0 :                 return WERR_OK;
    3513             :         }
    3514             : 
    3515           0 :         printername = argv[1];
    3516             : 
    3517             :         /* first get the connection to the remote server */
    3518             : 
    3519           0 :         nt_status = cli_full_connection_creds(&cli_server2, lp_netbios_name(), argv[2],
    3520             :                                 NULL, 0,
    3521             :                                 "IPC$", "IPC",
    3522             :                                 creds,
    3523             :                                 CLI_FULL_CONNECTION_IPC);
    3524           0 :         if ( !NT_STATUS_IS_OK(nt_status) )
    3525           0 :                 return WERR_GEN_FAILURE;
    3526             : 
    3527           0 :         nt_status = cli_rpc_pipe_open_noauth(cli_server2, &ndr_table_spoolss,
    3528             :                                              &cli2);
    3529           0 :         if (!NT_STATUS_IS_OK(nt_status)) {
    3530           0 :                 printf("failed to open spoolss pipe on server %s (%s)\n",
    3531           0 :                         argv[2], nt_errstr(nt_status));
    3532           0 :                 return WERR_GEN_FAILURE;
    3533             :         }
    3534             : 
    3535             :         /* now open up both printers */
    3536             : 
    3537           0 :         RPCCLIENT_PRINTERNAME(printername_path, cli, printername);
    3538             : 
    3539           0 :         printf("Opening %s...", printername_path);
    3540             : 
    3541           0 :         werror = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    3542             :                                                printername_path,
    3543             :                                                PRINTER_ALL_ACCESS,
    3544             :                                                &hPrinter1);
    3545           0 :         if ( !W_ERROR_IS_OK(werror) ) {
    3546           0 :                 printf("failed (%s)\n", win_errstr(werror));
    3547           0 :                 goto done;
    3548             :         }
    3549           0 :         printf("ok\n");
    3550             : 
    3551           0 :         RPCCLIENT_PRINTERNAME(printername_path, cli2, printername);
    3552             : 
    3553           0 :         printf("Opening %s...", printername_path);
    3554           0 :         werror = rpccli_spoolss_openprinter_ex(cli2, mem_ctx,
    3555             :                                                printername_path,
    3556             :                                                PRINTER_ALL_ACCESS,
    3557             :                                                &hPrinter2);
    3558           0 :         if ( !W_ERROR_IS_OK(werror) ) {
    3559           0 :                  printf("failed (%s)\n", win_errstr(werror));
    3560           0 :                 goto done;
    3561             :         }
    3562           0 :         printf("ok\n");
    3563             : 
    3564           0 :         compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
    3565           0 :         compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
    3566             : #if 0
    3567             :         compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
    3568             : #endif
    3569             : 
    3570             : 
    3571           0 : done:
    3572             :         /* cleanup */
    3573             : 
    3574           0 :         printf("Closing printers...");
    3575             :         {
    3576             :                 WERROR _result;
    3577           0 :                 dcerpc_spoolss_ClosePrinter(cli->binding_handle, mem_ctx, &hPrinter1, &_result);
    3578           0 :                 dcerpc_spoolss_ClosePrinter(cli2->binding_handle, mem_ctx, &hPrinter2, &_result);
    3579             :         }
    3580           0 :         printf("ok\n");
    3581             : 
    3582             :         /* close the second remote connection */
    3583             : 
    3584           0 :         cli_shutdown( cli_server2 );
    3585           0 :         return WERR_OK;
    3586             : }
    3587             : 
    3588           0 : static void display_proc_info1(struct spoolss_PrintProcessorInfo1 *r)
    3589             : {
    3590           0 :         printf("print_processor_name: %s\n", r->print_processor_name);
    3591           0 : }
    3592             : 
    3593           0 : static WERROR cmd_spoolss_enum_procs(struct rpc_pipe_client *cli,
    3594             :                                      TALLOC_CTX *mem_ctx, int argc,
    3595             :                                      const char **argv)
    3596             : {
    3597             :         WERROR werror;
    3598           0 :         const char *environment = SPOOLSS_ARCHITECTURE_NT_X86;
    3599           0 :         uint32_t num_procs, level = 1, i;
    3600             :         union spoolss_PrintProcessorInfo *procs;
    3601             : 
    3602             :         /* Parse the command arguments */
    3603             : 
    3604           0 :         if (argc < 1 || argc > 4) {
    3605           0 :                 printf ("Usage: %s [environment] [level]\n", argv[0]);
    3606           0 :                 return WERR_OK;
    3607             :         }
    3608             : 
    3609           0 :         if (argc >= 2) {
    3610           0 :                 environment = argv[1];
    3611             :         }
    3612             : 
    3613           0 :         if (argc == 3) {
    3614           0 :                 level = atoi(argv[2]);
    3615             :         }
    3616             : 
    3617             :         /* Enumerate Print Processors */
    3618             : 
    3619           0 :         werror = rpccli_spoolss_enumprintprocessors(cli, mem_ctx,
    3620           0 :                                                     cli->srv_name_slash,
    3621             :                                                     environment,
    3622             :                                                     level,
    3623             :                                                     0,
    3624             :                                                     &num_procs,
    3625             :                                                     &procs);
    3626           0 :         if (!W_ERROR_IS_OK(werror))
    3627           0 :                 goto done;
    3628             : 
    3629             :         /* Display output */
    3630             : 
    3631           0 :         for (i = 0; i < num_procs; i++) {
    3632           0 :                 switch (level) {
    3633           0 :                 case 1:
    3634           0 :                         display_proc_info1(&procs[i].info1);
    3635           0 :                         break;
    3636             :                 }
    3637             :         }
    3638             : 
    3639           0 :  done:
    3640           0 :         return werror;
    3641             : }
    3642             : 
    3643           0 : static void display_proc_data_types_info1(struct spoolss_PrintProcDataTypesInfo1 *r)
    3644             : {
    3645           0 :         printf("name_array: %s\n", r->name_array);
    3646           0 : }
    3647             : 
    3648           0 : static WERROR cmd_spoolss_enum_proc_data_types(struct rpc_pipe_client *cli,
    3649             :                                                TALLOC_CTX *mem_ctx, int argc,
    3650             :                                                const char **argv)
    3651             : {
    3652             :         WERROR werror;
    3653           0 :         const char *print_processor_name = "winprint";
    3654           0 :         uint32_t num_procs, level = 1, i;
    3655             :         union spoolss_PrintProcDataTypesInfo *procs;
    3656             : 
    3657             :         /* Parse the command arguments */
    3658             : 
    3659           0 :         if (argc < 1 || argc > 4) {
    3660           0 :                 printf ("Usage: %s [environment] [level]\n", argv[0]);
    3661           0 :                 return WERR_OK;
    3662             :         }
    3663             : 
    3664           0 :         if (argc >= 2) {
    3665           0 :                 print_processor_name = argv[1];
    3666             :         }
    3667             : 
    3668           0 :         if (argc == 3) {
    3669           0 :                 level = atoi(argv[2]);
    3670             :         }
    3671             : 
    3672             :         /* Enumerate Print Processor Data Types */
    3673             : 
    3674           0 :         werror = rpccli_spoolss_enumprintprocessordatatypes(cli, mem_ctx,
    3675           0 :                                                             cli->srv_name_slash,
    3676             :                                                             print_processor_name,
    3677             :                                                             level,
    3678             :                                                             0,
    3679             :                                                             &num_procs,
    3680             :                                                             &procs);
    3681           0 :         if (!W_ERROR_IS_OK(werror))
    3682           0 :                 goto done;
    3683             : 
    3684             :         /* Display output */
    3685             : 
    3686           0 :         for (i = 0; i < num_procs; i++) {
    3687           0 :                 switch (level) {
    3688           0 :                 case 1:
    3689           0 :                         display_proc_data_types_info1(&procs[i].info1);
    3690           0 :                         break;
    3691             :                 }
    3692             :         }
    3693             : 
    3694           0 :  done:
    3695           0 :         return werror;
    3696             : }
    3697             : 
    3698           0 : static void display_monitor1(const struct spoolss_MonitorInfo1 *r)
    3699             : {
    3700           0 :         printf("monitor_name: %s\n", r->monitor_name);
    3701           0 : }
    3702             : 
    3703           0 : static void display_monitor2(const struct spoolss_MonitorInfo2 *r)
    3704             : {
    3705           0 :         printf("monitor_name: %s\n", r->monitor_name);
    3706           0 :         printf("environment: %s\n", r->environment);
    3707           0 :         printf("dll_name: %s\n", r->dll_name);
    3708           0 : }
    3709             : 
    3710           0 : static WERROR cmd_spoolss_enum_monitors(struct rpc_pipe_client *cli,
    3711             :                                         TALLOC_CTX *mem_ctx, int argc,
    3712             :                                         const char **argv)
    3713             : {
    3714             :         WERROR werror;
    3715           0 :         uint32_t count, level = 1, i;
    3716             :         union spoolss_MonitorInfo *info;
    3717             : 
    3718             :         /* Parse the command arguments */
    3719             : 
    3720           0 :         if (argc > 2) {
    3721           0 :                 printf("Usage: %s [level]\n", argv[0]);
    3722           0 :                 return WERR_OK;
    3723             :         }
    3724             : 
    3725           0 :         if (argc == 2) {
    3726           0 :                 level = atoi(argv[1]);
    3727             :         }
    3728             : 
    3729             :         /* Enumerate Print Monitors */
    3730             : 
    3731           0 :         werror = rpccli_spoolss_enummonitors(cli, mem_ctx,
    3732           0 :                                              cli->srv_name_slash,
    3733             :                                              level,
    3734             :                                              0,
    3735             :                                              &count,
    3736             :                                              &info);
    3737           0 :         if (!W_ERROR_IS_OK(werror)) {
    3738           0 :                 goto done;
    3739             :         }
    3740             : 
    3741             :         /* Display output */
    3742             : 
    3743           0 :         for (i = 0; i < count; i++) {
    3744           0 :                 switch (level) {
    3745           0 :                 case 1:
    3746           0 :                         display_monitor1(&info[i].info1);
    3747           0 :                         break;
    3748           0 :                 case 2:
    3749           0 :                         display_monitor2(&info[i].info2);
    3750           0 :                         break;
    3751             :                 }
    3752             :         }
    3753             : 
    3754           0 :  done:
    3755           0 :         return werror;
    3756             : }
    3757             : 
    3758           0 : static WERROR cmd_spoolss_create_printer_ic(struct rpc_pipe_client *cli,
    3759             :                                             TALLOC_CTX *mem_ctx, int argc,
    3760             :                                             const char **argv)
    3761             : {
    3762             :         WERROR result;
    3763             :         NTSTATUS status;
    3764             :         struct policy_handle handle, gdi_handle;
    3765             :         const char *printername;
    3766             :         struct spoolss_DevmodeContainer devmode_ctr;
    3767           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    3768             : 
    3769           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    3770             : 
    3771           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    3772             :                                                printername,
    3773             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    3774             :                                                &handle);
    3775           0 :         if (!W_ERROR_IS_OK(result)) {
    3776           0 :                 return result;
    3777             :         }
    3778             : 
    3779           0 :         ZERO_STRUCT(devmode_ctr);
    3780             : 
    3781           0 :         status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
    3782             :                                                 &handle,
    3783             :                                                 &gdi_handle,
    3784             :                                                 &devmode_ctr,
    3785             :                                                 &result);
    3786           0 :         if (!NT_STATUS_IS_OK(status)) {
    3787           0 :                 result = ntstatus_to_werror(status);
    3788           0 :                 goto done;
    3789             :         }
    3790           0 :         if (!W_ERROR_IS_OK(result)) {
    3791           0 :                 goto done;
    3792             :         }
    3793             : 
    3794           0 :  done:
    3795           0 :         if (is_valid_policy_hnd(&gdi_handle)) {
    3796             :                 WERROR _result;
    3797           0 :                 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
    3798             :         }
    3799           0 :         if (is_valid_policy_hnd(&handle)) {
    3800             :                 WERROR _result;
    3801           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
    3802             :         }
    3803             : 
    3804           0 :         return result;
    3805             : }
    3806             : 
    3807           0 : static WERROR cmd_spoolss_play_gdi_script_on_printer_ic(struct rpc_pipe_client *cli,
    3808             :                                                         TALLOC_CTX *mem_ctx, int argc,
    3809             :                                                         const char **argv)
    3810             : {
    3811             :         WERROR result;
    3812             :         NTSTATUS status;
    3813             :         struct policy_handle handle, gdi_handle;
    3814             :         const char *printername;
    3815             :         struct spoolss_DevmodeContainer devmode_ctr;
    3816           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    3817             :         DATA_BLOB in,out;
    3818           0 :         uint32_t count = 0;
    3819             : 
    3820           0 :         RPCCLIENT_PRINTERNAME(printername, cli, argv[1]);
    3821             : 
    3822           0 :         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
    3823             :                                                printername,
    3824             :                                                SEC_FLAG_MAXIMUM_ALLOWED,
    3825             :                                                &handle);
    3826           0 :         if (!W_ERROR_IS_OK(result)) {
    3827           0 :                 return result;
    3828             :         }
    3829             : 
    3830           0 :         ZERO_STRUCT(devmode_ctr);
    3831             : 
    3832           0 :         status = dcerpc_spoolss_CreatePrinterIC(b, mem_ctx,
    3833             :                                                 &handle,
    3834             :                                                 &gdi_handle,
    3835             :                                                 &devmode_ctr,
    3836             :                                                 &result);
    3837           0 :         if (!NT_STATUS_IS_OK(status)) {
    3838           0 :                 result = ntstatus_to_werror(status);
    3839           0 :                 goto done;
    3840             :         }
    3841           0 :         if (!W_ERROR_IS_OK(result)) {
    3842           0 :                 goto done;
    3843             :         }
    3844             : 
    3845           0 :         in = data_blob_string_const("");
    3846           0 :         out = data_blob_talloc_zero(mem_ctx, 4);
    3847             : 
    3848           0 :         status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
    3849             :                                                          &gdi_handle,
    3850             :                                                          in.data,
    3851           0 :                                                          in.length,
    3852             :                                                          out.data,
    3853           0 :                                                          out.length,
    3854             :                                                          0, /* ul */
    3855             :                                                          &result);
    3856           0 :         if (!NT_STATUS_IS_OK(status)) {
    3857           0 :                 result = ntstatus_to_werror(status);
    3858           0 :                 goto done;
    3859             :         }
    3860           0 :         if (!W_ERROR_IS_OK(result)) {
    3861           0 :                 goto done;
    3862             :         }
    3863             : 
    3864           0 :         count = IVAL(out.data, 0);
    3865             : 
    3866           0 :         out = data_blob_talloc_zero(mem_ctx,
    3867           0 :                                     count * sizeof(struct UNIVERSAL_FONT_ID) + 4);
    3868             : 
    3869           0 :         status = dcerpc_spoolss_PlayGDIScriptOnPrinterIC(b, mem_ctx,
    3870             :                                                          &gdi_handle,
    3871             :                                                          in.data,
    3872           0 :                                                          in.length,
    3873             :                                                          out.data,
    3874           0 :                                                          out.length,
    3875             :                                                          0, /* ul */
    3876             :                                                          &result);
    3877           0 :         if (!NT_STATUS_IS_OK(status)) {
    3878           0 :                 result = ntstatus_to_werror(status);
    3879           0 :                 goto done;
    3880             :         }
    3881           0 :         if (!W_ERROR_IS_OK(result)) {
    3882           0 :                 goto done;
    3883             :         }
    3884             : 
    3885             :         {
    3886             :                 enum ndr_err_code ndr_err;
    3887             :                 struct UNIVERSAL_FONT_ID_ctr r;
    3888             : 
    3889           0 :                 ndr_err = ndr_pull_struct_blob(&out, mem_ctx, &r,
    3890             :                         (ndr_pull_flags_fn_t)ndr_pull_UNIVERSAL_FONT_ID_ctr);
    3891           0 :                 if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    3892           0 :                         NDR_PRINT_DEBUG(UNIVERSAL_FONT_ID_ctr, &r);
    3893             :                 }
    3894             :         }
    3895             : 
    3896           0 :  done:
    3897           0 :         if (is_valid_policy_hnd(&gdi_handle)) {
    3898             :                 WERROR _result;
    3899           0 :                 dcerpc_spoolss_DeletePrinterIC(b, mem_ctx, &gdi_handle, &_result);
    3900             :         }
    3901           0 :         if (is_valid_policy_hnd(&handle)) {
    3902             :                 WERROR _result;
    3903           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &_result);
    3904             :         }
    3905             : 
    3906           0 :         return result;
    3907             : }
    3908             : 
    3909           0 : static WERROR cmd_spoolss_get_core_printer_drivers(struct rpc_pipe_client *cli,
    3910             :                                                    TALLOC_CTX *mem_ctx, int argc,
    3911             :                                                    const char **argv)
    3912             : {
    3913             :         NTSTATUS status;
    3914             :         HRESULT result;
    3915           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    3916           0 :         const char *architecture = SPOOLSS_ARCHITECTURE_x64;
    3917             :         struct spoolss_CorePrinterDriver core_printer_drivers;
    3918             :         DATA_BLOB blob;
    3919             :         bool ok;
    3920             :         int i;
    3921             :         uint32_t count;
    3922             :         const char **array;
    3923             : 
    3924           0 :         if (argc == 1) {
    3925           0 :                 count = 1;
    3926           0 :                 array = talloc_zero_array(mem_ctx, const char *, count + 1);
    3927           0 :                 if (array == NULL) {
    3928           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    3929             :                 }
    3930           0 :                 array[0] = talloc_strdup(array, SPOOLSS_CORE_PRINT_PACKAGE_FILES_XPSDRV);
    3931           0 :                 if (array[0] == NULL) {
    3932           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    3933             :                 }
    3934             :         } else {
    3935           0 :                 count = argc -1;
    3936           0 :                 array = talloc_zero_array(mem_ctx, const char *, count + 1);
    3937           0 :                 if (array == NULL) {
    3938           0 :                         return WERR_NOT_ENOUGH_MEMORY;
    3939             :                 }
    3940           0 :                 for (i = 0; i < argc - 1; i++) {
    3941           0 :                         array[i] = talloc_strdup(array, argv[i + 1]);
    3942           0 :                         if (array[i] == NULL) {
    3943           0 :                                 return WERR_NOT_ENOUGH_MEMORY;
    3944             :                         }
    3945             :                 }
    3946             :         }
    3947             : 
    3948           0 :         ok = push_reg_multi_sz(mem_ctx, &blob, array);
    3949           0 :         if (!ok) {
    3950           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    3951             :         }
    3952             : 
    3953           0 :         status = dcerpc_spoolss_GetCorePrinterDrivers(b, mem_ctx,
    3954           0 :                                                       cli->srv_name_slash,
    3955             :                                                       architecture,
    3956           0 :                                                       blob.length/2,
    3957           0 :                                                       (uint16_t *)blob.data,
    3958             :                                                       count,
    3959             :                                                       &core_printer_drivers,
    3960             :                                                       &result);
    3961           0 :         if (!NT_STATUS_IS_OK(status)) {
    3962           0 :                 return ntstatus_to_werror(status);
    3963             :         }
    3964             : 
    3965           0 :         if (!HRES_IS_OK(result)) {
    3966           0 :                 return W_ERROR(WIN32_FROM_HRESULT(result));
    3967             :         }
    3968             : 
    3969           0 :         return WERR_OK;
    3970             : }
    3971             : 
    3972           0 : static WERROR cmd_spoolss_enum_permachineconnections(struct rpc_pipe_client *cli,
    3973             :                                                      TALLOC_CTX *mem_ctx, int argc,
    3974             :                                                      const char **argv)
    3975             : {
    3976             :         NTSTATUS status;
    3977             :         WERROR result;
    3978           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    3979           0 :         const char *servername = cli->srv_name_slash;
    3980           0 :         DATA_BLOB in = data_blob_null;
    3981             :         struct spoolss_PrinterInfo4 *info;
    3982             :         uint32_t needed, count;
    3983             : 
    3984           0 :         if (argc > 2) {
    3985           0 :                 printf("usage: %s [servername]\n", argv[0]);
    3986           0 :                 return WERR_OK;
    3987             :         }
    3988             : 
    3989           0 :         if (argc > 1) {
    3990           0 :                 servername = argv[1];
    3991             :         }
    3992             : 
    3993           0 :         status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
    3994             :                                                           servername,
    3995             :                                                           &in,
    3996           0 :                                                           in.length,
    3997             :                                                           &count,
    3998             :                                                           &info,
    3999             :                                                           &needed,
    4000             :                                                           &result);
    4001           0 :         if (!NT_STATUS_IS_OK(status)) {
    4002           0 :                 return ntstatus_to_werror(status);
    4003             :         }
    4004             : 
    4005           0 :         if (W_ERROR_EQUAL(result, WERR_INSUFFICIENT_BUFFER)) {
    4006           0 :                 in = data_blob_talloc_zero(mem_ctx, needed);
    4007           0 :                 status = dcerpc_spoolss_EnumPerMachineConnections(b, mem_ctx,
    4008             :                                                                   servername,
    4009             :                                                                   &in,
    4010           0 :                                                                   in.length,
    4011             :                                                                   &count,
    4012             :                                                                   &info,
    4013             :                                                                   &needed,
    4014             :                                                                   &result);
    4015           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4016           0 :                         return ntstatus_to_werror(status);
    4017             :                 }
    4018             :         }
    4019             : 
    4020           0 :         return result;
    4021             : }
    4022             : 
    4023           0 : static WERROR cmd_spoolss_add_permachineconnection(struct rpc_pipe_client *cli,
    4024             :                                                    TALLOC_CTX *mem_ctx, int argc,
    4025             :                                                    const char **argv)
    4026             : {
    4027             :         NTSTATUS status;
    4028             :         WERROR result;
    4029           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    4030           0 :         const char *servername = cli->srv_name_slash;
    4031           0 :         const char *printername = "Microsoft Print to PDF";
    4032           0 :         const char *printserver = "samba.org";
    4033           0 :         const char *provider = ""; /* refers to Win32spl.dll then */
    4034             :         const char *composed_printername;
    4035             : 
    4036           0 :         if (argc > 5) {
    4037           0 :                 printf("usage: %s [servername] [printername] [printserver] [provider]\n", argv[0]);
    4038           0 :                 return WERR_OK;
    4039             :         }
    4040             : 
    4041           0 :         if (argc > 1) {
    4042           0 :                 servername = argv[1];
    4043             :         }
    4044           0 :         if (argc > 2) {
    4045           0 :                 printername = argv[2];
    4046             :         }
    4047           0 :         if (argc > 3) {
    4048           0 :                 printserver = argv[3];
    4049             :         }
    4050           0 :         if (argc > 4) {
    4051           0 :                 provider = argv[4];
    4052             :         }
    4053             : 
    4054           0 :         composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
    4055             :                         printername);
    4056           0 :         if (composed_printername == NULL) {
    4057           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4058             :         }
    4059           0 :         status = dcerpc_spoolss_AddPerMachineConnection(b, mem_ctx,
    4060             :                                                         servername,
    4061             :                                                         composed_printername,
    4062             :                                                         printserver,
    4063             :                                                         provider,
    4064             :                                                         &result);
    4065           0 :         if (!NT_STATUS_IS_OK(status)) {
    4066           0 :                 return ntstatus_to_werror(status);
    4067             :         }
    4068             : 
    4069           0 :         return result;
    4070             : }
    4071             : 
    4072           0 : static WERROR cmd_spoolss_del_permachineconnection(struct rpc_pipe_client *cli,
    4073             :                                                    TALLOC_CTX *mem_ctx, int argc,
    4074             :                                                    const char **argv)
    4075             : {
    4076             :         NTSTATUS status;
    4077             :         WERROR result;
    4078           0 :         struct dcerpc_binding_handle *b = cli->binding_handle;
    4079           0 :         const char *servername = cli->srv_name_slash;
    4080           0 :         const char *printername = "Microsoft Print to PDF";
    4081             :         const char *composed_printername;
    4082             : 
    4083           0 :         if (argc > 3) {
    4084           0 :                 printf("usage: %s [servername] [printername]\n", argv[0]);
    4085           0 :                 return WERR_OK;
    4086             :         }
    4087             : 
    4088           0 :         if (argc > 1) {
    4089           0 :                 servername = argv[1];
    4090             :         }
    4091           0 :         if (argc > 2) {
    4092           0 :                 printername = argv[2];
    4093             :         }
    4094             : 
    4095           0 :         composed_printername = talloc_asprintf(mem_ctx, "%s\\%s", servername,
    4096             :                         printername);
    4097           0 :         if (composed_printername == NULL) {
    4098           0 :                 return WERR_NOT_ENOUGH_MEMORY;
    4099             :         }
    4100             : 
    4101           0 :         status = dcerpc_spoolss_DeletePerMachineConnection(b, mem_ctx,
    4102             :                                                            servername,
    4103             :                                                            composed_printername,
    4104             :                                                            &result);
    4105           0 :         if (!NT_STATUS_IS_OK(status)) {
    4106           0 :                 return ntstatus_to_werror(status);
    4107             :         }
    4108             : 
    4109           0 :         return result;
    4110             : }
    4111             : 
    4112             : /* List of commands exported by this module */
    4113             : struct cmd_set spoolss_commands[] = {
    4114             : 
    4115             :         {
    4116             :                 .name = "SPOOLSS",
    4117             :         },
    4118             : 
    4119             :         {
    4120             :                 .name               = "adddriver",
    4121             :                 .returntype         = RPC_RTYPE_WERROR,
    4122             :                 .ntfn               = NULL,
    4123             :                 .wfn                = cmd_spoolss_addprinterdriver,
    4124             :                 .table              = &ndr_table_spoolss,
    4125             :                 .rpc_pipe           = NULL,
    4126             :                 .description        = "Add a print driver",
    4127             :                 .usage              = "",
    4128             :                 .use_netlogon_creds = false,
    4129             :         },
    4130             :         {
    4131             :                 .name               = "addprinter",
    4132             :                 .returntype         = RPC_RTYPE_WERROR,
    4133             :                 .ntfn               = NULL,
    4134             :                 .wfn                = cmd_spoolss_addprinterex,
    4135             :                 .table              = &ndr_table_spoolss,
    4136             :                 .rpc_pipe           = NULL,
    4137             :                 .description        = "Add a printer",
    4138             :                 .usage              = "",
    4139             :         },
    4140             :         {
    4141             :                 .name               = "deldriver",
    4142             :                 .returntype         = RPC_RTYPE_WERROR,
    4143             :                 .ntfn               = NULL,
    4144             :                 .wfn                = cmd_spoolss_deletedriver,
    4145             :                 .table              = &ndr_table_spoolss,
    4146             :                 .rpc_pipe           = NULL,
    4147             :                 .description        = "Delete a printer driver",
    4148             :                 .usage              = "",
    4149             :         },
    4150             :         {
    4151             :                 .name               = "deldriverex",
    4152             :                 .returntype         = RPC_RTYPE_WERROR,
    4153             :                 .ntfn               = NULL,
    4154             :                 .wfn                = cmd_spoolss_deletedriverex,
    4155             :                 .table              = &ndr_table_spoolss,
    4156             :                 .rpc_pipe           = NULL,
    4157             :                 .description        = "Delete a printer driver with files",
    4158             :                 .usage              = "",
    4159             :         },
    4160             :         {
    4161             :                 .name               = "enumdata",
    4162             :                 .returntype         = RPC_RTYPE_WERROR,
    4163             :                 .ntfn               = NULL,
    4164             :                 .wfn                = cmd_spoolss_enum_data,
    4165             :                 .table              = &ndr_table_spoolss,
    4166             :                 .rpc_pipe           = NULL,
    4167             :                 .description        = "Enumerate printer data",
    4168             :                 .usage              = "",
    4169             :         },
    4170             :         {
    4171             :                 .name               = "enumdataex",
    4172             :                 .returntype         = RPC_RTYPE_WERROR,
    4173             :                 .ntfn               = NULL,
    4174             :                 .wfn                = cmd_spoolss_enum_data_ex,
    4175             :                 .table              = &ndr_table_spoolss,
    4176             :                 .rpc_pipe           = NULL,
    4177             :                 .description        = "Enumerate printer data for a key",
    4178             :                 .usage              = "",
    4179             :         },
    4180             :         {
    4181             :                 .name               = "enumkey",
    4182             :                 .returntype         = RPC_RTYPE_WERROR,
    4183             :                 .ntfn               = NULL,
    4184             :                 .wfn                = cmd_spoolss_enum_printerkey,
    4185             :                 .table              = &ndr_table_spoolss,
    4186             :                 .rpc_pipe           = NULL,
    4187             :                 .description        = "Enumerate printer keys",
    4188             :                 .usage              = "",
    4189             :         },
    4190             :         {
    4191             :                 .name               = "enumjobs",
    4192             :                 .returntype         = RPC_RTYPE_WERROR,
    4193             :                 .ntfn               = NULL,
    4194             :                 .wfn                = cmd_spoolss_enum_jobs,
    4195             :                 .table              = &ndr_table_spoolss,
    4196             :                 .rpc_pipe           = NULL,
    4197             :                 .description        = "Enumerate print jobs",
    4198             :                 .usage              = "",
    4199             :         },
    4200             :         {
    4201             :                 .name               = "getjob",
    4202             :                 .returntype         = RPC_RTYPE_WERROR,
    4203             :                 .ntfn               = NULL,
    4204             :                 .wfn                = cmd_spoolss_get_job,
    4205             :                 .table              = &ndr_table_spoolss,
    4206             :                 .rpc_pipe           = NULL,
    4207             :                 .description        = "Get print job",
    4208             :                 .usage              = "",
    4209             :         },
    4210             :         {
    4211             :                 .name               = "setjob",
    4212             :                 .returntype         = RPC_RTYPE_WERROR,
    4213             :                 .ntfn               = NULL,
    4214             :                 .wfn                = cmd_spoolss_set_job,
    4215             :                 .table              = &ndr_table_spoolss,
    4216             :                 .rpc_pipe           = NULL,
    4217             :                 .description        = "Set print job",
    4218             :                 .usage              = "",
    4219             :         },
    4220             :         {
    4221             :                 .name               = "enumports",
    4222             :                 .returntype         = RPC_RTYPE_WERROR,
    4223             :                 .ntfn               = NULL,
    4224             :                 .wfn                = cmd_spoolss_enum_ports,
    4225             :                 .table              = &ndr_table_spoolss,
    4226             :                 .rpc_pipe           = NULL,
    4227             :                 .description        = "Enumerate printer ports",
    4228             :                 .usage              = "",
    4229             :         },
    4230             :         {
    4231             :                 .name               = "enumdrivers",
    4232             :                 .returntype         = RPC_RTYPE_WERROR,
    4233             :                 .ntfn               = NULL,
    4234             :                 .wfn                = cmd_spoolss_enum_drivers,
    4235             :                 .table              = &ndr_table_spoolss,
    4236             :                 .rpc_pipe           = NULL,
    4237             :                 .description        = "Enumerate installed printer drivers",
    4238             :                 .usage              = "",
    4239             :         },
    4240             :         {
    4241             :                 .name               = "enumprinters",
    4242             :                 .returntype         = RPC_RTYPE_WERROR,
    4243             :                 .ntfn               = NULL,
    4244             :                 .wfn                = cmd_spoolss_enum_printers,
    4245             :                 .table              = &ndr_table_spoolss,
    4246             :                 .rpc_pipe           = NULL,
    4247             :                 .description        = "Enumerate printers",
    4248             :                 .usage              = "",
    4249             :         },
    4250             :         {
    4251             :                 .name               = "getdata",
    4252             :                 .returntype         = RPC_RTYPE_WERROR,
    4253             :                 .ntfn               = NULL,
    4254             :                 .wfn                = cmd_spoolss_getprinterdata,
    4255             :                 .table              = &ndr_table_spoolss,
    4256             :                 .rpc_pipe           = NULL,
    4257             :                 .description        = "Get print driver data",
    4258             :                 .usage              = "",
    4259             :         },
    4260             :         {
    4261             :                 .name               = "getdataex",
    4262             :                 .returntype         = RPC_RTYPE_WERROR,
    4263             :                 .ntfn               = NULL,
    4264             :                 .wfn                = cmd_spoolss_getprinterdataex,
    4265             :                 .table              = &ndr_table_spoolss,
    4266             :                 .rpc_pipe           = NULL,
    4267             :                 .description        = "Get printer driver data with keyname",
    4268             :                 .usage              = "",
    4269             :         },
    4270             :         {
    4271             :                 .name               = "getdriver",
    4272             :                 .returntype         = RPC_RTYPE_WERROR,
    4273             :                 .ntfn               = NULL,
    4274             :                 .wfn                = cmd_spoolss_getdriver,
    4275             :                 .table              = &ndr_table_spoolss,
    4276             :                 .rpc_pipe           = NULL,
    4277             :                 .description        = "Get print driver information",
    4278             :                 .usage              = "",
    4279             :         },
    4280             :         {
    4281             :                 .name               = "getdriverdir",
    4282             :                 .returntype         = RPC_RTYPE_WERROR,
    4283             :                 .ntfn               = NULL,
    4284             :                 .wfn                = cmd_spoolss_getdriverdir,
    4285             :                 .table              = &ndr_table_spoolss,
    4286             :                 .rpc_pipe           = NULL,
    4287             :                 .description        = "Get print driver upload directory",
    4288             :                 .usage              = "",
    4289             :         },
    4290             :         {
    4291             :                 .name               = "getdriverpackagepath",
    4292             :                 .returntype         = RPC_RTYPE_WERROR,
    4293             :                 .ntfn               = NULL,
    4294             :                 .wfn                = cmd_spoolss_getdriverpackagepath,
    4295             :                 .table              = &ndr_table_spoolss,
    4296             :                 .rpc_pipe           = NULL,
    4297             :                 .description        = "Get print driver package download directory",
    4298             :                 .usage              = "",
    4299             :         },
    4300             :         {
    4301             :                 .name               = "getprinter",
    4302             :                 .returntype         = RPC_RTYPE_WERROR,
    4303             :                 .ntfn               = NULL,
    4304             :                 .wfn                = cmd_spoolss_getprinter,
    4305             :                 .table              = &ndr_table_spoolss,
    4306             :                 .rpc_pipe           = NULL,
    4307             :                 .description        = "Get printer info",
    4308             :                 .usage              = "",
    4309             :         },
    4310             :         {
    4311             :                 .name               = "openprinter",
    4312             :                 .returntype         = RPC_RTYPE_WERROR,
    4313             :                 .ntfn               = NULL,
    4314             :                 .wfn                = cmd_spoolss_open_printer,
    4315             :                 .table              = &ndr_table_spoolss,
    4316             :                 .rpc_pipe           = NULL,
    4317             :                 .description        = "Open printer handle",
    4318             :                 .usage              = "",
    4319             :         },
    4320             :         {
    4321             :                 .name               = "openprinter_ex",
    4322             :                 .returntype         = RPC_RTYPE_WERROR,
    4323             :                 .ntfn               = NULL,
    4324             :                 .wfn                = cmd_spoolss_open_printer_ex,
    4325             :                 .table              = &ndr_table_spoolss,
    4326             :                 .rpc_pipe           = NULL,
    4327             :                 .description        = "Open printer handle",
    4328             :                 .usage              = "",
    4329             :         },
    4330             :         {
    4331             :                 .name               = "setdriver",
    4332             :                 .returntype         = RPC_RTYPE_WERROR,
    4333             :                 .ntfn               = NULL,
    4334             :                 .wfn                = cmd_spoolss_setdriver,
    4335             :                 .table              = &ndr_table_spoolss,
    4336             :                 .rpc_pipe           = NULL,
    4337             :                 .description        = "Set printer driver",
    4338             :                 .usage              = "",
    4339             :         },
    4340             :         {
    4341             :                 .name               = "getprintprocdir",
    4342             :                 .returntype         = RPC_RTYPE_WERROR,
    4343             :                 .ntfn               = NULL,
    4344             :                 .wfn                = cmd_spoolss_getprintprocdir,
    4345             :                 .table              = &ndr_table_spoolss,
    4346             :                 .rpc_pipe           = NULL,
    4347             :                 .description        = "Get print processor directory",
    4348             :                 .usage              = "",
    4349             :         },
    4350             :         {
    4351             :                 .name               = "addform",
    4352             :                 .returntype         = RPC_RTYPE_WERROR,
    4353             :                 .ntfn               = NULL,
    4354             :                 .wfn                = cmd_spoolss_addform,
    4355             :                 .table              = &ndr_table_spoolss,
    4356             :                 .rpc_pipe           = NULL,
    4357             :                 .description        = "Add form",
    4358             :                 .usage              = "",
    4359             :         },
    4360             :         {
    4361             :                 .name               = "setform",
    4362             :                 .returntype         = RPC_RTYPE_WERROR,
    4363             :                 .ntfn               = NULL,
    4364             :                 .wfn                = cmd_spoolss_setform,
    4365             :                 .table              = &ndr_table_spoolss,
    4366             :                 .rpc_pipe           = NULL,
    4367             :                 .description        = "Set form",
    4368             :                 .usage              = "",
    4369             :         },
    4370             :         {
    4371             :                 .name               = "getform",
    4372             :                 .returntype         = RPC_RTYPE_WERROR,
    4373             :                 .ntfn               = NULL,
    4374             :                 .wfn                = cmd_spoolss_getform,
    4375             :                 .table              = &ndr_table_spoolss,
    4376             :                 .rpc_pipe           = NULL,
    4377             :                 .description        = "Get form",
    4378             :                 .usage              = "",
    4379             :         },
    4380             :         {
    4381             :                 .name               = "deleteform",
    4382             :                 .returntype         = RPC_RTYPE_WERROR,
    4383             :                 .ntfn               = NULL,
    4384             :                 .wfn                = cmd_spoolss_deleteform,
    4385             :                 .table              = &ndr_table_spoolss,
    4386             :                 .rpc_pipe           = NULL,
    4387             :                 .description        = "Delete form",
    4388             :                 .usage              = "",
    4389             :         },
    4390             :         {
    4391             :                 .name               = "enumforms",
    4392             :                 .returntype         = RPC_RTYPE_WERROR,
    4393             :                 .ntfn               = NULL,
    4394             :                 .wfn                = cmd_spoolss_enum_forms,
    4395             :                 .table              = &ndr_table_spoolss,
    4396             :                 .rpc_pipe           = NULL,
    4397             :                 .description        = "Enumerate forms",
    4398             :                 .usage              = "",
    4399             :         },
    4400             :         {
    4401             :                 .name               = "setprinter",
    4402             :                 .returntype         = RPC_RTYPE_WERROR,
    4403             :                 .ntfn               = NULL,
    4404             :                 .wfn                = cmd_spoolss_setprinter,
    4405             :                 .table              = &ndr_table_spoolss,
    4406             :                 .rpc_pipe           = NULL,
    4407             :                 .description        = "Set printer comment",
    4408             :                 .usage              = "",
    4409             :         },
    4410             :         {
    4411             :                 .name               = "setprintername",
    4412             :                 .returntype         = RPC_RTYPE_WERROR,
    4413             :                 .ntfn               = NULL,
    4414             :                 .wfn                = cmd_spoolss_setprintername,
    4415             :                 .table              = &ndr_table_spoolss,
    4416             :                 .rpc_pipe           = NULL,
    4417             :                 .description        = "Set printername",
    4418             :                 .usage              = "",
    4419             :         },
    4420             :         {
    4421             :                 .name               = "setprinterdata",
    4422             :                 .returntype         = RPC_RTYPE_WERROR,
    4423             :                 .ntfn               = NULL,
    4424             :                 .wfn                = cmd_spoolss_setprinterdata,
    4425             :                 .table              = &ndr_table_spoolss,
    4426             :                 .rpc_pipe           = NULL,
    4427             :                 .description        = "Set REG_SZ printer data",
    4428             :                 .usage              = "",
    4429             :         },
    4430             :         {
    4431             :                 .name               = "rffpcnex",
    4432             :                 .returntype         = RPC_RTYPE_WERROR,
    4433             :                 .ntfn               = NULL,
    4434             :                 .wfn                = cmd_spoolss_rffpcnex,
    4435             :                 .table              = &ndr_table_spoolss,
    4436             :                 .rpc_pipe           = NULL,
    4437             :                 .description        = "Rffpcnex test",
    4438             :                 .usage              = "",
    4439             :         },
    4440             :         {
    4441             :                 .name               = "printercmp",
    4442             :                 .returntype         = RPC_RTYPE_WERROR,
    4443             :                 .ntfn               = NULL,
    4444             :                 .wfn                = cmd_spoolss_printercmp,
    4445             :                 .table              = &ndr_table_spoolss,
    4446             :                 .rpc_pipe           = NULL,
    4447             :                 .description        = "Printer comparison test",
    4448             :                 .usage              = "",
    4449             :         },
    4450             :         {
    4451             :                 .name               = "enumprocs",
    4452             :                 .returntype         = RPC_RTYPE_WERROR,
    4453             :                 .ntfn               = NULL,
    4454             :                 .wfn                = cmd_spoolss_enum_procs,
    4455             :                 .table              = &ndr_table_spoolss,
    4456             :                 .rpc_pipe           = NULL,
    4457             :                 .description        = "Enumerate Print Processors",
    4458             :                 .usage              = "",
    4459             :         },
    4460             :         {
    4461             :                 .name               = "enumprocdatatypes",
    4462             :                 .returntype         = RPC_RTYPE_WERROR,
    4463             :                 .ntfn               = NULL,
    4464             :                 .wfn                = cmd_spoolss_enum_proc_data_types,
    4465             :                 .table              = &ndr_table_spoolss,
    4466             :                 .rpc_pipe           = NULL,
    4467             :                 .description        = "Enumerate Print Processor Data Types",
    4468             :                 .usage              = "",
    4469             :         },
    4470             :         {
    4471             :                 .name               = "enummonitors",
    4472             :                 .returntype         = RPC_RTYPE_WERROR,
    4473             :                 .ntfn               = NULL,
    4474             :                 .wfn                = cmd_spoolss_enum_monitors,
    4475             :                 .table              = &ndr_table_spoolss,
    4476             :                 .rpc_pipe           = NULL,
    4477             :                 .description        = "Enumerate Print Monitors",
    4478             :                 .usage              = "",
    4479             :         },
    4480             :         {
    4481             :                 .name               = "createprinteric",
    4482             :                 .returntype         = RPC_RTYPE_WERROR,
    4483             :                 .ntfn               = NULL,
    4484             :                 .wfn                = cmd_spoolss_create_printer_ic,
    4485             :                 .table              = &ndr_table_spoolss,
    4486             :                 .rpc_pipe           = NULL,
    4487             :                 .description        = "Create Printer IC",
    4488             :                 .usage              = "",
    4489             :         },
    4490             :         {
    4491             :                 .name               = "playgdiscriptonprinteric",
    4492             :                 .returntype         = RPC_RTYPE_WERROR,
    4493             :                 .ntfn               = NULL,
    4494             :                 .wfn                = cmd_spoolss_play_gdi_script_on_printer_ic,
    4495             :                 .table              = &ndr_table_spoolss,
    4496             :                 .rpc_pipe           = NULL,
    4497             :                 .description        = "Create Printer IC",
    4498             :                 .usage              = "",
    4499             :         },
    4500             :         {
    4501             :                 .name               = "getcoreprinterdrivers",
    4502             :                 .returntype         = RPC_RTYPE_WERROR,
    4503             :                 .ntfn               = NULL,
    4504             :                 .wfn                = cmd_spoolss_get_core_printer_drivers,
    4505             :                 .table              = &ndr_table_spoolss,
    4506             :                 .rpc_pipe           = NULL,
    4507             :                 .description        = "Get CorePrinterDriver",
    4508             :                 .usage              = "",
    4509             :         },
    4510             :         {
    4511             :                 .name               = "enumpermachineconnections",
    4512             :                 .returntype         = RPC_RTYPE_WERROR,
    4513             :                 .ntfn               = NULL,
    4514             :                 .wfn                = cmd_spoolss_enum_permachineconnections,
    4515             :                 .table              = &ndr_table_spoolss,
    4516             :                 .rpc_pipe           = NULL,
    4517             :                 .description        = "Enumerate Per Machine Connections",
    4518             :                 .usage              = "",
    4519             :         },
    4520             :         {
    4521             :                 .name               = "addpermachineconnection",
    4522             :                 .returntype         = RPC_RTYPE_WERROR,
    4523             :                 .ntfn               = NULL,
    4524             :                 .wfn                = cmd_spoolss_add_permachineconnection,
    4525             :                 .table              = &ndr_table_spoolss,
    4526             :                 .rpc_pipe           = NULL,
    4527             :                 .description        = "Add Per Machine Connection",
    4528             :                 .usage              = "",
    4529             :         },
    4530             :         {
    4531             :                 .name               = "delpermachineconnection",
    4532             :                 .returntype         = RPC_RTYPE_WERROR,
    4533             :                 .ntfn               = NULL,
    4534             :                 .wfn                = cmd_spoolss_del_permachineconnection,
    4535             :                 .table              = &ndr_table_spoolss,
    4536             :                 .rpc_pipe           = NULL,
    4537             :                 .description        = "Delete Per Machine Connection",
    4538             :                 .usage              = "",
    4539             :         },
    4540             :         {
    4541             :                 .name = NULL,
    4542             :         },
    4543             : };

Generated by: LCOV version 1.14