rpcclient/cmd_spoolss.c

説明を見る。
00001 /*
00002    Unix SMB/CIFS implementation.
00003    RPC pipe client
00004 
00005    Copyright (C) Gerald Carter                2001-2005
00006    Copyright (C) Tim Potter                        2000
00007    Copyright (C) Andrew Tridgell              1992-1999
00008    Copyright (C) Luke Kenneth Casson Leighton 1996-1999
00009  
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014    
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019    
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00023 */
00024 
00025 #include "includes.h"
00026 #include "rpcclient.h"
00027 
00028 struct table_node {
00029         const char      *long_archi;
00030         const char      *short_archi;
00031         int     version;
00032 };
00033  
00034 /* The version int is used by getdrivers.  Note that
00035    all architecture strings that support mutliple
00036    versions must be grouped together since enumdrivers
00037    uses this property to prevent issuing multiple 
00038    enumdriver calls for the same arch */
00039 
00040 
00041 static const struct table_node archi_table[]= {
00042 
00043         {"Windows 4.0",          "WIN40",       0 },
00044         {"Windows NT x86",       "W32X86",      2 },
00045         {"Windows NT x86",       "W32X86",      3 },
00046         {"Windows NT R4000",     "W32MIPS",     2 },
00047         {"Windows NT Alpha_AXP", "W32ALPHA",    2 },
00048         {"Windows NT PowerPC",   "W32PPC",      2 },
00049         {"Windows IA64",         "IA64",        3 },
00050         {"Windows x64",          "x64",         3 },
00051         {NULL,                   "",            -1 }
00052 };
00053 
00054 /**
00055  * @file
00056  *
00057  * rpcclient module for SPOOLSS rpc pipe.
00058  *
00059  * This generally just parses and checks command lines, and then calls
00060  * a cli_spoolss function.
00061  **/
00062 
00063 /****************************************************************************
00064  function to do the mapping between the long architecture name and
00065  the short one.
00066 ****************************************************************************/
00067 
00068 static const char *cmd_spoolss_get_short_archi(const char *long_archi)
00069 {
00070         int i=-1;
00071 
00072         DEBUG(107,("Getting architecture dependant directory\n"));
00073         do {
00074                 i++;
00075         } while ( (archi_table[i].long_archi!=NULL ) &&
00076                   StrCaseCmp(long_archi, archi_table[i].long_archi) );
00077 
00078         if (archi_table[i].long_archi==NULL) {
00079                 DEBUGADD(10,("Unknown architecture [%s] !\n", long_archi));
00080                 return NULL;
00081         }
00082 
00083         /* this might be client code - but shouldn't this be an fstrcpy etc? */
00084 
00085 
00086         DEBUGADD(108,("index: [%d]\n", i));
00087         DEBUGADD(108,("long architecture: [%s]\n", archi_table[i].long_archi));
00088         DEBUGADD(108,("short architecture: [%s]\n", archi_table[i].short_archi));
00089 
00090         return archi_table[i].short_archi;
00091 }
00092 
00093 /****************************************************************************
00094 ****************************************************************************/
00095 
00096 static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli, 
00097                                             TALLOC_CTX *mem_ctx,
00098                                             int argc, const char **argv)
00099 {
00100         WERROR          werror;
00101         fstring         printername;
00102         fstring         servername, user;
00103         POLICY_HND      hnd;
00104         
00105         if (argc != 2) {
00106                 printf("Usage: %s <printername>\n", argv[0]);
00107                 return WERR_OK;
00108         }
00109         
00110         if (!cli)
00111             return WERR_GENERAL_FAILURE;
00112 
00113         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
00114         strupper_m(servername);
00115         fstrcpy(user, cli->user_name);
00116         fstrcpy(printername, argv[1]);
00117 
00118         /* Open the printer handle */
00119 
00120         werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
00121                                              "", PRINTER_ALL_ACCESS, 
00122                                              servername, user, &hnd);
00123 
00124         if (W_ERROR_IS_OK(werror)) {
00125                 printf("Printer %s opened successfully\n", printername);
00126                 werror = rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
00127 
00128                 if (!W_ERROR_IS_OK(werror)) {
00129                         printf("Error closing printer handle! (%s)\n", 
00130                                 get_dos_error_msg(werror));
00131                 }
00132         }
00133 
00134         return werror;
00135 }
00136 
00137 
00138 /****************************************************************************
00139 ****************************************************************************/
00140 
00141 static void display_print_info_0(PRINTER_INFO_0 *i0)
00142 {
00143         fstring name = "";
00144         fstring servername = "";
00145 
00146         if (!i0)
00147                 return;
00148 
00149         rpcstr_pull(name, i0->printername.buffer, sizeof(name), -1, STR_TERMINATE);
00150 
00151         rpcstr_pull(servername, i0->servername.buffer, sizeof(servername), -1,STR_TERMINATE);
00152   
00153         printf("\tprintername:[%s]\n", name);
00154         printf("\tservername:[%s]\n", servername);
00155         printf("\tcjobs:[0x%x]\n", i0->cjobs);
00156         printf("\ttotal_jobs:[0x%x]\n", i0->total_jobs);
00157         
00158         printf("\t:date: [%d]-[%d]-[%d] (%d)\n", i0->year, i0->month, 
00159                i0->day, i0->dayofweek);
00160         printf("\t:time: [%d]-[%d]-[%d]-[%d]\n", i0->hour, i0->minute, 
00161                i0->second, i0->milliseconds);
00162         
00163         printf("\tglobal_counter:[0x%x]\n", i0->global_counter);
00164         printf("\ttotal_pages:[0x%x]\n", i0->total_pages);
00165         
00166         printf("\tmajorversion:[0x%x]\n", i0->major_version);
00167         printf("\tbuildversion:[0x%x]\n", i0->build_version);
00168         
00169         printf("\tunknown7:[0x%x]\n", i0->unknown7);
00170         printf("\tunknown8:[0x%x]\n", i0->unknown8);
00171         printf("\tunknown9:[0x%x]\n", i0->unknown9);
00172         printf("\tsession_counter:[0x%x]\n", i0->session_counter);
00173         printf("\tunknown11:[0x%x]\n", i0->unknown11);
00174         printf("\tprinter_errors:[0x%x]\n", i0->printer_errors);
00175         printf("\tunknown13:[0x%x]\n", i0->unknown13);
00176         printf("\tunknown14:[0x%x]\n", i0->unknown14);
00177         printf("\tunknown15:[0x%x]\n", i0->unknown15);
00178         printf("\tunknown16:[0x%x]\n", i0->unknown16);
00179         printf("\tchange_id:[0x%x]\n", i0->change_id);
00180         printf("\tunknown18:[0x%x]\n", i0->unknown18);
00181         printf("\tstatus:[0x%x]\n", i0->status);
00182         printf("\tunknown20:[0x%x]\n", i0->unknown20);
00183         printf("\tc_setprinter:[0x%x]\n", i0->c_setprinter);
00184         printf("\tunknown22:[0x%x]\n", i0->unknown22);
00185         printf("\tunknown23:[0x%x]\n", i0->unknown23);
00186         printf("\tunknown24:[0x%x]\n", i0->unknown24);
00187         printf("\tunknown25:[0x%x]\n", i0->unknown25);
00188         printf("\tunknown26:[0x%x]\n", i0->unknown26);
00189         printf("\tunknown27:[0x%x]\n", i0->unknown27);
00190         printf("\tunknown28:[0x%x]\n", i0->unknown28);
00191         printf("\tunknown29:[0x%x]\n", i0->unknown29);
00192 
00193         printf("\n");
00194 }
00195 
00196 /****************************************************************************
00197 ****************************************************************************/
00198 
00199 static void display_print_info_1(PRINTER_INFO_1 *i1)
00200 {
00201         fstring desc = "";
00202         fstring name = "";
00203         fstring comm = "";
00204 
00205         rpcstr_pull(desc, i1->description.buffer, sizeof(desc), -1,
00206                     STR_TERMINATE);
00207 
00208         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
00209         rpcstr_pull(comm, i1->comment.buffer, sizeof(comm), -1, STR_TERMINATE);
00210 
00211         printf("\tflags:[0x%x]\n", i1->flags);
00212         printf("\tname:[%s]\n", name);
00213         printf("\tdescription:[%s]\n", desc);
00214         printf("\tcomment:[%s]\n", comm);
00215 
00216         printf("\n");
00217 }
00218 
00219 /****************************************************************************
00220 ****************************************************************************/
00221 
00222 static void display_print_info_2(PRINTER_INFO_2 *i2)
00223 {
00224         fstring servername = "";
00225         fstring printername = "";
00226         fstring sharename = "";
00227         fstring portname = "";
00228         fstring drivername = "";
00229         fstring comment = "";
00230         fstring location = "";
00231         fstring sepfile = "";
00232         fstring printprocessor = "";
00233         fstring datatype = "";
00234         fstring parameters = "";
00235         
00236         rpcstr_pull(servername, i2->servername.buffer,sizeof(servername), -1, STR_TERMINATE);
00237         rpcstr_pull(printername, i2->printername.buffer,sizeof(printername), -1, STR_TERMINATE);
00238         rpcstr_pull(sharename, i2->sharename.buffer,sizeof(sharename), -1, STR_TERMINATE);
00239         rpcstr_pull(portname, i2->portname.buffer,sizeof(portname), -1, STR_TERMINATE);
00240         rpcstr_pull(drivername, i2->drivername.buffer,sizeof(drivername), -1, STR_TERMINATE);
00241         rpcstr_pull(comment, i2->comment.buffer,sizeof(comment), -1, STR_TERMINATE);
00242         rpcstr_pull(location, i2->location.buffer,sizeof(location), -1, STR_TERMINATE);
00243         rpcstr_pull(sepfile, i2->sepfile.buffer,sizeof(sepfile), -1, STR_TERMINATE);
00244         rpcstr_pull(printprocessor, i2->printprocessor.buffer,sizeof(printprocessor), -1, STR_TERMINATE);
00245         rpcstr_pull(datatype, i2->datatype.buffer,sizeof(datatype), -1, STR_TERMINATE);
00246         rpcstr_pull(parameters, i2->parameters.buffer,sizeof(parameters), -1, STR_TERMINATE);
00247 
00248         printf("\tservername:[%s]\n", servername);
00249         printf("\tprintername:[%s]\n", printername);
00250         printf("\tsharename:[%s]\n", sharename);
00251         printf("\tportname:[%s]\n", portname);
00252         printf("\tdrivername:[%s]\n", drivername);
00253         printf("\tcomment:[%s]\n", comment);
00254         printf("\tlocation:[%s]\n", location);
00255         printf("\tsepfile:[%s]\n", sepfile);
00256         printf("\tprintprocessor:[%s]\n", printprocessor);
00257         printf("\tdatatype:[%s]\n", datatype);
00258         printf("\tparameters:[%s]\n", parameters);
00259         printf("\tattributes:[0x%x]\n", i2->attributes);
00260         printf("\tpriority:[0x%x]\n", i2->priority);
00261         printf("\tdefaultpriority:[0x%x]\n", i2->defaultpriority);
00262         printf("\tstarttime:[0x%x]\n", i2->starttime);
00263         printf("\tuntiltime:[0x%x]\n", i2->untiltime);
00264         printf("\tstatus:[0x%x]\n", i2->status);
00265         printf("\tcjobs:[0x%x]\n", i2->cjobs);
00266         printf("\taverageppm:[0x%x]\n", i2->averageppm);
00267 
00268         if (i2->secdesc) 
00269                 display_sec_desc(i2->secdesc);
00270 
00271         printf("\n");
00272 }
00273 
00274 /****************************************************************************
00275 ****************************************************************************/
00276 
00277 static void display_print_info_3(PRINTER_INFO_3 *i3)
00278 {
00279         display_sec_desc(i3->secdesc);
00280 
00281         printf("\n");
00282 }
00283 
00284 /****************************************************************************
00285 ****************************************************************************/
00286 
00287 static void display_print_info_7(PRINTER_INFO_7 *i7)
00288 {
00289         fstring guid = "";
00290         rpcstr_pull(guid, i7->guid.buffer,sizeof(guid), -1, STR_TERMINATE);
00291         printf("\tguid:[%s]\n", guid);
00292         printf("\taction:[0x%x]\n", i7->action);
00293 }
00294 
00295 
00296 /****************************************************************************
00297 ****************************************************************************/
00298 
00299 static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli, 
00300                                           TALLOC_CTX *mem_ctx,
00301                                           int argc, const char **argv)
00302 {
00303         WERROR                  result;
00304         uint32                  info_level = 1;
00305         PRINTER_INFO_CTR        ctr;
00306         uint32                  i = 0, num_printers;
00307         fstring name;
00308 
00309         if (argc > 3) 
00310         {
00311                 printf("Usage: %s [level] [name]\n", argv[0]);
00312                 return WERR_OK;
00313         }
00314 
00315         if (argc >= 2)
00316                 info_level = atoi(argv[1]);
00317 
00318         if (argc == 3)
00319                 fstrcpy(name, argv[2]);
00320         else {
00321                 slprintf(name, sizeof(name)-1, "\\\\%s", cli->cli->desthost);
00322                 strupper_m(name);
00323         }
00324 
00325         ZERO_STRUCT(ctr);
00326 
00327         result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL, 
00328                 info_level, &num_printers, &ctr);
00329 
00330         if (W_ERROR_IS_OK(result)) {
00331 
00332                 if (!num_printers) {
00333                         printf ("No printers returned.\n");
00334                         goto done;
00335                 }
00336         
00337                 for (i = 0; i < num_printers; i++) {
00338                         switch(info_level) {
00339                         case 0:
00340                                 display_print_info_0(&ctr.printers_0[i]);
00341                                 break;
00342                         case 1:
00343                                 display_print_info_1(&ctr.printers_1[i]);
00344                                 break;
00345                         case 2:
00346                                 display_print_info_2(&ctr.printers_2[i]);
00347                                 break;
00348                         case 3:
00349                                 display_print_info_3(&ctr.printers_3[i]);
00350                                 break;
00351                         default:
00352                                 printf("unknown info level %d\n", info_level);
00353                                 goto done;
00354                         }
00355                 }
00356         }
00357         done:
00358 
00359         return result;
00360 }
00361 
00362 /****************************************************************************
00363 ****************************************************************************/
00364 
00365 static void display_port_info_1(PORT_INFO_1 *i1)
00366 {
00367         fstring buffer;
00368         
00369         rpcstr_pull(buffer, i1->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
00370         printf("\tPort Name:\t[%s]\n", buffer);
00371 }
00372 
00373 /****************************************************************************
00374 ****************************************************************************/
00375 
00376 static void display_port_info_2(PORT_INFO_2 *i2)
00377 {
00378         fstring buffer;
00379         
00380         rpcstr_pull(buffer, i2->port_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
00381         printf("\tPort Name:\t[%s]\n", buffer);
00382         rpcstr_pull(buffer, i2->monitor_name.buffer, sizeof(buffer), -1, STR_TERMINATE);
00383 
00384         printf("\tMonitor Name:\t[%s]\n", buffer);
00385         rpcstr_pull(buffer, i2->description.buffer, sizeof(buffer), -1, STR_TERMINATE);
00386 
00387         printf("\tDescription:\t[%s]\n", buffer);
00388         printf("\tPort Type:\t" );
00389         if ( i2->port_type ) {
00390                 int comma = 0; /* hack */
00391                 printf( "[" );
00392                 if ( i2->port_type & PORT_TYPE_READ ) {
00393                         printf( "Read" );
00394                         comma = 1;
00395                 }
00396                 if ( i2->port_type & PORT_TYPE_WRITE ) {
00397                         printf( "%sWrite", comma ? ", " : "" );
00398                         comma = 1;
00399                 }
00400                 /* These two have slightly different interpretations
00401                  on 95/98/ME but I'm disregarding that for now */
00402                 if ( i2->port_type & PORT_TYPE_REDIRECTED ) {
00403                         printf( "%sRedirected", comma ? ", " : "" );
00404                         comma = 1;
00405                 }
00406                 if ( i2->port_type & PORT_TYPE_NET_ATTACHED ) {
00407                         printf( "%sNet-Attached", comma ? ", " : "" );
00408                 }
00409                 printf( "]\n" );
00410         } else {
00411                 printf( "[Unset]\n" );
00412         }
00413         printf("\tReserved:\t[%d]\n", i2->reserved);
00414         printf("\n");
00415 }
00416 
00417 /****************************************************************************
00418 ****************************************************************************/
00419 
00420 static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli, 
00421                                        TALLOC_CTX *mem_ctx, int argc, 
00422                                        const char **argv)
00423 {
00424         WERROR                  result;
00425         uint32                  info_level = 1;
00426         PORT_INFO_CTR           ctr;
00427         uint32                  returned;
00428         
00429         if (argc > 2) {
00430                 printf("Usage: %s [level]\n", argv[0]);
00431                 return WERR_OK;
00432         }
00433         
00434         if (argc == 2)
00435                 info_level = atoi(argv[1]);
00436 
00437         /* Enumerate ports */
00438 
00439         ZERO_STRUCT(ctr);
00440 
00441         result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr);
00442 
00443         if (W_ERROR_IS_OK(result)) {
00444                 int i;
00445 
00446                 for (i = 0; i < returned; i++) {
00447                         switch (info_level) {
00448                         case 1:
00449                                 display_port_info_1(&ctr.port.info_1[i]);
00450                                 break;
00451                         case 2:
00452                                 display_port_info_2(&ctr.port.info_2[i]);
00453                                 break;
00454                         default:
00455                                 printf("unknown info level %d\n", info_level);
00456                                 break;
00457                         }
00458                 }
00459         }
00460         
00461         return result;
00462 }
00463 
00464 /****************************************************************************
00465 ****************************************************************************/
00466 
00467 static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli,
00468                                        TALLOC_CTX *mem_ctx,
00469                                        int argc, const char **argv)
00470 {
00471         POLICY_HND      pol;
00472         WERROR          result;
00473         uint32          info_level = 2;
00474         BOOL            opened_hnd = False;
00475         PRINTER_INFO_CTR ctr;
00476         fstring         printername,
00477                         servername,
00478                         user,
00479                         comment;
00480 
00481         if (argc == 1 || argc > 3) {
00482                 printf("Usage: %s printername comment\n", argv[0]);
00483 
00484                 return WERR_OK;
00485         }
00486 
00487         /* Open a printer handle */
00488         if (argc == 3) {
00489                 fstrcpy(comment, argv[2]);
00490         }
00491 
00492         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
00493         strupper_m(servername);
00494         slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
00495         fstrcpy(user, cli->user_name);
00496 
00497         /* get a printer handle */
00498         result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
00499                                 PRINTER_ALL_ACCESS, servername,
00500                                 user, &pol);
00501                                 
00502         if (!W_ERROR_IS_OK(result))
00503                 goto done;
00504 
00505         opened_hnd = True;
00506 
00507         /* Get printer info */
00508         result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
00509 
00510         if (!W_ERROR_IS_OK(result))
00511                 goto done;
00512 
00513 
00514         /* Modify the comment. */
00515         init_unistr(&ctr.printers_2->comment, comment);
00516         ctr.printers_2->devmode = NULL;
00517         ctr.printers_2->secdesc = NULL;
00518 
00519         result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
00520         if (W_ERROR_IS_OK(result))
00521                 printf("Success in setting comment.\n");
00522 
00523  done:
00524         if (opened_hnd)
00525                 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
00526 
00527         return result;
00528 }
00529 
00530 /****************************************************************************
00531 ****************************************************************************/
00532 
00533 static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli,
00534                                        TALLOC_CTX *mem_ctx,
00535                                        int argc, const char **argv)
00536 {
00537         POLICY_HND      pol;
00538         WERROR          result;
00539         uint32          info_level = 2;
00540         BOOL            opened_hnd = False;
00541         PRINTER_INFO_CTR ctr;
00542         fstring         printername,
00543                         servername,
00544                         user,
00545                         new_printername;
00546 
00547         if (argc == 1 || argc > 3) {
00548                 printf("Usage: %s printername new_printername\n", argv[0]);
00549 
00550                 return WERR_OK;
00551         }
00552 
00553         /* Open a printer handle */
00554         if (argc == 3) {
00555                 fstrcpy(new_printername, argv[2]);
00556         }
00557 
00558         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
00559         strupper_m(servername);
00560         slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
00561         fstrcpy(user, cli->user_name);
00562 
00563         /* get a printer handle */
00564         result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
00565                                 PRINTER_ALL_ACCESS, servername,
00566                                 user, &pol);
00567                                 
00568         if (!W_ERROR_IS_OK(result))
00569                 goto done;
00570 
00571         opened_hnd = True;
00572 
00573         /* Get printer info */
00574         result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
00575 
00576         if (!W_ERROR_IS_OK(result))
00577                 goto done;
00578 
00579         /* Modify the printername. */
00580         init_unistr(&ctr.printers_2->printername, new_printername);
00581         ctr.printers_2->devmode = NULL;
00582         ctr.printers_2->secdesc = NULL;
00583 
00584         result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0);
00585         if (W_ERROR_IS_OK(result))
00586                 printf("Success in setting printername.\n");
00587 
00588  done:
00589         if (opened_hnd)
00590                 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
00591 
00592         return result;
00593 }
00594 
00595 /****************************************************************************
00596 ****************************************************************************/
00597 
00598 static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli,
00599                                        TALLOC_CTX *mem_ctx,
00600                                        int argc, const char **argv)
00601 {
00602         POLICY_HND      pol;
00603         WERROR          result;
00604         uint32          info_level = 1;
00605         BOOL            opened_hnd = False;
00606         PRINTER_INFO_CTR ctr;
00607         fstring         printername,
00608                         servername,
00609                         user;
00610 
00611         if (argc == 1 || argc > 3) {
00612                 printf("Usage: %s <printername> [level]\n", argv[0]);
00613                 return WERR_OK;
00614         }
00615 
00616         /* Open a printer handle */
00617         if (argc == 3) {
00618                 info_level = atoi(argv[2]);
00619         }
00620 
00621         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
00622         strupper_m(servername);
00623         slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
00624         fstrcpy(user, cli->user_name);
00625         
00626         /* get a printer handle */
00627 
00628         result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
00629                                              "", MAXIMUM_ALLOWED_ACCESS, 
00630                                              servername, user, &pol);
00631 
00632         if (!W_ERROR_IS_OK(result))
00633                 goto done;
00634  
00635         opened_hnd = True;
00636 
00637         /* Get printer info */
00638 
00639         result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr);
00640 
00641         if (!W_ERROR_IS_OK(result))
00642                 goto done;
00643 
00644         /* Display printer info */
00645 
00646         switch (info_level) {
00647         case 0: 
00648                 display_print_info_0(ctr.printers_0);
00649                 break;
00650         case 1:
00651                 display_print_info_1(ctr.printers_1);
00652                 break;
00653         case 2:
00654                 display_print_info_2(ctr.printers_2);
00655                 break;
00656         case 3:
00657                 display_print_info_3(ctr.printers_3);
00658                 break;
00659         case 7:
00660                 display_print_info_7(ctr.printers_7);
00661                 break;
00662         default:
00663                 printf("unknown info level %d\n", info_level);
00664                 break;
00665         }
00666 
00667  done: 
00668         if (opened_hnd) 
00669                 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
00670 
00671         return result;
00672 }
00673 
00674 /****************************************************************************
00675 ****************************************************************************/
00676 
00677 static void display_reg_value(REGISTRY_VALUE value)
00678 {
00679         pstring text;
00680 
00681         switch(value.type) {
00682         case REG_DWORD:
00683                 printf("%s: REG_DWORD: 0x%08x\n", value.valuename, 
00684                        *((uint32 *) value.data_p));
00685                 break;
00686         case REG_SZ:
00687                 rpcstr_pull(text, value.data_p, sizeof(text), value.size,
00688                             STR_TERMINATE);
00689                 printf("%s: REG_SZ: %s\n", value.valuename, text);
00690                 break;
00691         case REG_BINARY: {
00692                 char *hex = hex_encode(NULL, value.data_p, value.size);
00693                 size_t i, len;
00694                 printf("%s: REG_BINARY:", value.valuename);
00695                 len = strlen(hex);
00696                 for (i=0; i<len; i++) {
00697                         if (hex[i] == '\0') {
00698                                 break;
00699                         }
00700                         if (i%40 == 0) {
00701                                 putchar('\n');
00702                         }
00703                         putchar(hex[i]);
00704                 }
00705                 TALLOC_FREE(hex);
00706                 putchar('\n');
00707                 break;
00708         }
00709         case REG_MULTI_SZ: {
00710                 uint16 *curstr = (uint16 *) value.data_p;
00711                 uint8 *start = value.data_p;
00712                 printf("%s: REG_MULTI_SZ:\n", value.valuename);
00713                 while (((uint8 *) curstr < start + value.size)) {
00714                         rpcstr_pull(text, curstr, sizeof(text), -1, 
00715                                     STR_TERMINATE);
00716                         printf("  %s\n", *text != 0 ? text : "NULL");
00717                         curstr += strlen(text) + 1;
00718                 }
00719         }
00720         break;
00721         default:
00722                 printf("%s: unknown type %d\n", value.valuename, value.type);
00723         }
00724         
00725 }
00726 
00727 /****************************************************************************
00728 ****************************************************************************/
00729 
00730 static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli,
00731                                            TALLOC_CTX *mem_ctx,
00732                                            int argc, const char **argv)
00733 {
00734         POLICY_HND      pol;
00735         WERROR          result;
00736         BOOL            opened_hnd = False;
00737         fstring         printername,
00738                         servername,
00739                         user;
00740         const char *valuename;
00741         REGISTRY_VALUE value;
00742 
00743         if (argc != 3) {
00744                 printf("Usage: %s <printername> <valuename>\n", argv[0]);
00745                 printf("<printername> of . queries print server\n");
00746                 return WERR_OK;
00747         }
00748         valuename = argv[2];
00749 
00750         /* Open a printer handle */
00751 
00752         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
00753         strupper_m(servername);
00754         if (strncmp(argv[1], ".", sizeof(".")) == 0)
00755                 fstrcpy(printername, servername);
00756         else
00757                 slprintf(printername, sizeof(servername)-1, "%s\\%s", 
00758                           servername, argv[1]);
00759         fstrcpy(user, cli->user_name);
00760         
00761         /* get a printer handle */
00762 
00763         result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
00764                                              "", MAXIMUM_ALLOWED_ACCESS, 
00765                                              servername, user, &pol);
00766 
00767         if (!W_ERROR_IS_OK(result))
00768                 goto done;
00769  
00770         opened_hnd = True;
00771 
00772         /* Get printer info */
00773 
00774         result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value);
00775 
00776         if (!W_ERROR_IS_OK(result))
00777                 goto done;
00778 
00779         /* Display printer data */
00780 
00781         fstrcpy(value.valuename, valuename);
00782         display_reg_value(value);
00783         
00784 
00785  done: 
00786         if (opened_hnd) 
00787                 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
00788 
00789         return result;
00790 }
00791 
00792 /****************************************************************************
00793 ****************************************************************************/
00794 
00795 static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli,
00796                                              TALLOC_CTX *mem_ctx,
00797                                              int argc, const char **argv)
00798 {
00799         POLICY_HND      pol;
00800         WERROR          result;
00801         BOOL            opened_hnd = False;
00802         fstring         printername,
00803                         servername,
00804                         user;
00805         const char *valuename, *keyname;
00806         REGISTRY_VALUE value;
00807 
00808         if (argc != 4) {
00809                 printf("Usage: %s <printername> <keyname> <valuename>\n", 
00810                        argv[0]);
00811                 printf("<printername> of . queries print server\n");
00812                 return WERR_OK;
00813         }
00814         valuename = argv[3];
00815         keyname = argv[2];
00816 
00817         /* Open a printer handle */
00818 
00819         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
00820         strupper_m(servername);
00821         if (strncmp(argv[1], ".", sizeof(".")) == 0)
00822                 fstrcpy(printername, servername);
00823         else
00824                 slprintf(printername, sizeof(printername)-1, "%s\\%s", 
00825                           servername, argv[1]);
00826         fstrcpy(user, cli->user_name);
00827         
00828         /* get a printer handle */
00829 
00830         result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
00831                                              "", MAXIMUM_ALLOWED_ACCESS, 
00832                                              servername, user, &pol);
00833 
00834         if (!W_ERROR_IS_OK(result))
00835                 goto done;
00836  
00837         opened_hnd = True;
00838 
00839         /* Get printer info */
00840 
00841         result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname, 
00842                 valuename, &value);
00843 
00844         if (!W_ERROR_IS_OK(result))
00845                 goto done;
00846 
00847         /* Display printer data */
00848 
00849         fstrcpy(value.valuename, valuename);
00850         display_reg_value(value);
00851         
00852 
00853  done: 
00854         if (opened_hnd) 
00855                 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
00856 
00857         return result;
00858 }
00859 
00860 /****************************************************************************
00861 ****************************************************************************/
00862 
00863 static void display_print_driver_1(DRIVER_INFO_1 *i1)
00864 {
00865         fstring name;
00866         if (i1 == NULL)
00867                 return;
00868 
00869         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
00870 
00871         printf ("Printer Driver Info 1:\n");
00872         printf ("\tDriver Name: [%s]\n\n", name);
00873         
00874         return;
00875 }
00876 
00877 /****************************************************************************
00878 ****************************************************************************/
00879 
00880 static void display_print_driver_2(DRIVER_INFO_2 *i1)
00881 {
00882         fstring name;
00883         fstring architecture;
00884         fstring driverpath;
00885         fstring datafile;
00886         fstring configfile;
00887         if (i1 == NULL)
00888                 return;
00889 
00890         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
00891         rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
00892         rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
00893         rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
00894         rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
00895 
00896         printf ("Printer Driver Info 2:\n");
00897         printf ("\tVersion: [%x]\n", i1->version);
00898         printf ("\tDriver Name: [%s]\n", name);
00899         printf ("\tArchitecture: [%s]\n", architecture);
00900         printf ("\tDriver Path: [%s]\n", driverpath);
00901         printf ("\tDatafile: [%s]\n", datafile);
00902         printf ("\tConfigfile: [%s]\n\n", configfile);
00903 
00904         return;
00905 }
00906 
00907 /****************************************************************************
00908 ****************************************************************************/
00909 
00910 static void display_print_driver_3(DRIVER_INFO_3 *i1)
00911 {
00912         fstring name = "";
00913         fstring architecture = "";
00914         fstring driverpath = "";
00915         fstring datafile = "";
00916         fstring configfile = "";
00917         fstring helpfile = "";
00918         fstring dependentfiles = "";
00919         fstring monitorname = "";
00920         fstring defaultdatatype = "";
00921         
00922         int length=0;
00923         BOOL valid = True;
00924         
00925         if (i1 == NULL)
00926                 return;
00927 
00928         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
00929         rpcstr_pull(architecture, i1->architecture.buffer, sizeof(architecture), -1, STR_TERMINATE);
00930         rpcstr_pull(driverpath, i1->driverpath.buffer, sizeof(driverpath), -1, STR_TERMINATE);
00931         rpcstr_pull(datafile, i1->datafile.buffer, sizeof(datafile), -1, STR_TERMINATE);
00932         rpcstr_pull(configfile, i1->configfile.buffer, sizeof(configfile), -1, STR_TERMINATE);
00933         rpcstr_pull(helpfile, i1->helpfile.buffer, sizeof(helpfile), -1, STR_TERMINATE);
00934         rpcstr_pull(monitorname, i1->monitorname.buffer, sizeof(monitorname), -1, STR_TERMINATE);
00935         rpcstr_pull(defaultdatatype, i1->defaultdatatype.buffer, sizeof(defaultdatatype), -1, STR_TERMINATE);
00936 
00937         printf ("Printer Driver Info 3:\n");
00938         printf ("\tVersion: [%x]\n", i1->version);
00939         printf ("\tDriver Name: [%s]\n",name);
00940         printf ("\tArchitecture: [%s]\n", architecture);
00941         printf ("\tDriver Path: [%s]\n", driverpath);
00942         printf ("\tDatafile: [%s]\n", datafile);
00943         printf ("\tConfigfile: [%s]\n", configfile);
00944         printf ("\tHelpfile: [%s]\n\n", helpfile);
00945 
00946         while (valid)
00947         {
00948                 rpcstr_pull(dependentfiles, i1->dependentfiles+length, sizeof(dependentfiles), -1, STR_TERMINATE);
00949                 
00950                 length+=strlen(dependentfiles)+1;
00951                 
00952                 if (strlen(dependentfiles) > 0)
00953                 {
00954                         printf ("\tDependentfiles: [%s]\n", dependentfiles);
00955                 }
00956                 else
00957                 {
00958                         valid = False;
00959                 }
00960         }
00961         
00962         printf ("\n");
00963 
00964         printf ("\tMonitorname: [%s]\n", monitorname);
00965         printf ("\tDefaultdatatype: [%s]\n\n", defaultdatatype);
00966 
00967         return; 
00968 }
00969 
00970 /****************************************************************************
00971 ****************************************************************************/
00972 
00973 static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli, 
00974                                       TALLOC_CTX *mem_ctx,
00975                                       int argc, const char **argv)
00976 {
00977         POLICY_HND      pol;
00978         WERROR          werror;
00979         uint32          info_level = 3;
00980         BOOL            opened_hnd = False;
00981         PRINTER_DRIVER_CTR      ctr;
00982         fstring         printername, 
00983                         servername, 
00984                         user;
00985         uint32          i;
00986         BOOL            success = False;
00987 
00988         if ((argc == 1) || (argc > 3)) 
00989         {
00990                 printf("Usage: %s <printername> [level]\n", argv[0]);
00991                 return WERR_OK;
00992         }
00993 
00994         /* get the arguments need to open the printer handle */
00995         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
00996         strupper_m(servername);
00997         fstrcpy(user, cli->user_name);
00998         slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
00999         if (argc == 3)
01000                 info_level = atoi(argv[2]);
01001 
01002         /* Open a printer handle */
01003 
01004         werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
01005                                              PRINTER_ACCESS_USE,
01006                                              servername, user, &pol);
01007 
01008         if (!W_ERROR_IS_OK(werror)) {
01009                 printf("Error opening printer handle for %s!\n", printername);
01010                 return werror;
01011         }
01012 
01013         opened_hnd = True;
01014 
01015         /* loop through and print driver info level for each architecture */
01016 
01017         for (i=0; archi_table[i].long_archi!=NULL; i++) {
01018 
01019                 werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level, 
01020                         archi_table[i].long_archi, archi_table[i].version,
01021                         &ctr);
01022 
01023                 if (!W_ERROR_IS_OK(werror))
01024                         continue;
01025                 
01026                 /* need at least one success */
01027                 
01028                 success = True;
01029                         
01030                 printf ("\n[%s]\n", archi_table[i].long_archi);
01031 
01032                 switch (info_level) {
01033                 case 1:
01034                         display_print_driver_1 (ctr.info1);
01035                         break;
01036                 case 2:
01037                         display_print_driver_2 (ctr.info2);
01038                         break;
01039                 case 3:
01040                         display_print_driver_3 (ctr.info3);
01041                         break;
01042                 default:
01043                         printf("unknown info level %d\n", info_level);
01044                         break;
01045                 }
01046         }
01047         
01048         /* Cleanup */
01049 
01050         if (opened_hnd)
01051                 rpccli_spoolss_close_printer (cli, mem_ctx, &pol);
01052         
01053         if ( success )
01054                 werror = WERR_OK;
01055                 
01056         return werror;
01057 }
01058 
01059 /****************************************************************************
01060 ****************************************************************************/
01061 
01062 static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli, 
01063                                          TALLOC_CTX *mem_ctx,
01064                                          int argc, const char **argv)
01065 {
01066         WERROR werror = WERR_OK;
01067         uint32          info_level = 1;
01068         PRINTER_DRIVER_CTR      ctr;
01069         uint32          i, j,
01070                         returned;
01071 
01072         if (argc > 2) {
01073                 printf("Usage: enumdrivers [level]\n");
01074                 return WERR_OK;
01075         }
01076 
01077         if (argc == 2)
01078                 info_level = atoi(argv[1]);
01079 
01080 
01081         /* loop through and print driver info level for each architecture */
01082         for (i=0; archi_table[i].long_archi!=NULL; i++) {
01083                 /* check to see if we already asked for this architecture string */
01084 
01085                 if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) )
01086                         continue;
01087 
01088                 werror = rpccli_spoolss_enumprinterdrivers(
01089                         cli, mem_ctx, info_level, 
01090                         archi_table[i].long_archi, &returned, &ctr);
01091 
01092                 if (W_ERROR_V(werror) == W_ERROR_V(WERR_INVALID_ENVIRONMENT)) {
01093                         printf ("Server does not support environment [%s]\n", 
01094                                 archi_table[i].long_archi);
01095                         werror = WERR_OK;
01096                         continue;
01097                 }
01098 
01099                 if (returned == 0)
01100                         continue;
01101                         
01102                 if (!W_ERROR_IS_OK(werror)) {
01103                         printf ("Error getting driver for environment [%s] - %d\n",
01104                                 archi_table[i].long_archi, W_ERROR_V(werror));
01105                         continue;
01106                 }
01107                 
01108                 printf ("\n[%s]\n", archi_table[i].long_archi);
01109                 switch (info_level) 
01110                 {
01111                         
01112                 case 1:
01113                         for (j=0; j < returned; j++) {
01114                                 display_print_driver_1 (&ctr.info1[j]);
01115                         }
01116                         break;
01117                 case 2:
01118                         for (j=0; j < returned; j++) {
01119                                 display_print_driver_2 (&ctr.info2[j]);
01120                         }
01121                         break;
01122                 case 3:
01123                         for (j=0; j < returned; j++) {
01124                                 display_print_driver_3 (&ctr.info3[j]);
01125                         }
01126                         break;
01127                 default:
01128                         printf("unknown info level %d\n", info_level);
01129                         return WERR_UNKNOWN_LEVEL;
01130                 }
01131         }
01132         
01133         return werror;
01134 }
01135 
01136 /****************************************************************************
01137 ****************************************************************************/
01138 
01139 static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1)
01140 {
01141         fstring name;
01142         if (i1 == NULL)
01143                 return;
01144  
01145         rpcstr_pull(name, i1->name.buffer, sizeof(name), -1, STR_TERMINATE);
01146  
01147         printf ("\tDirectory Name:[%s]\n", name);
01148 }
01149 
01150 /****************************************************************************
01151 ****************************************************************************/
01152 
01153 static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli, 
01154                                          TALLOC_CTX *mem_ctx,
01155                                          int argc, const char **argv)
01156 {
01157         WERROR result;
01158         fstring                 env;
01159         DRIVER_DIRECTORY_CTR    ctr;
01160 
01161         if (argc > 2) {
01162                 printf("Usage: %s [environment]\n", argv[0]);
01163                 return WERR_OK;
01164         }
01165 
01166         /* Get the arguments need to open the printer handle */
01167 
01168         if (argc == 2)
01169                 fstrcpy (env, argv[1]);
01170         else
01171                 fstrcpy (env, "Windows NT x86");
01172 
01173         /* Get the directory.  Only use Info level 1 */
01174 
01175         result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr);
01176 
01177         if (W_ERROR_IS_OK(result))
01178                 display_printdriverdir_1(ctr.info1);
01179 
01180         return result;
01181 }
01182 
01183 /****************************************************************************
01184 ****************************************************************************/
01185 
01186 void set_drv_info_3_env (DRIVER_INFO_3 *info, const char *arch)
01187 {
01188 
01189         int i;
01190         
01191         for (i=0; archi_table[i].long_archi != NULL; i++) 
01192         {
01193                 if (strcmp(arch, archi_table[i].short_archi) == 0)
01194                 {
01195                         info->version = archi_table[i].version;
01196                         init_unistr (&info->architecture, archi_table[i].long_archi);
01197                         break;
01198                 }
01199         }
01200         
01201         if (archi_table[i].long_archi == NULL)
01202         {
01203                 DEBUG(0, ("set_drv_info_3_env: Unknown arch [%s]\n", arch));
01204         }
01205         
01206         return;
01207 }
01208 
01209 
01210 /**************************************************************************
01211  wrapper for strtok to get the next parameter from a delimited list.
01212  Needed to handle the empty parameter string denoted by "NULL"
01213  *************************************************************************/
01214  
01215 static char* get_driver_3_param (char* str, const char* delim, UNISTR* dest)
01216 {
01217         char    *ptr;
01218 
01219         /* get the next token */
01220         ptr = strtok(str, delim);
01221 
01222         /* a string of 'NULL' is used to represent an empty
01223            parameter because two consecutive delimiters
01224            will not return an empty string.  See man strtok(3)
01225            for details */
01226         if (ptr && (StrCaseCmp(ptr, "NULL") == 0))
01227                 ptr = NULL;
01228 
01229         if (dest != NULL)
01230                 init_unistr(dest, ptr); 
01231 
01232         return ptr;
01233 }
01234 
01235 /********************************************************************************
01236  fill in the members of a DRIVER_INFO_3 struct using a character 
01237  string in the form of
01238          <Long Printer Name>:<Driver File Name>:<Data File Name>:\
01239              <Config File Name>:<Help File Name>:<Language Monitor Name>:\
01240              <Default Data Type>:<Comma Separated list of Files> 
01241  *******************************************************************************/
01242 static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info, 
01243                                       char *args )
01244 {
01245         char    *str, *str2;
01246         uint32  len, i;
01247         
01248         /* fill in the UNISTR fields */
01249         str = get_driver_3_param (args, ":", &info->name);
01250         str = get_driver_3_param (NULL, ":", &info->driverpath);
01251         str = get_driver_3_param (NULL, ":", &info->datafile);
01252         str = get_driver_3_param (NULL, ":", &info->configfile);
01253         str = get_driver_3_param (NULL, ":", &info->helpfile);
01254         str = get_driver_3_param (NULL, ":", &info->monitorname);
01255         str = get_driver_3_param (NULL, ":", &info->defaultdatatype);
01256 
01257         /* <Comma Separated List of Dependent Files> */
01258         str2 = get_driver_3_param (NULL, ":", NULL); /* save the beginning of the string */
01259         str = str2;                     
01260 
01261         /* begin to strip out each filename */
01262         str = strtok(str, ",");         
01263         len = 0;
01264         while (str != NULL)
01265         {
01266                 /* keep a cumlative count of the str lengths */
01267                 len += strlen(str)+1;
01268                 str = strtok(NULL, ",");
01269         }
01270 
01271         /* allocate the space; add one extra slot for a terminating NULL.
01272            Each filename is NULL terminated and the end contains a double
01273            NULL */
01274         if ((info->dependentfiles=TALLOC_ARRAY(mem_ctx, uint16, len+1)) == NULL)
01275         {
01276                 DEBUG(0,("init_drv_info_3_members: Unable to malloc memory for dependenfiles\n"));
01277                 return False;
01278         }
01279         for (i=0; i<len; i++)
01280         {
01281                 SSVAL(&info->dependentfiles[i], 0, str2[i]);
01282         }
01283         info->dependentfiles[len] = '\0';
01284 
01285         return True;
01286 }
01287 
01288 
01289 /****************************************************************************
01290 ****************************************************************************/
01291 
01292 static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli, 
01293                                              TALLOC_CTX *mem_ctx,
01294                                              int argc, const char **argv)
01295 {
01296         WERROR result;
01297         uint32                  level = 3;
01298         PRINTER_DRIVER_CTR      ctr;
01299         DRIVER_INFO_3           info3;
01300         const char              *arch;
01301         fstring                 driver_name;
01302         char                    *driver_args;
01303 
01304         /* parse the command arguements */
01305         if (argc != 3 && argc != 4)
01306         {
01307                 printf ("Usage: %s <Environment> \\\n", argv[0]);
01308                 printf ("\t<Long Printer Name>:<Driver File Name>:<Data File Name>:\\\n");
01309                 printf ("\t<Config File Name>:<Help File Name>:<Language Monitor Name>:\\\n");
01310                 printf ("\t<Default Data Type>:<Comma Separated list of Files> \\\n");
01311                 printf ("\t[version]\n");
01312 
01313             return WERR_OK;
01314         }
01315                 
01316         /* Fill in the DRIVER_INFO_3 struct */
01317         ZERO_STRUCT(info3);
01318         if (!(arch = cmd_spoolss_get_short_archi(argv[1])))
01319         {
01320                 printf ("Error Unknown architechture [%s]\n", argv[1]);
01321                 return WERR_INVALID_PARAM;
01322         }
01323         else
01324                 set_drv_info_3_env(&info3, arch);
01325 
01326         driver_args = talloc_strdup( mem_ctx, argv[2] );
01327         if (!init_drv_info_3_members(mem_ctx, &info3, driver_args ))
01328         {
01329                 printf ("Error Invalid parameter list - %s.\n", argv[2]);
01330                 return WERR_INVALID_PARAM;
01331         }
01332 
01333         /* if printer driver version specified, override the default version
01334          * used by the architecture.  This allows installation of Windows
01335          * 2000 (version 3) printer drivers. */
01336         if (argc == 4)
01337         {
01338                 info3.version = atoi(argv[3]);
01339         }
01340 
01341 
01342         ctr.info3 = &info3;
01343         result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr);
01344 
01345         if (W_ERROR_IS_OK(result)) {
01346                 rpcstr_pull(driver_name, info3.name.buffer, 
01347                             sizeof(driver_name), -1, STR_TERMINATE);
01348                 printf ("Printer Driver %s successfully installed.\n",
01349                         driver_name);
01350         }
01351 
01352         return result;
01353 }
01354 
01355 
01356 /****************************************************************************
01357 ****************************************************************************/
01358 
01359 static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli, 
01360                                          TALLOC_CTX *mem_ctx,
01361                                          int argc, const char **argv)
01362 {
01363         WERROR result;
01364         uint32                  level = 2;
01365         PRINTER_INFO_CTR        ctr;
01366         PRINTER_INFO_2          info2;
01367         fstring                 servername;
01368         
01369         /* parse the command arguements */
01370         if (argc != 5)
01371         {
01372                 printf ("Usage: %s <name> <shared name> <driver> <port>\n", argv[0]);
01373                 return WERR_OK;
01374         }
01375         
01376         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
01377         strupper_m(servername);
01378 
01379         /* Fill in the DRIVER_INFO_2 struct */
01380         ZERO_STRUCT(info2);
01381         
01382         init_unistr( &info2.printername,        argv[1]);
01383         init_unistr( &info2.sharename,          argv[2]);
01384         init_unistr( &info2.drivername,         argv[3]);
01385         init_unistr( &info2.portname,           argv[4]);
01386         init_unistr( &info2.comment,            "Created by rpcclient");
01387         init_unistr( &info2.printprocessor,     "winprint");
01388         init_unistr( &info2.datatype,           "RAW");
01389         info2.devmode =         NULL;
01390         info2.secdesc =         NULL;
01391         info2.attributes        = PRINTER_ATTRIBUTE_SHARED;
01392         info2.priority          = 0;
01393         info2.defaultpriority   = 0;
01394         info2.starttime         = 0;
01395         info2.untiltime         = 0;
01396         
01397         /* These three fields must not be used by AddPrinter() 
01398            as defined in the MS Platform SDK documentation..  
01399            --jerry
01400         info2.status            = 0;
01401         info2.cjobs             = 0;
01402         info2.averageppm        = 0;
01403         */
01404 
01405         ctr.printers_2 = &info2;
01406         result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr);
01407 
01408         if (W_ERROR_IS_OK(result))
01409                 printf ("Printer %s successfully installed.\n", argv[1]);
01410 
01411         return result;
01412 }
01413 
01414 /****************************************************************************
01415 ****************************************************************************/
01416 
01417 static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli, 
01418                                       TALLOC_CTX *mem_ctx,
01419                                       int argc, const char **argv)
01420 {
01421         POLICY_HND              pol;
01422         WERROR                  result;
01423         uint32                  level = 2;
01424         BOOL                    opened_hnd = False;
01425         PRINTER_INFO_CTR        ctr;
01426         PRINTER_INFO_2          info2;
01427         fstring                 servername,
01428                                 printername,
01429                                 user;
01430         
01431         /* parse the command arguements */
01432         if (argc != 3)
01433         {
01434                 printf ("Usage: %s <printer> <driver>\n", argv[0]);
01435                 return WERR_OK;
01436         }
01437 
01438         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
01439         strupper_m(servername);
01440         slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]);
01441         fstrcpy(user, cli->user_name);
01442 
01443         /* Get a printer handle */
01444 
01445         result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
01446                                              PRINTER_ALL_ACCESS,
01447                                              servername, user, &pol);
01448 
01449         if (!W_ERROR_IS_OK(result))
01450                 goto done;
01451 
01452         opened_hnd = True;
01453 
01454         /* Get printer info */
01455 
01456         ZERO_STRUCT (info2);
01457         ctr.printers_2 = &info2;
01458 
01459         result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr);
01460 
01461         if (!W_ERROR_IS_OK(result)) {
01462                 printf ("Unable to retrieve printer information!\n");
01463                 goto done;
01464         }
01465 
01466         /* Set the printer driver */
01467 
01468         init_unistr(&ctr.printers_2->drivername, argv[2]);
01469 
01470         result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0);
01471 
01472         if (!W_ERROR_IS_OK(result)) {
01473                 printf("SetPrinter call failed!\n");
01474                 goto done;;
01475         }
01476 
01477         printf("Succesfully set %s to driver %s.\n", argv[1], argv[2]);
01478 
01479 done:
01480         /* Cleanup */
01481 
01482         if (opened_hnd)
01483                 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
01484 
01485         return result;
01486 }
01487 
01488 
01489 /****************************************************************************
01490 ****************************************************************************/
01491 
01492 static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli, 
01493                                          TALLOC_CTX *mem_ctx,
01494                                          int argc, const char **argv)
01495 {
01496         WERROR result, ret = WERR_UNKNOWN_PRINTER_DRIVER;
01497  
01498         int   i;
01499         int vers = -1;
01500  
01501         const char *arch = NULL;
01502  
01503         /* parse the command arguements */
01504         if (argc < 2 || argc > 4) {
01505                 printf ("Usage: %s <driver> [arch] [version]\n", argv[0]);
01506                 return WERR_OK;
01507         }
01508 
01509         if (argc >= 3)
01510                 arch = argv[2];
01511         if (argc == 4)
01512                 vers = atoi (argv[3]);
01513  
01514  
01515         /* delete the driver for all architectures */
01516         for (i=0; archi_table[i].long_archi; i++) {
01517 
01518                 if (arch &&  !strequal( archi_table[i].long_archi, arch)) 
01519                         continue;
01520 
01521                 if (vers >= 0 && archi_table[i].version != vers)
01522                         continue;
01523 
01524                 /* make the call to remove the driver */
01525                 result = rpccli_spoolss_deleteprinterdriverex(
01526                         cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version); 
01527 
01528                 if ( !W_ERROR_IS_OK(result) ) 
01529                 {
01530                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
01531                                 printf ("Failed to remove driver %s for arch [%s] (version: %d): %s\n", 
01532                                         argv[1], archi_table[i].long_archi, archi_table[i].version, dos_errstr(result));
01533                         }
01534                 } 
01535                 else 
01536                 {
01537                         printf ("Driver %s and files removed for arch [%s] (version: %d).\n", argv[1], 
01538                         archi_table[i].long_archi, archi_table[i].version);
01539                         ret = WERR_OK;
01540                 }
01541         }
01542   
01543         return ret;
01544 }
01545 
01546 
01547 /****************************************************************************
01548 ****************************************************************************/
01549 
01550 static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli, 
01551                                          TALLOC_CTX *mem_ctx,
01552                                          int argc, const char **argv)
01553 {
01554         WERROR result = WERR_OK;
01555         fstring                 servername;
01556         int                     i;
01557         
01558         /* parse the command arguements */
01559         if (argc != 2) {
01560                 printf ("Usage: %s <driver>\n", argv[0]);
01561                 return WERR_OK;
01562         }
01563 
01564         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
01565         strupper_m(servername);
01566 
01567         /* delete the driver for all architectures */
01568         for (i=0; archi_table[i].long_archi; i++) {
01569                 /* make the call to remove the driver */
01570                 result = rpccli_spoolss_deleteprinterdriver(
01571                         cli, mem_ctx, archi_table[i].long_archi, argv[1]);
01572 
01573                 if ( !W_ERROR_IS_OK(result) ) {
01574                         if ( !W_ERROR_EQUAL(result, WERR_UNKNOWN_PRINTER_DRIVER) ) {
01575                                 printf ("Failed to remove driver %s for arch [%s] - error 0x%x!\n", 
01576                                         argv[1], archi_table[i].long_archi, 
01577                                         W_ERROR_V(result));
01578                         }
01579                 } else {
01580                         printf ("Driver %s removed for arch [%s].\n", argv[1], 
01581                                 archi_table[i].long_archi);
01582                 }
01583         }
01584                 
01585         return result;
01586 }
01587 
01588 /****************************************************************************
01589 ****************************************************************************/
01590 
01591 static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli, 
01592                                             TALLOC_CTX *mem_ctx,
01593                                             int argc, const char **argv)
01594 {
01595         WERROR result;
01596         char *servername = NULL, *environment = NULL;
01597         fstring procdir;
01598         
01599         /* parse the command arguements */
01600         if (argc > 2) {
01601                 printf ("Usage: %s [environment]\n", argv[0]);
01602                 return WERR_OK;
01603         }
01604 
01605         if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0)
01606                 return WERR_NOMEM;
01607         strupper_m(servername);
01608 
01609         if (asprintf(&environment, "%s", (argc == 2) ? argv[1] : 
01610                      PRINTER_DRIVER_ARCHITECTURE) < 0) {
01611                 SAFE_FREE(servername);
01612                 return WERR_NOMEM;
01613         }
01614 
01615         result = rpccli_spoolss_getprintprocessordirectory(
01616                 cli, mem_ctx, servername, environment, procdir);
01617 
01618         if (W_ERROR_IS_OK(result))
01619                 printf("%s\n", procdir);
01620 
01621         SAFE_FREE(servername);
01622         SAFE_FREE(environment);
01623 
01624         return result;
01625 }
01626 
01627 /****************************************************************************
01628 ****************************************************************************/
01629 
01630 static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
01631                                     int argc, const char **argv)
01632 {
01633         POLICY_HND handle;
01634         WERROR werror;
01635         char *servername = NULL, *printername = NULL;
01636         FORM form;
01637         BOOL got_handle = False;
01638         
01639         /* Parse the command arguements */
01640 
01641         if (argc != 3) {
01642                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
01643                 return WERR_OK;
01644         }
01645         
01646         /* Get a printer handle */
01647 
01648         asprintf(&servername, "\\\\%s", cli->cli->desthost);
01649         strupper_m(servername);
01650         asprintf(&printername, "%s\\%s", servername, argv[1]);
01651 
01652         werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", 
01653                                              PRINTER_ALL_ACCESS, 
01654                                              servername, cli->user_name, &handle);
01655 
01656         if (!W_ERROR_IS_OK(werror))
01657                 goto done;
01658 
01659         got_handle = True;
01660 
01661         /* Dummy up some values for the form data */
01662 
01663         form.flags = FORM_USER;
01664         form.size_x = form.size_y = 100;
01665         form.left = 0;
01666         form.top = 10;
01667         form.right = 20;
01668         form.bottom = 30;
01669 
01670         init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
01671 
01672         /* Add the form */
01673 
01674 
01675         werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form);
01676 
01677  done:
01678         if (got_handle)
01679                 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
01680 
01681         SAFE_FREE(servername);
01682         SAFE_FREE(printername);
01683 
01684         return werror;
01685 }
01686 
01687 /****************************************************************************
01688 ****************************************************************************/
01689 
01690 static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
01691                                     int argc, const char **argv)
01692 {
01693         POLICY_HND handle;
01694         WERROR werror;
01695         char *servername = NULL, *printername = NULL;
01696         FORM form;
01697         BOOL got_handle = False;
01698         
01699         /* Parse the command arguements */
01700 
01701         if (argc != 3) {
01702                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
01703                 return WERR_OK;
01704         }
01705         
01706         /* Get a printer handle */
01707 
01708         asprintf(&servername, "\\\\%s", cli->cli->desthost);
01709         strupper_m(servername);
01710         asprintf(&printername, "%s\\%s", servername, argv[1]);
01711 
01712         werror = rpccli_spoolss_open_printer_ex(
01713                 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
01714                 servername, cli->user_name, &handle);
01715 
01716         if (!W_ERROR_IS_OK(werror))
01717                 goto done;
01718 
01719         got_handle = True;
01720 
01721         /* Dummy up some values for the form data */
01722 
01723         form.flags = FORM_PRINTER;
01724         form.size_x = form.size_y = 100;
01725         form.left = 0;
01726         form.top = 1000;
01727         form.right = 2000;
01728         form.bottom = 3000;
01729 
01730         init_unistr2(&form.name, argv[2], UNI_STR_TERMINATE);
01731 
01732         /* Set the form */
01733 
01734         werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form);
01735 
01736  done:
01737         if (got_handle)
01738                 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
01739 
01740         SAFE_FREE(servername);
01741         SAFE_FREE(printername);
01742 
01743         return werror;
01744 }
01745 
01746 /****************************************************************************
01747 ****************************************************************************/
01748 
01749 static const char *get_form_flag(int form_flag)
01750 {
01751         switch (form_flag) {
01752         case FORM_USER:
01753                 return "FORM_USER";
01754         case FORM_BUILTIN:
01755                 return "FORM_BUILTIN";
01756         case FORM_PRINTER:
01757                 return "FORM_PRINTER";
01758         default:
01759                 return "unknown";
01760         }
01761 }
01762 
01763 /****************************************************************************
01764 ****************************************************************************/
01765 
01766 static void display_form(FORM_1 *form)
01767 {
01768         fstring form_name = "";
01769 
01770         if (form->name.buffer)
01771                 rpcstr_pull(form_name, form->name.buffer,
01772                             sizeof(form_name), -1, STR_TERMINATE);
01773 
01774         printf("%s\n" \
01775                 "\tflag: %s (%d)\n" \
01776                 "\twidth: %d, length: %d\n" \
01777                 "\tleft: %d, right: %d, top: %d, bottom: %d\n\n", 
01778                 form_name, get_form_flag(form->flag), form->flag,
01779                 form->width, form->length, 
01780                 form->left, form->right, 
01781                 form->top, form->bottom);
01782 }
01783 
01784 /****************************************************************************
01785 ****************************************************************************/
01786 
01787 static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
01788                                     int argc, const char **argv)
01789 {
01790         POLICY_HND handle;
01791         WERROR werror;
01792         char *servername = NULL, *printername = NULL;
01793         FORM_1 form;
01794         BOOL got_handle = False;
01795         
01796         /* Parse the command arguements */
01797 
01798         if (argc != 3) {
01799                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
01800                 return WERR_OK;
01801         }
01802         
01803         /* Get a printer handle */
01804 
01805         asprintf(&servername, "\\\\%s", cli->cli->desthost);
01806         strupper_m(servername);
01807         asprintf(&printername, "%s\\%s", servername, argv[1]);
01808 
01809         werror = rpccli_spoolss_open_printer_ex(
01810                 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
01811                 servername, cli->user_name, &handle);
01812 
01813         if (!W_ERROR_IS_OK(werror))
01814                 goto done;
01815 
01816         got_handle = True;
01817 
01818         /* Get the form */
01819 
01820         werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form);
01821 
01822         if (!W_ERROR_IS_OK(werror))
01823                 goto done;
01824 
01825         display_form(&form);
01826 
01827  done:
01828         if (got_handle)
01829                 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
01830 
01831         SAFE_FREE(servername);
01832         SAFE_FREE(printername);
01833 
01834         return werror;
01835 }
01836 
01837 /****************************************************************************
01838 ****************************************************************************/
01839 
01840 static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli, 
01841                                        TALLOC_CTX *mem_ctx, int argc, 
01842                                        const char **argv)
01843 {
01844         POLICY_HND handle;
01845         WERROR werror;
01846         char *servername = NULL, *printername = NULL;
01847         BOOL got_handle = False;
01848         
01849         /* Parse the command arguements */
01850 
01851         if (argc != 3) {
01852                 printf ("Usage: %s <printer> <formname>\n", argv[0]);
01853                 return WERR_OK;
01854         }
01855         
01856         /* Get a printer handle */
01857 
01858         asprintf(&servername, "\\\\%s", cli->cli->desthost);
01859         strupper_m(servername);
01860         asprintf(&printername, "%s\\%s", servername, argv[1]);
01861 
01862         werror = rpccli_spoolss_open_printer_ex(
01863                 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
01864                 servername, cli->user_name, &handle);
01865 
01866         if (!W_ERROR_IS_OK(werror))
01867                 goto done;
01868 
01869         got_handle = True;
01870 
01871         /* Delete the form */
01872 
01873         werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]);
01874 
01875  done:
01876         if (got_handle)
01877                 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
01878 
01879         SAFE_FREE(servername);
01880         SAFE_FREE(printername);
01881 
01882         return werror;
01883 }
01884 
01885 /****************************************************************************
01886 ****************************************************************************/
01887 
01888 static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli, 
01889                                        TALLOC_CTX *mem_ctx, int argc, 
01890                                        const char **argv)
01891 {
01892         POLICY_HND handle;
01893         WERROR werror;
01894         char *servername = NULL, *printername = NULL;
01895         BOOL got_handle = False;
01896         uint32 num_forms, level = 1, i;
01897         FORM_1 *forms;
01898         
01899         /* Parse the command arguements */
01900 
01901         if (argc != 2) {
01902                 printf ("Usage: %s <printer>\n", argv[0]);
01903                 return WERR_OK;
01904         }
01905         
01906         /* Get a printer handle */
01907 
01908         asprintf(&servername, "\\\\%s", cli->cli->desthost);
01909         strupper_m(servername);
01910         asprintf(&printername, "%s\\%s", servername, argv[1]);
01911 
01912         werror = rpccli_spoolss_open_printer_ex(
01913                 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
01914                 servername, cli->user_name, &handle);
01915 
01916         if (!W_ERROR_IS_OK(werror))
01917                 goto done;
01918 
01919         got_handle = True;
01920 
01921         /* Enumerate forms */
01922 
01923         werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms);
01924 
01925         if (!W_ERROR_IS_OK(werror))
01926                 goto done;
01927 
01928         /* Display output */
01929 
01930         for (i = 0; i < num_forms; i++) {
01931 
01932                 display_form(&forms[i]);
01933 
01934         }
01935 
01936  done:
01937         if (got_handle)
01938                 rpccli_spoolss_close_printer(cli, mem_ctx, &handle);
01939 
01940         SAFE_FREE(servername);
01941         SAFE_FREE(printername);
01942 
01943         return werror;
01944 }
01945 
01946 /****************************************************************************
01947 ****************************************************************************/
01948 
01949 static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli,
01950                                             TALLOC_CTX *mem_ctx,
01951                                             int argc, const char **argv)
01952 {
01953         WERROR result;
01954         fstring servername, printername, user;
01955         POLICY_HND pol;
01956         BOOL opened_hnd = False;
01957         PRINTER_INFO_CTR ctr;
01958         PRINTER_INFO_0 info;
01959         REGISTRY_VALUE value;
01960 
01961         /* parse the command arguements */
01962         if (argc < 5) {
01963                 printf ("Usage: %s <printer> <string|binary|dword|multistring>"
01964                         " <value> <data>\n",
01965                         argv[0]);
01966                 return WERR_INVALID_PARAM;
01967         }
01968 
01969         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
01970         strupper_m(servername);
01971         slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]);
01972         fstrcpy(user, cli->user_name);
01973 
01974         value.type = REG_NONE;
01975 
01976         if (strequal(argv[2], "string")) {
01977                 value.type = REG_SZ;
01978         }
01979 
01980         if (strequal(argv[2], "binary")) {
01981                 value.type = REG_BINARY;
01982         }
01983 
01984         if (strequal(argv[2], "dword")) {
01985                 value.type = REG_DWORD;
01986         }
01987 
01988         if (strequal(argv[2], "multistring")) {
01989                 value.type = REG_MULTI_SZ;
01990         }
01991 
01992         if (value.type == REG_NONE) {
01993                 printf("Unknown data type: %s\n", argv[2]);
01994                 return WERR_INVALID_PARAM;
01995         }
01996 
01997         /* get a printer handle */
01998         result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "",
01999                                              MAXIMUM_ALLOWED_ACCESS, servername, 
02000                                              user, &pol);
02001         if (!W_ERROR_IS_OK(result))
02002                 goto done;
02003 
02004         opened_hnd = True;
02005 
02006         ctr.printers_0 = &info;
02007 
02008         result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
02009 
02010         if (!W_ERROR_IS_OK(result))
02011                 goto done;
02012                 
02013         printf("%s\n", current_timestring(True));
02014         printf("\tchange_id (before set)\t:[0x%x]\n", info.change_id);
02015 
02016         /* Set the printer data */
02017         
02018         fstrcpy(value.valuename, argv[3]);
02019 
02020         switch (value.type) {
02021         case REG_SZ: {
02022                 UNISTR2 data;
02023                 init_unistr2(&data, argv[4], UNI_STR_TERMINATE);
02024                 value.size = data.uni_str_len * 2;
02025                 if (value.size) {
02026                         value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, data.buffer,
02027                                                       value.size);
02028                 } else {
02029                         value.data_p = NULL;
02030                 }
02031                 break;
02032         }
02033         case REG_DWORD: {
02034                 uint32 data = strtoul(argv[4], NULL, 10);
02035                 value.size = sizeof(data);
02036                 if (sizeof(data)) {
02037                         value.data_p = (uint8 *)TALLOC_MEMDUP(mem_ctx, &data,
02038                                                       sizeof(data));
02039                 } else {
02040                         value.data_p = NULL;
02041                 }
02042                 break;
02043         }
02044         case REG_BINARY: {
02045                 DATA_BLOB data = strhex_to_data_blob(mem_ctx, argv[4]);
02046                 value.data_p = data.data;
02047                 value.size = data.length;
02048                 break;
02049         }
02050         case REG_MULTI_SZ: {
02051                 int i;
02052                 size_t len = 0;
02053                 char *p;
02054 
02055                 for (i=4; i<argc; i++) {
02056                         if (strcmp(argv[i], "NULL") == 0) {
02057                                 argv[i] = "";
02058                         }
02059                         len += strlen(argv[i])+1;
02060                 }
02061 
02062                 value.size = len*2;
02063                 value.data_p = TALLOC_ARRAY(mem_ctx, unsigned char, value.size);
02064                 if (value.data_p == NULL) {
02065                         result = WERR_NOMEM;
02066                         goto done;
02067                 }
02068 
02069                 p = (char *)value.data_p;
02070                 len = value.size;
02071                 for (i=4; i<argc; i++) {
02072                         size_t l = (strlen(argv[i])+1)*2;
02073                         rpcstr_push(p, argv[i], len, STR_TERMINATE);
02074                         p += l;
02075                         len -= l;
02076                 }
02077                 SMB_ASSERT(len == 0);
02078                 break;
02079         }
02080         default:
02081                 printf("Unknown data type: %s\n", argv[2]);
02082                 result = WERR_INVALID_PARAM;
02083                 goto done;
02084         }
02085 
02086         result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value);
02087                 
02088         if (!W_ERROR_IS_OK(result)) {
02089                 printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]);
02090                 goto done;
02091         }
02092         printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]);
02093         
02094         result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr);
02095 
02096         if (!W_ERROR_IS_OK(result))
02097                 goto done;
02098                 
02099         printf("%s\n", current_timestring(True));
02100         printf("\tchange_id (after set)\t:[0x%x]\n", info.change_id);
02101 
02102 done:
02103         /* cleanup */
02104         if (opened_hnd)
02105                 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
02106 
02107         return result;
02108 }
02109 
02110 /****************************************************************************
02111 ****************************************************************************/
02112 
02113 static void display_job_info_1(JOB_INFO_1 *job)
02114 {
02115         fstring username = "", document = "", text_status = "";
02116 
02117         rpcstr_pull(username, job->username.buffer,
02118                     sizeof(username), -1, STR_TERMINATE);
02119 
02120         rpcstr_pull(document, job->document.buffer,
02121                     sizeof(document), -1, STR_TERMINATE);
02122 
02123         rpcstr_pull(text_status, job->text_status.buffer,
02124                     sizeof(text_status), -1, STR_TERMINATE);
02125 
02126         printf("%d: jobid[%d]: %s %s %s %d/%d pages\n", job->position, job->jobid,
02127                username, document, text_status, job->pagesprinted,
02128                job->totalpages);
02129 }
02130 
02131 /****************************************************************************
02132 ****************************************************************************/
02133 
02134 static void display_job_info_2(JOB_INFO_2 *job)
02135 {
02136         fstring username = "", document = "", text_status = "";
02137 
02138         rpcstr_pull(username, job->username.buffer,
02139                     sizeof(username), -1, STR_TERMINATE);
02140 
02141         rpcstr_pull(document, job->document.buffer,
02142                     sizeof(document), -1, STR_TERMINATE);
02143 
02144         rpcstr_pull(text_status, job->text_status.buffer,
02145                     sizeof(text_status), -1, STR_TERMINATE);
02146 
02147         printf("%d: jobid[%d]: %s %s %s %d/%d pages, %d bytes\n", job->position, job->jobid,
02148                username, document, text_status, job->pagesprinted,
02149                job->totalpages, job->size);
02150 }
02151 
02152 /****************************************************************************
02153 ****************************************************************************/
02154 
02155 static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli, 
02156                                       TALLOC_CTX *mem_ctx, int argc, 
02157                                       const char **argv)
02158 {
02159         WERROR result;
02160         uint32 level = 1, num_jobs, i;
02161         BOOL got_hnd = False;
02162         pstring printername;
02163         fstring servername, user;
02164         POLICY_HND hnd;
02165         JOB_INFO_CTR ctr;
02166         
02167         if (argc < 2 || argc > 3) {
02168                 printf("Usage: %s printername [level]\n", argv[0]);
02169                 return WERR_OK;
02170         }
02171         
02172         if (argc == 3)
02173                 level = atoi(argv[2]);
02174 
02175         /* Open printer handle */
02176 
02177         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
02178         strupper_m(servername);
02179         fstrcpy(user, cli->user_name);
02180         slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->cli->desthost);
02181         strupper_m(printername);
02182         pstrcat(printername, argv[1]);
02183 
02184         result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
02185                                              "", MAXIMUM_ALLOWED_ACCESS, 
02186                                              servername, user, &hnd);
02187 
02188         if (!W_ERROR_IS_OK(result))
02189                 goto done;
02190  
02191         got_hnd = True;
02192 
02193         /* Enumerate ports */
02194 
02195         result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000,
02196                 &num_jobs, &ctr);
02197 
02198         if (!W_ERROR_IS_OK(result))
02199                 goto done;
02200 
02201         for (i = 0; i < num_jobs; i++) {
02202                 switch(level) {
02203                 case 1:
02204                         display_job_info_1(&ctr.job.job_info_1[i]);
02205                         break;
02206                 case 2:
02207                         display_job_info_2(&ctr.job.job_info_2[i]);
02208                         break;
02209                 default:
02210                         d_printf("unknown info level %d\n", level);
02211                         break;
02212                 }
02213         }
02214         
02215 done:
02216         if (got_hnd)
02217                 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
02218 
02219         return result;
02220 }
02221 
02222 /****************************************************************************
02223 ****************************************************************************/
02224 
02225 static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli, 
02226                                        TALLOC_CTX *mem_ctx, int argc, 
02227                                        const char **argv)
02228 {
02229         WERROR result;
02230         uint32 i=0, val_needed, data_needed;
02231         BOOL got_hnd = False;
02232         pstring printername;
02233         fstring servername, user;
02234         POLICY_HND hnd;
02235 
02236         if (argc != 2) {
02237                 printf("Usage: %s printername\n", argv[0]);
02238                 return WERR_OK;
02239         }
02240         
02241         /* Open printer handle */
02242 
02243         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
02244         strupper_m(servername);
02245         fstrcpy(user, cli->user_name);
02246         slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
02247         strupper_m(printername);
02248         pstrcat(printername, argv[1]);
02249 
02250         result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
02251                                              "", MAXIMUM_ALLOWED_ACCESS, 
02252                                              servername, user, &hnd);
02253 
02254         if (!W_ERROR_IS_OK(result))
02255                 goto done;
02256  
02257         got_hnd = True;
02258 
02259         /* Enumerate data */
02260 
02261         result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0,
02262                                              &val_needed, &data_needed,
02263                                              NULL);
02264         while (W_ERROR_IS_OK(result)) {
02265                 REGISTRY_VALUE value;
02266                 result = rpccli_spoolss_enumprinterdata(
02267                         cli, mem_ctx, &hnd, i++, val_needed,
02268                         data_needed, 0, 0, &value);
02269                 if (W_ERROR_IS_OK(result))
02270                         display_reg_value(value);
02271         }
02272         if (W_ERROR_V(result) == ERRnomoreitems)
02273                 result = W_ERROR(ERRsuccess);
02274 
02275 done:
02276         if (got_hnd)
02277                 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
02278 
02279         return result;
02280 }
02281 
02282 /****************************************************************************
02283 ****************************************************************************/
02284 
02285 static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli, 
02286                                           TALLOC_CTX *mem_ctx, int argc, 
02287                                           const char **argv)
02288 {
02289         WERROR result;
02290         uint32 i;
02291         BOOL got_hnd = False;
02292         pstring printername;
02293         fstring servername, user;
02294         const char *keyname = NULL;
02295         POLICY_HND hnd;
02296         REGVAL_CTR *ctr = NULL;
02297 
02298         if (argc != 3) {
02299                 printf("Usage: %s printername <keyname>\n", argv[0]);
02300                 return WERR_OK;
02301         }
02302         
02303         keyname = argv[2];
02304 
02305         /* Open printer handle */
02306 
02307         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
02308         strupper_m(servername);
02309         fstrcpy(user, cli->user_name);
02310         slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
02311         strupper_m(printername);
02312         pstrcat(printername, argv[1]);
02313 
02314         result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
02315                                              "", MAXIMUM_ALLOWED_ACCESS, 
02316                                              servername, user, &hnd);
02317 
02318         if (!W_ERROR_IS_OK(result))
02319                 goto done;
02320  
02321         got_hnd = True;
02322 
02323         /* Enumerate subkeys */
02324 
02325         if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) 
02326                 return WERR_NOMEM;
02327 
02328         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr);
02329 
02330         if (!W_ERROR_IS_OK(result))
02331                 goto done;
02332 
02333         for (i=0; i < ctr->num_values; i++) {
02334                 display_reg_value(*(ctr->values[i]));
02335         }
02336 
02337         TALLOC_FREE( ctr );
02338 
02339 done:
02340         if (got_hnd)
02341                 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
02342 
02343         return result;
02344 }
02345 
02346 /****************************************************************************
02347 ****************************************************************************/
02348 
02349 static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli, 
02350                                              TALLOC_CTX *mem_ctx, int argc, 
02351                                              const char **argv)
02352 {
02353         WERROR result;
02354         BOOL got_hnd = False;
02355         pstring printername;
02356         fstring servername, user;
02357         const char *keyname = NULL;
02358         POLICY_HND hnd;
02359         uint16 *keylist = NULL, *curkey;
02360 
02361         if (argc < 2 || argc > 3) {
02362                 printf("Usage: %s printername [keyname]\n", argv[0]);
02363                 return WERR_OK;
02364         }
02365                 
02366         if (argc == 3)
02367                 keyname = argv[2];
02368         else
02369                 keyname = "";
02370 
02371         /* Open printer handle */
02372 
02373         slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost);
02374         strupper_m(servername);
02375         fstrcpy(user, cli->user_name);
02376         slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost);
02377         strupper_m(printername);
02378         pstrcat(printername, argv[1]);
02379 
02380         result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
02381                                              "", MAXIMUM_ALLOWED_ACCESS, 
02382                                              servername, user, &hnd);
02383 
02384         if (!W_ERROR_IS_OK(result))
02385                 goto done;
02386          
02387         got_hnd = True;
02388 
02389         /* Enumerate subkeys */
02390 
02391         result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL);
02392 
02393         if (!W_ERROR_IS_OK(result))
02394                 goto done;
02395 
02396         curkey = keylist;
02397         while (*curkey != 0) {
02398                 pstring subkey;
02399                 rpcstr_pull(subkey, curkey, sizeof(subkey), -1, 
02400                             STR_TERMINATE);
02401                 printf("%s\n", subkey);
02402                 curkey += strlen(subkey) + 1;
02403         }
02404 
02405 done:
02406 
02407         SAFE_FREE(keylist);
02408 
02409         if (got_hnd)
02410                 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
02411 
02412         return result;
02413 }
02414 
02415 /****************************************************************************
02416 ****************************************************************************/
02417 
02418 static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli, 
02419                                      TALLOC_CTX *mem_ctx, int argc, 
02420                                      const char **argv)
02421 {
02422         fstring servername, printername;
02423         POLICY_HND hnd;
02424         BOOL got_hnd = False;
02425         WERROR result;
02426         SPOOL_NOTIFY_OPTION option;
02427 
02428         if (argc != 2) {
02429                 printf("Usage: %s printername\n", argv[0]);
02430                 result = WERR_OK;
02431                 goto done;
02432         }
02433 
02434         /* Open printer */
02435 
02436         slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost);
02437         strupper_m(servername);
02438 
02439         slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost,
02440                  argv[1]);
02441         strupper_m(printername);
02442 
02443         result = rpccli_spoolss_open_printer_ex(
02444                 cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, 
02445                 servername, cli->user_name, &hnd);
02446 
02447         if (!W_ERROR_IS_OK(result)) {
02448                 printf("Error opening %s\n", argv[1]);
02449                 goto done;
02450         }
02451 
02452         got_hnd = True;
02453 
02454         /* Create spool options */
02455 
02456         ZERO_STRUCT(option);
02457 
02458         option.version = 2;
02459         option.option_type_ptr = 1;
02460         option.count = option.ctr.count = 2;
02461 
02462         option.ctr.type = TALLOC_ARRAY(mem_ctx, SPOOL_NOTIFY_OPTION_TYPE, 2);
02463         if (option.ctr.type == NULL) {
02464                 result = WERR_NOMEM;
02465                 goto done;
02466         }
02467 
02468         ZERO_STRUCT(option.ctr.type[0]);
02469         option.ctr.type[0].type = PRINTER_NOTIFY_TYPE;
02470         option.ctr.type[0].count = option.ctr.type[0].count2 = 1;
02471         option.ctr.type[0].fields_ptr = 1;
02472         option.ctr.type[0].fields[0] = PRINTER_NOTIFY_SERVER_NAME;
02473 
02474         ZERO_STRUCT(option.ctr.type[1]);
02475         option.ctr.type[1].type = JOB_NOTIFY_TYPE;
02476         option.ctr.type[1].count = option.ctr.type[1].count2 = 1;
02477         option.ctr.type[1].fields_ptr = 1;
02478         option.ctr.type[1].fields[0] = JOB_NOTIFY_PRINTER_NAME;
02479 
02480         /* Send rffpcnex */
02481 
02482         slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname());
02483         strupper_m(servername);
02484 
02485         result = rpccli_spoolss_rffpcnex(
02486                 cli, mem_ctx, &hnd, 0, 0, servername, 123, &option);
02487 
02488         if (!W_ERROR_IS_OK(result)) {
02489                 printf("Error rffpcnex %s\n", argv[1]);
02490                 goto done;
02491         }
02492 
02493 done:           
02494         if (got_hnd)
02495                 rpccli_spoolss_close_printer(cli, mem_ctx, &hnd);
02496 
02497         return result;
02498 }
02499 
02500 /****************************************************************************
02501 ****************************************************************************/
02502 
02503 static BOOL compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
02504                              struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
02505 {
02506         PRINTER_INFO_CTR ctr1, ctr2;
02507         WERROR werror;
02508         TALLOC_CTX *mem_ctx = talloc_init("compare_printer");
02509 
02510         printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost);
02511         werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1);
02512         if ( !W_ERROR_IS_OK(werror) ) {
02513                 printf("failed (%s)\n", dos_errstr(werror));
02514                 talloc_destroy(mem_ctx);
02515                 return False;
02516         }
02517         printf("ok\n");
02518 
02519         printf("Retrieving printer properties for %s...", cli2->cli->desthost);
02520         werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2);
02521         if ( !W_ERROR_IS_OK(werror) ) {
02522                 printf("failed (%s)\n", dos_errstr(werror));
02523                 talloc_destroy(mem_ctx);
02524                 return False;
02525         }
02526         printf("ok\n");
02527 
02528         talloc_destroy(mem_ctx);
02529 
02530         return True;
02531 }
02532 
02533 /****************************************************************************
02534 ****************************************************************************/
02535 
02536 static BOOL compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1,
02537                                      struct rpc_pipe_client *cli2, POLICY_HND *hnd2 )
02538 {
02539         PRINTER_INFO_CTR ctr1, ctr2;
02540         WERROR werror;
02541         TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc");
02542         SEC_DESC *sd1, *sd2;
02543         BOOL result = True;
02544 
02545 
02546         printf("Retreiving printer security for %s...", cli1->cli->desthost);
02547         werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1);
02548         if ( !W_ERROR_IS_OK(werror) ) {
02549                 printf("failed (%s)\n", dos_errstr(werror));
02550                 result = False;
02551                 goto done;
02552         }
02553         printf("ok\n");
02554 
02555         printf("Retrieving printer security for %s...", cli2->cli->desthost);
02556         werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2);
02557         if ( !W_ERROR_IS_OK(werror) ) {
02558                 printf("failed (%s)\n", dos_errstr(werror));
02559                 result = False;
02560                 goto done;
02561         }
02562         printf("ok\n");
02563         
02564 
02565         printf("++ ");
02566 
02567         if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) {
02568                 printf("NULL PRINTER_INFO_3!\n");
02569                 result = False;
02570                 goto done;
02571         }
02572         
02573         sd1 = ctr1.printers_3->secdesc;
02574         sd2 = ctr2.printers_3->secdesc;
02575         
02576         if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) {
02577                 printf("NULL secdesc!\n");
02578                 result = False;
02579                 goto done;
02580         }
02581         
02582         if (!sec_desc_equal( sd1, sd2 ) ) {
02583                 printf("Security Descriptors *not* equal!\n");
02584                 result = False;
02585                 goto done;
02586         }
02587         
02588         printf("Security descriptors match\n");
02589         
02590 done:
02591         talloc_destroy(mem_ctx);
02592         return result;
02593 }
02594 
02595 
02596 /****************************************************************************
02597 ****************************************************************************/
02598 
02599 static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli, 
02600                                      TALLOC_CTX *mem_ctx, int argc, 
02601                                      const char **argv)
02602 {
02603         fstring printername, servername1, servername2;
02604         pstring printername_path;
02605         struct cli_state *cli_server1 = cli->cli;
02606         struct cli_state *cli_server2 = NULL;
02607         struct rpc_pipe_client *cli2 = NULL;
02608         POLICY_HND hPrinter1, hPrinter2;
02609         NTSTATUS nt_status;
02610         WERROR werror;
02611         
02612         if ( argc != 3 )  {
02613                 printf("Usage: %s <printer> <server>\n", argv[0]);
02614                 return WERR_OK;
02615         }
02616         
02617         fstrcpy( printername, argv[1] );
02618         
02619         fstrcpy( servername1, cli->cli->desthost );
02620         fstrcpy( servername2, argv[2] );
02621         strupper_m( servername1 );
02622         strupper_m( servername2 );
02623         
02624         
02625         /* first get the connection to the remote server */
02626         
02627         nt_status = cli_full_connection(&cli_server2, global_myname(), servername2, 
02628                                         NULL, 0,
02629                                         "IPC$", "IPC",  
02630                                         cmdline_auth_info.username, 
02631                                         lp_workgroup(),
02632                                         cmdline_auth_info.password, 
02633                                         cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0,
02634                                         cmdline_auth_info.signing_state, NULL);
02635                                         
02636         if ( !NT_STATUS_IS_OK(nt_status) )
02637                 return WERR_GENERAL_FAILURE;
02638 
02639         cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status);
02640         if (!cli2) {
02641                 printf("failed to open spoolss pipe on server %s (%s)\n",
02642                         servername2, nt_errstr(nt_status));
02643                 return WERR_GENERAL_FAILURE;
02644         }
02645                                         
02646         /* now open up both printers */
02647 
02648         pstr_sprintf( printername_path, "\\\\%s\\%s", servername1, printername );
02649         printf("Opening %s...", printername_path);
02650         werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path, 
02651                 "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1);
02652         if ( !W_ERROR_IS_OK(werror) ) {
02653                 printf("failed (%s)\n", dos_errstr(werror));
02654                 goto done;
02655         }
02656         printf("ok\n");
02657         
02658         pstr_sprintf( printername_path, "\\\\%s\\%s", servername2, printername );
02659         printf("Opening %s...", printername_path);
02660         werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path,  
02661                 "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 );
02662         if ( !W_ERROR_IS_OK(werror) ) {
02663                  printf("failed (%s)\n", dos_errstr(werror));
02664                 goto done;
02665         }
02666         printf("ok\n");
02667         
02668         
02669         compare_printer( cli, &hPrinter1, cli2, &hPrinter2 );
02670         compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 );
02671 #if 0
02672         compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 );
02673 #endif
02674 
02675 
02676 done:
02677         /* cleanup */
02678 
02679         printf("Closing printers...");  
02680         rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 );
02681         rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 );
02682         printf("ok\n");
02683         
02684         /* close the second remote connection */
02685         
02686         cli_shutdown( cli_server2 );
02687         
02688         return WERR_OK;
02689 }
02690 
02691 /* List of commands exported by this module */
02692 struct cmd_set spoolss_commands[] = {
02693 
02694         { "SPOOLSS"  },
02695 
02696         { "adddriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver,   PI_SPOOLSS, NULL, "Add a print driver",                  "" },
02697         { "addprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex,       PI_SPOOLSS, NULL, "Add a printer",                       "" },
02698         { "deldriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver,       PI_SPOOLSS, NULL, "Delete a printer driver",             "" },
02699         { "deldriverex",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex,     PI_SPOOLSS, NULL, "Delete a printer driver with files",  "" },
02700         { "enumdata",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data,          PI_SPOOLSS, NULL, "Enumerate printer data",              "" },
02701         { "enumdataex",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex,       PI_SPOOLSS, NULL, "Enumerate printer data for a key",    "" },
02702         { "enumkey",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey,    PI_SPOOLSS, NULL, "Enumerate printer keys",              "" },
02703         { "enumjobs",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs,          PI_SPOOLSS, NULL, "Enumerate print jobs",                "" },
02704         { "enumports",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports,         PI_SPOOLSS, NULL, "Enumerate printer ports",             "" },
02705         { "enumdrivers",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers,       PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" },
02706         { "enumprinters",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers,      PI_SPOOLSS, NULL, "Enumerate printers",                  "" },
02707         { "getdata",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata,     PI_SPOOLSS, NULL, "Get print driver data",               "" },
02708         { "getdataex",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex,   PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""},
02709         { "getdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver,          PI_SPOOLSS, NULL, "Get print driver information",        "" },
02710         { "getdriverdir",       RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir,       PI_SPOOLSS, NULL, "Get print driver upload directory",   "" },
02711         { "getprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter,         PI_SPOOLSS, NULL, "Get printer info",                    "" },
02712         { "openprinter",        RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex,    PI_SPOOLSS, NULL, "Open printer handle",                 "" },
02713         { "setdriver",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver,          PI_SPOOLSS, NULL, "Set printer driver",                  "" },
02714         { "getprintprocdir",    RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir,    PI_SPOOLSS, NULL, "Get print processor directory",       "" },
02715         { "addform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform,            PI_SPOOLSS, NULL, "Add form",                            "" },
02716         { "setform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform,            PI_SPOOLSS, NULL, "Set form",                            "" },
02717         { "getform",            RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform,            PI_SPOOLSS, NULL, "Get form",                            "" },
02718         { "deleteform",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform,         PI_SPOOLSS, NULL, "Delete form",                         "" },
02719         { "enumforms",          RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms,         PI_SPOOLSS, NULL, "Enumerate forms",                     "" },
02720         { "setprinter",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter,         PI_SPOOLSS, NULL, "Set printer comment",                 "" },
02721         { "setprintername",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername,     PI_SPOOLSS, NULL, "Set printername",                 "" },
02722         { "setprinterdata",     RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata,     PI_SPOOLSS, NULL, "Set REG_SZ printer data",             "" },
02723         { "rffpcnex",           RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex,           PI_SPOOLSS, NULL, "Rffpcnex test", "" },
02724         { "printercmp",         RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp,         PI_SPOOLSS, NULL, "Printer comparison test", "" },
02725 
02726         { NULL }
02727 };

Sambaに対してSat Aug 29 21:23:23 2009に生成されました。  doxygen 1.4.7