From 3eff1f48d5806aeb0347f13c50e7620bbdc04dd5 Mon Sep 17 00:00:00 2001 From: Günther Deschner Date: Wed, 13 Oct 2004 01:40:35 +0000 Subject: r2942: Add client-side support of triggering ads printer publishing over msrpc 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/utils/net_help.c | 3 + source3/utils/net_rpc.c | 102 ++++++++++++++++++++++ source3/utils/net_rpc_printer.c | 188 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 293 insertions(+) (limited to 'source3/utils') diff --git a/source3/utils/net_help.c b/source3/utils/net_help.c index 4b19bcf5aa..cc5208b821 100644 --- a/source3/utils/net_help.c +++ b/source3/utils/net_help.c @@ -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]"\ diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index 018731afda..295c8c5853 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -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} }; diff --git a/source3/utils/net_rpc_printer.c b/source3/utils/net_rpc_printer.c index f470d8b6d9..a7e0ebeb6c 100644 --- a/source3/utils/net_rpc_printer.c +++ b/source3/utils/net_rpc_printer.c @@ -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 -- cgit