r2942: Add client-side support of triggering ads printer publishing over msrpc
authorGünther Deschner <gd@samba.org>
Wed, 13 Oct 2004 01:40:35 +0000 (01:40 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 15:52:57 +0000 (10:52 -0500)
setprinter calls inside the net-tool.

This is usefull to mimic the same queries a windows-client does. At
least win2k returns WERR_IO_PENDING when printer is published via
setprinter, samba returns WERR_OK but this does not hurt.

Guenther
(This used to be commit 69b745fb98b8054d1f52e8a3fe3b933fb04336db)

source3/include/doserr.h
source3/libsmb/doserr.c
source3/utils/net_help.c
source3/utils/net_rpc.c
source3/utils/net_rpc_printer.c

index 576aeda2bf79bf12bca9c568fe5c63ce7de0b305..c6d6b1fac90c982795893b07bf558fb03bd3fa38 100644 (file)
 #define WERR_NO_MORE_ITEMS W_ERROR(259)
 #define WERR_MORE_DATA W_ERROR(234)
 #define WERR_INVALID_OWNER W_ERROR(1307)
+#define WERR_IO_PENDING W_ERROR(997)
 #define WERR_CAN_NOT_COMPLETE W_ERROR(1003)
 #define WERR_INVALID_SECURITY_DESCRIPTOR W_ERROR(1338)
 #define WERR_SERVER_UNAVAILABLE W_ERROR(1722)
index c6348568cf957ace636fcc9c7d14c8f30e79d843..96c052c7c56d25b43c6227816818a0ca34545c7a 100644 (file)
@@ -68,6 +68,7 @@ werror_code_struct dos_errs[] =
        { "WERR_INVALID_SECURITY_DESCRIPTOR", WERR_INVALID_SECURITY_DESCRIPTOR },
        { "WERR_INVALID_OWNER", WERR_INVALID_OWNER },
        { "WERR_SERVER_UNAVAILABLE", WERR_SERVER_UNAVAILABLE },
+       { "WERR_IO_PENDING", WERR_IO_PENDING },
        { NULL, W_ERROR(0) }
 };
 
index 4b19bcf5aa703248ddaf4ced4a73b435638dc829..cc5208b821fe38d6db7c2a1c2e48ff4e125d006c 100644 (file)
@@ -176,6 +176,9 @@ int net_help_printer(int argc, const char **argv)
                 "\tlists all printers on print-server\n\n");
        d_printf("net rpc printer DRIVER [printer] [misc. options] [targets]\n"\
                 "\tlists all printer-drivers on print-server\n\n");
+       d_printf("net rpc printer PUBLISH action [printer] [misc. options] [targets]\n"\
+                "\tpublishes printer settings in Active Directory\n"
+                "\taction can be one of PUBLISH, UPDATE, UNPUBLISH or LIST\n\n");
        d_printf("net rpc printer MIGRATE PRINTERS [printer] [misc. options] [targets]"\
                 "\n\tmigrates printers from remote to local server\n\n");
        d_printf("net rpc printer MIGRATE SETTINGS [printer] [misc. options] [targets]"\
index 018731afdaafc6e0730f1664e924209784ddd9f5..295c8c5853f312423001315c3b926063e35400b3 100644 (file)
@@ -3,6 +3,7 @@
    Distributed SMB/CIFS Server Management Utility 
    Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org)
    Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com)
+   Copyright (C) 2004 Guenther Deschner (gd@samba.org)
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -5044,6 +5045,106 @@ static int rpc_printer_driver_list(int argc, const char **argv)
                               argc, argv);
 }
 
+/** 
+ * Publish printer in ADS via MSRPC
+ *
+ * @param argc  Standard main() style argc
+ * @param argv  Standard main() style argv.  Initial components are already
+ *              stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_publish_publish(int argc, const char **argv)
+{
+
+       return run_rpc_command(NULL, PI_SPOOLSS, 0, 
+                              rpc_printer_publish_publish_internals,
+                              argc, argv);
+}
+
+/** 
+ * Update printer in ADS via MSRPC
+ *
+ * @param argc  Standard main() style argc
+ * @param argv  Standard main() style argv.  Initial components are already
+ *              stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_publish_update(int argc, const char **argv)
+{
+
+       return run_rpc_command(NULL, PI_SPOOLSS, 0, 
+                              rpc_printer_publish_update_internals,
+                              argc, argv);
+}
+
+/** 
+ * UnPublish printer in ADS via MSRPC
+ *
+ * @param argc  Standard main() style argc
+ * @param argv  Standard main() style argv.  Initial components are already
+ *              stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_publish_unpublish(int argc, const char **argv)
+{
+
+       return run_rpc_command(NULL, PI_SPOOLSS, 0, 
+                              rpc_printer_publish_unpublish_internals,
+                              argc, argv);
+}
+
+/** 
+ * List published printers via MSRPC
+ *
+ * @param argc  Standard main() style argc
+ * @param argv  Standard main() style argv.  Initial components are already
+ *              stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_publish_list(int argc, const char **argv)
+{
+
+       return run_rpc_command(NULL, PI_SPOOLSS, 0, 
+                              rpc_printer_publish_list_internals,
+                              argc, argv);
+}
+
+
+/** 
+ * Publish printer in ADS
+ *
+ * @param argc  Standard main() style argc
+ * @param argv  Standard main() style argv.  Initial components are already
+ *              stripped
+ *
+ * @return A shell status integer (0 for success)
+ **/
+static int rpc_printer_publish(int argc, const char **argv)
+{
+
+       struct functable func[] = {
+               {"publish",     rpc_printer_publish_publish},
+               {"update",      rpc_printer_publish_update},
+               {"unpublish",   rpc_printer_publish_unpublish},
+               {"list",        rpc_printer_publish_list},
+               {"help",        rpc_printer_usage},
+               {NULL, NULL}
+       };
+
+       if (argc == 0)
+               return run_rpc_command(NULL, PI_SPOOLSS, 0, 
+                              rpc_printer_publish_list_internals,
+                              argc, argv);
+
+       return net_run_function(argc, argv, func, rpc_printer_usage);
+
+}
+
+
 /** 
  * Display rpc printer help page.
  * @param argc  Standard main() style argc
@@ -5067,6 +5168,7 @@ int net_rpc_printer(int argc, const char **argv)
                {"list", rpc_printer_list},
                {"migrate", rpc_printer_migrate},
                {"driver", rpc_printer_driver_list},
+               {"publish", rpc_printer_publish},
                {NULL, NULL}
        };
 
index f470d8b6d94a1b96ffd234021dd0bc4fc3cc6954..a7e0ebeb6caf665290fd8b33868cf3674f10072f 100644 (file)
@@ -1288,6 +1288,194 @@ done:
 
 }
 
+/** 
+ * Publish print-queues with args-wrapper
+ *
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc  Standard main() style argc
+ * @param argv  Standard main() style argv.  Initial components are already
+ *              stripped
+ * @param action
+ *
+ * @return Normal NTSTATUS return.
+ **/
+
+static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+                                                  int argc, const char **argv, uint32 action)
+{
+       NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+       uint32 i, num_printers; 
+       uint32 level = 7;
+       pstring printername, sharename;
+       PRINTER_INFO_CTR ctr, ctr_pub;
+       POLICY_HND hnd;
+       BOOL got_hnd = False;
+       WERROR result;
+       char *action_str;
+
+       if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr))
+               return nt_status;
+
+       for (i = 0; i < num_printers; i++) {
+
+               /* do some initialization */
+               rpcstr_pull(printername, ctr.printers_2[i].printername.buffer, 
+                       sizeof(printername), -1, STR_TERMINATE);
+               rpcstr_pull(sharename, ctr.printers_2[i].sharename.buffer, 
+                       sizeof(sharename), -1, STR_TERMINATE);
+
+               /* open printer handle */
+               if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
+                       PRINTER_ALL_ACCESS, cli->user_name, &hnd)) 
+                       goto done;
+
+               got_hnd = True;
+
+               /* check for existing dst printer */
+               if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, &ctr_pub)) 
+                       goto done;
+
+               /* check action and set string */
+               switch (action) {
+               case SPOOL_DS_PUBLISH:
+                       action_str = "published";
+                       break;
+               case SPOOL_DS_UPDATE:
+                       action_str = "updated";
+                       break;
+               case SPOOL_DS_UNPUBLISH:
+                       action_str = "unpublished";
+                       break;
+               default:
+                       printf("unkown action: %d\n", action);
+                       break;
+               }
+
+               ctr_pub.printers_7->action = action;
+
+               result = cli_spoolss_setprinter(cli, mem_ctx, &hnd, level, &ctr_pub, 0);
+               if (!W_ERROR_IS_OK(result) && (W_ERROR_V(result) =! W_ERROR_V(WERR_IO_PENDING))) {
+                       printf("cannot set printer-info: %s\n", dos_errstr(result));
+                       goto done;
+               }
+
+               printf("successfully %s printer %s in Active Directory\n", action_str, sharename);
+       }
+
+       nt_status = NT_STATUS_OK;
+
+done:
+       if (got_hnd) 
+               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+       
+       return nt_status;
+}
+
+NTSTATUS rpc_printer_publish_publish_internals(const DOM_SID *domain_sid, const char *domain_name, 
+                                              struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+                                              int argc, const char **argv)
+{
+       return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_PUBLISH);
+}
+
+NTSTATUS rpc_printer_publish_unpublish_internals(const DOM_SID *domain_sid, const char *domain_name, 
+                                                struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+                                                int argc, const char **argv)
+{
+       return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_UNPUBLISH);
+}
+
+NTSTATUS rpc_printer_publish_update_internals(const DOM_SID *domain_sid, const char *domain_name, 
+                                             struct cli_state *cli, TALLOC_CTX *mem_ctx, 
+                                             int argc, const char **argv)
+{
+       return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_UPDATE);
+}
+
+/** 
+ * List print-queues w.r.t. thei publishing
+ *
+ * All parameters are provided by the run_rpc_command function, except for
+ * argc, argv which are passed through. 
+ *
+ * @param domain_sid The domain sid aquired from the remote server
+ * @param cli A cli_state connected to the server.
+ * @param mem_ctx Talloc context, destoyed on compleation of the function.
+ * @param argc  Standard main() style argc
+ * @param argv  Standard main() style argv.  Initial components are already
+ *              stripped
+ *
+ * @return Normal NTSTATUS return.
+ **/
+NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid, const char *domain_name, 
+                                           struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                           int argc, const char **argv)
+{
+       NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+       uint32 i, num_printers; 
+       uint32 level = 7;
+       pstring printername, sharename;
+       pstring guid;
+       PRINTER_INFO_CTR ctr, ctr_pub;
+       POLICY_HND hnd;
+       BOOL got_hnd = False;
+       int state;
+
+       if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr))
+               return nt_status;
+
+       for (i = 0; i < num_printers; i++) {
+
+               ZERO_STRUCT(ctr_pub);
+
+               /* do some initialization */
+               rpcstr_pull(printername, ctr.printers_2[i].printername.buffer, 
+                       sizeof(printername), -1, STR_TERMINATE);
+               rpcstr_pull(sharename, ctr.printers_2[i].sharename.buffer, 
+                       sizeof(sharename), -1, STR_TERMINATE);
+
+               /* open printer handle */
+               if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename,
+                       PRINTER_ALL_ACCESS, cli->user_name, &hnd)) 
+                       goto done;
+
+               got_hnd = True;
+
+               /* check for existing dst printer */
+               if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, &ctr_pub)) 
+                       goto done;
+
+               rpcstr_pull(guid, ctr_pub.printers_7->guid.buffer, sizeof(guid), -1, STR_TERMINATE);
+
+               state = ctr_pub.printers_7->action;
+               switch (state) {
+                       case SPOOL_DS_PUBLISH:
+                               printf("printer [%s] is published", sharename);
+                               if (opt_verbose)
+                                       printf(", guid: %s", guid);
+                               printf("\n");
+                               break;
+                       case SPOOL_DS_UNPUBLISH:
+                               printf("printer [%s] is unpublished\n", sharename);
+                               break;
+                       case SPOOL_DS_UPDATE:
+                               printf("printer [%s] is currently updating\n", sharename);
+                               break;
+                       default:
+                               printf("unkown state: %d\n", state);
+                               break;
+               }
+       }
+
+       nt_status = NT_STATUS_OK;
+
+done:
+       if (got_hnd) 
+               cli_spoolss_close_printer(cli, mem_ctx, &hnd);
+       
+       return nt_status;
+}
 
 /** 
  * Migrate Printer-ACLs from a source server to the destination server