2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean Francois Micouleau 1998-2000,
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "rpc_parse.h"
29 #define DBGC_CLASS DBGC_RPC_CLI
31 extern pstring global_myname;
33 struct msg_info_table {
37 void (*construct_fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
38 print_queue_struct *queue,
39 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
42 struct msg_info_table msg_table[] = {
43 { PRINTER_MESSAGE_DRIVER, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_MESSAGE_DRIVER", spoolss_notify_driver_name },
44 { PRINTER_MESSAGE_ATTRIBUTES, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_MESSAGE_ATTRIBUTES", spoolss_notify_attributes },
45 { PRINTER_MESSAGE_COMMENT, PRINTER_NOTIFY_COMMENT, "PRINTER_MESSAGE_COMMENT", spoolss_notify_comment },
46 { PRINTER_MESSAGE_LOCATION, PRINTER_NOTIFY_LOCATION, "PRINTER_MESSAGE_LOCATION", spoolss_notify_location },
47 { PRINTER_MESSAGE_PRINTERNAME, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_MESSAGE_PRINTERNAME", spoolss_notify_printer_name },
48 { PRINTER_MESSAGE_SHARENAME, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_MESSAGE_SHARENAME", spoolss_notify_share_name },
49 { PRINTER_MESSAGE_PORT, PRINTER_NOTIFY_PORT_NAME, "PRINTER_MESSAGE_PORT", spoolss_notify_port_name },
50 { PRINTER_MESSAGE_CJOBS, PRINTER_NOTIFY_CJOBS, "PRINTER_MESSAGE_CJOBS", spoolss_notify_cjobs },
51 { PRINTER_MESSAGE_SEPFILE, PRINTER_NOTIFY_SEPFILE, "PRINTER_MESSAGE_SEPFILE", spoolss_notify_sepfile },
52 { PRINTER_MESSAGE_PARAMS, PRINTER_NOTIFY_PARAMETERS, "PRINTER_MESSAGE_PARAMETERS", spoolss_notify_parameters },
53 { PRINTER_MESSAGE_DATATYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_MESSAGE_DATATYPE", spoolss_notify_datatype },
54 { PRINTER_MESSAGE_NULL, 0x0, "", NULL },
57 /*********************************************************
58 Disconnect from the client machine.
59 **********************************************************/
60 BOOL spoolss_disconnect_from_client( struct cli_state *cli)
62 cli_nt_session_close(cli);
70 /*********************************************************
71 Connect to the client machine.
72 **********************************************************/
74 BOOL spoolss_connect_to_client( struct cli_state *cli, char *remote_machine)
77 if(cli_initialise(cli) == NULL) {
78 DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
82 if(!resolve_name( remote_machine, &cli->dest_ip, 0x20)) {
83 DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
88 if (ismyip(cli->dest_ip)) {
89 DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
94 if (!cli_connect(cli, remote_machine, &cli->dest_ip)) {
95 DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
100 if (!attempt_netbios_session_request(cli, global_myname, remote_machine, &cli->dest_ip)) {
101 DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
106 cli->protocol = PROTOCOL_NT1;
108 if (!cli_negprot(cli)) {
109 DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
114 if (cli->protocol != PROTOCOL_NT1) {
115 DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
121 * Do an anonymous session setup.
124 if (!cli_session_setup(cli, "", "", 0, "", 0, "")) {
125 DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
130 if (!(cli->sec_mode & NEGOTIATE_SECURITY_USER_LEVEL)) {
131 DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
136 if (!cli_send_tconX(cli, "IPC$", "IPC", "", 1)) {
137 DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(cli) ));
143 * Ok - we have an anonymous connection to the IPC$ share.
144 * Now start the NT Domain stuff :-).
147 if(cli_nt_session_open(cli, PIPE_SPOOLSS) == False) {
148 DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(cli)));
149 cli_nt_session_close(cli);
159 * SPOOLSS Client RPC's used by servers as the notification
163 /***************************************************************************
164 do a reply open printer
165 ****************************************************************************/
167 WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
168 char *printer, uint32 localprinter, uint32 type,
171 WERROR result = W_ERROR(ERRgeneral);
176 SPOOL_Q_REPLYOPENPRINTER q_s;
177 SPOOL_R_REPLYOPENPRINTER r_s;
179 prs_init(&buf, 1024, mem_ctx, MARSHALL);
180 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL );
182 /* create and send a MSRPC command with api SPOOLSS_REPLYOPENPRINTER */
184 /* store the parameters */
185 make_spoolss_q_replyopenprinter(&q_s, printer, localprinter, type);
187 /* turn parameters into data stream */
188 if(!spoolss_io_q_replyopenprinter("", &q_s, &buf, 0)) {
189 DEBUG(0,("cli_spoolss_reply_open_printer: Error : failed to marshall SPOOL_Q_REPLYOPENPRINTER struct.\n"));
193 /* send the data on \PIPE\ */
194 if (!rpc_api_pipe_req(cli, SPOOLSS_REPLYOPENPRINTER, &buf, &rbuf))
197 /* turn data stream into parameters*/
198 if(!spoolss_io_r_replyopenprinter("", &r_s, &rbuf, 0)) {
199 DEBUG(0,("cli_spoolss_reply_open_printer: Error : failed to unmarshall SPOOL_R_REPLYOPENPRINTER struct.\n"));
203 memcpy(handle, &r_s.handle, sizeof(r_s.handle));
213 /***************************************************************************
214 do a reply open printer
215 ****************************************************************************/
217 WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx,
220 WERROR result = W_ERROR(ERRgeneral);
224 SPOOL_Q_REPLYCLOSEPRINTER q_s;
225 SPOOL_R_REPLYCLOSEPRINTER r_s;
227 prs_init(&buf, 1024, cli->mem_ctx, MARSHALL);
228 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL );
230 /* create and send a MSRPC command with api */
232 /* store the parameters */
233 make_spoolss_q_reply_closeprinter(&q_s, handle);
235 /* turn parameters into data stream */
236 if(!spoolss_io_q_replycloseprinter("", &q_s, &buf, 0)) {
237 DEBUG(0,("cli_spoolss_reply_close_printer: Error : failed to marshall SPOOL_Q_REPLY_CLOSEPRINTER struct.\n"));
241 /* send the data on \PIPE\ */
242 if (!rpc_api_pipe_req(cli, SPOOLSS_REPLYCLOSEPRINTER, &buf, &rbuf))
245 /* turn data stream into parameters*/
246 if(!spoolss_io_r_replycloseprinter("", &r_s, &rbuf, 0)) {
247 DEBUG(0,("cli_spoolss_reply_close_printer: Error : failed to marshall SPOOL_R_REPLY_CLOSEPRINTER struct.\n"));
262 /*********************************************************************
263 This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change
264 notification event when the registration **did not** use
265 SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor.
266 Also see cli_spolss_reply_rrpcn()
267 *********************************************************************/
269 WERROR cli_spoolss_routerreplyprinter (struct cli_state *cli, TALLOC_CTX *mem_ctx,
270 POLICY_HND *pol, uint32 condition, uint32 changd_id)
272 prs_struct qbuf, rbuf;
273 SPOOL_Q_ROUTERREPLYPRINTER q;
274 SPOOL_R_ROUTERREPLYPRINTER r;
275 WERROR result = W_ERROR(ERRgeneral);
281 /* Initialise input parameters */
283 prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL);
284 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL);
287 /* write the request */
288 make_spoolss_q_routerreplyprinter(&q, pol, condition, changd_id);
290 /* Marshall data and send request */
291 if (!spoolss_io_q_routerreplyprinter ("", &q, &qbuf, 0)) {
292 DEBUG(0,("cli_spoolss_routerreplyprinter: Unable to marshall SPOOL_Q_ROUTERREPLYPRINTER!\n"));
297 if (!rpc_api_pipe_req (cli, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf))
300 /* Unmarshall response */
301 if (!spoolss_io_r_routerreplyprinter ("", &r, &rbuf, 0)) {
302 DEBUG(0,("cli_spoolss_routerreplyprinter: Unable to unmarshall SPOOL_R_ROUTERREPLYPRINTER!\n"));
306 /* Return output parameters */
317 /**********************************************************************************
318 Build the SPOOL_NOTIFY_INFO_DATA entries based upon the flags which have been set
319 *********************************************************************************/
321 static int build_notify_data (TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer, uint32 flags,
322 SPOOL_NOTIFY_INFO_DATA **notify_data)
324 SPOOL_NOTIFY_INFO_DATA *data;
328 while ((msg_table[i].msg != PRINTER_MESSAGE_NULL) && flags)
330 if (flags & msg_table[i].msg)
332 DEBUG(10,("build_notify_data: %s set on [%s][%d]\n", msg_table[i].name,
333 printer->info_2->printername, idx));
334 if ((data=Realloc(*notify_data, (idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
335 DEBUG(0,("build_notify_data: Realloc() failed with size [%d]!\n",
336 (idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA)));
342 memset(*notify_data+idx, 0x0, sizeof(SPOOL_NOTIFY_INFO_DATA));
345 * 'id' (last param here) is undefined when type == PRINTER_NOTIFY_TYPE
346 * See PRINTER_NOTIFY_INFO_DATA entries in MSDN
349 construct_info_data(*notify_data+idx, PRINTER_NOTIFY_TYPE, msg_table[i].field, 0x00);
351 msg_table[i].construct_fn(-1, *notify_data+idx, NULL, printer, ctx);
361 /*********************************************************************
362 This SPOOLSS_ROUTERREPLYPRINTER function is used to send a change
363 notification event when the registration **did** use
364 SPOOL_NOTIFY_OPTION_TYPE structure to specify the events to monitor
365 Also see cli_spoolss_routereplyprinter()
366 *********************************************************************/
368 WERROR cli_spoolss_reply_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx,
369 POLICY_HND *handle, PRINTER_MESSAGE_INFO *info,
370 NT_PRINTER_INFO_LEVEL *printer)
375 SPOOL_NOTIFY_INFO notify_info;
376 SPOOL_NOTIFY_INFO_DATA *notify_data = NULL;
379 WERROR result = W_ERROR(ERRgeneral);
381 SPOOL_Q_REPLY_RRPCN q_s;
382 SPOOL_R_REPLY_RRPCN r_s;
385 DEBUG(5,("cli_spoolss_reply_rrpcn: NULL printer message info pointer!\n"));
389 prs_init(&buf, 1024, mem_ctx, MARSHALL);
390 prs_init(&rbuf, 0, mem_ctx, UNMARSHALL );
392 ZERO_STRUCT(notify_info);
395 * See comments in _spoolss_setprinter() about PRINTER_CHANGE_XXX
398 DEBUG(10,("cli_spoolss_reply_rrpcn: PRINTER_MESSAGE flags = 0x%8x\n", info->flags));
400 data_len = build_notify_data(mem_ctx, printer, info->flags, ¬ify_data);
401 if (info->flags && (data_len == -1)) {
402 DEBUG(0,("cli_spoolss_reply_rrpcn: Failed to build SPOOL_NOTIFY_INFO_DATA [flags == 0x%x] for printer [%s]\n",
403 info->flags, info->printer_name));
407 notify_info.version = 0x2;
408 notify_info.flags = 0x00020000; /* ?? */
409 notify_info.count = data_len;
410 notify_info.data = notify_data;
412 /* create and send a MSRPC command with api */
413 /* store the parameters */
415 make_spoolss_q_reply_rrpcn(&q_s, handle, info->low, info->high, ¬ify_info);
417 /* turn parameters into data stream */
418 if(!spoolss_io_q_reply_rrpcn("", &q_s, &buf, 0)) {
419 DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to marshall SPOOL_Q_REPLY_RRPCN struct.\n"));
423 /* send the data on \PIPE\ */
424 if (!rpc_api_pipe_req(cli, SPOOLSS_RRPCN, &buf, &rbuf))
428 /* turn data stream into parameters*/
429 if(!spoolss_io_r_reply_rrpcn("", &r_s, &rbuf, 0)) {
430 DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to unmarshall SPOOL_R_REPLY_RRPCN struct.\n"));
434 if (r_s.unknown0 == 0x00080000) {
435 DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n"));
444 * The memory allocated in this array is talloc'd so we only need
445 * free the array here. JRA.
447 SAFE_FREE(notify_data);