2 Unix SMB/Netbios implementation.
6 Copyright (C) Gerald Carter 2001,
7 Copyright (C) Tim Potter 2000,
8 Copyright (C) Andrew Tridgell 1994-2000
9 Copyright (C) Luke Kenneth Casson Leighton 1996-2000
10 Copyright (C) Jean-Francois Micouleau 1999-2000
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 extern pstring global_myname;
31 /* Opens a SMB connection to the SPOOLSS pipe */
32 struct cli_state *cli_spoolss_initialise(struct cli_state *cli,
34 struct ntuser_creds *creds)
36 struct in_addr dest_ip;
37 struct nmb_name calling, called;
39 extern pstring global_myname;
40 struct ntuser_creds anon;
42 /* Initialise cli_state information */
44 if (!cli_initialise(cli)) {
50 anon.pwd.null_pwd = 1;
54 cli_init_creds(cli, creds);
56 /* Establish a SMB connection */
58 if (!resolve_srv_name(system_name, dest_host, &dest_ip)) {
62 make_nmb_name(&called, dns_to_netbios_name(dest_host), 0x20);
63 make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
65 if (!cli_establish_connection(cli, dest_host, &dest_ip, &calling,
66 &called, "IPC$", "IPC", False, True)) {
70 /* Open a NT session thingy */
72 if (!cli_nt_session_open(cli, PIPE_SPOOLSS)) {
80 /* Shut down a SMB connection to the SPOOLSS pipe */
82 void cli_spoolss_shutdown(struct cli_state *cli)
84 if (cli->fd != -1) cli_ulogoff(cli);
90 uint32 cli_spoolss_open_printer_ex(struct cli_state *cli, char *printername,
91 char *datatype, uint32 access_required,
92 char *station, char *username,
95 prs_struct qbuf, rbuf;
96 SPOOL_Q_OPEN_PRINTER_EX q;
97 SPOOL_R_OPEN_PRINTER_EX r;
103 /* Initialise parse structures */
105 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
106 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
108 /* Initialise input parameters */
110 make_spoolss_q_open_printer_ex(&q, printername, datatype,
111 access_required, station, username);
113 /* Marshall data and send request */
115 if (!spoolss_io_q_open_printer_ex("", &q, &qbuf, 0) ||
116 !rpc_api_pipe_req(cli, SPOOLSS_OPENPRINTEREX, &qbuf, &rbuf)) {
117 result = NT_STATUS_UNSUCCESSFUL;
121 /* Unmarshall response */
123 if (!spoolss_io_r_open_printer_ex("", &r, &rbuf, 0)) {
124 result = NT_STATUS_UNSUCCESSFUL;
128 /* Return output parameters */
130 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
141 /* Close a printer handle */
143 uint32 cli_spoolss_close_printer(struct cli_state *cli, POLICY_HND *pol)
145 prs_struct qbuf, rbuf;
146 SPOOL_Q_CLOSEPRINTER q;
147 SPOOL_R_CLOSEPRINTER r;
153 /* Initialise parse structures */
155 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
156 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
158 /* Initialise input parameters */
160 make_spoolss_q_closeprinter(&q, pol);
162 /* Marshall data and send request */
164 if (!spoolss_io_q_closeprinter("", &q, &qbuf, 0) ||
165 !rpc_api_pipe_req(cli, SPOOLSS_CLOSEPRINTER, &qbuf, &rbuf)) {
166 result = NT_STATUS_UNSUCCESSFUL;
170 /* Unmarshall response */
172 if (!spoolss_io_r_closeprinter("", &r, &rbuf, 0)) {
173 result = NT_STATUS_UNSUCCESSFUL;
177 /* Return output parameters */
179 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
190 /* Initialize a spoolss NEW_BUFFER */
192 static void init_buffer(NEW_BUFFER *buffer, uint32 size, TALLOC_CTX *ctx)
194 buffer->ptr = (size != 0);
196 buffer->string_at_end = size;
197 prs_init(&buffer->prs, size, ctx, MARSHALL);
198 buffer->struct_start = prs_offset(&buffer->prs);
201 /* Decode various printer info levels - perhaps this should live in
204 static void decode_printer_info_0(NEW_BUFFER *buffer, uint32 returned,
205 PRINTER_INFO_0 **info)
210 inf=(PRINTER_INFO_0 *)malloc(returned*sizeof(PRINTER_INFO_0));
212 buffer->prs.data_offset=0;
214 for (i=0; i<returned; i++) {
215 smb_io_printer_info_0("", buffer, &inf[i], 0);
221 static void decode_printer_info_1(NEW_BUFFER *buffer, uint32 returned,
222 PRINTER_INFO_1 **info)
227 inf=(PRINTER_INFO_1 *)malloc(returned*sizeof(PRINTER_INFO_1));
229 buffer->prs.data_offset=0;
231 for (i=0; i<returned; i++) {
232 smb_io_printer_info_1("", buffer, &inf[i], 0);
238 static void decode_printer_info_2(NEW_BUFFER *buffer, uint32 returned,
239 PRINTER_INFO_2 **info)
244 inf=(PRINTER_INFO_2 *)malloc(returned*sizeof(PRINTER_INFO_2));
246 buffer->prs.data_offset=0;
248 for (i=0; i<returned; i++) {
249 /* a little initialization as we go */
250 inf[i].secdesc = NULL;
251 smb_io_printer_info_2("", buffer, &inf[i], 0);
257 static void decode_printer_info_3(NEW_BUFFER *buffer, uint32 returned,
258 PRINTER_INFO_3 **info)
263 inf=(PRINTER_INFO_3 *)malloc(returned*sizeof(PRINTER_INFO_3));
265 buffer->prs.data_offset=0;
267 for (i=0; i<returned; i++) {
268 inf[i].secdesc = NULL;
269 smb_io_printer_info_3("", buffer, &inf[i], 0);
275 /**********************************************************************
276 Decode a PORT_INFO_1 struct from a NEW_BUFFER
277 **********************************************************************/
278 static void decode_port_info_1(NEW_BUFFER *buffer, uint32 returned,
284 inf=(PORT_INFO_1*)malloc(returned*sizeof(PORT_INFO_1));
286 prs_set_offset(&buffer->prs, 0);
288 for (i=0; i<returned; i++) {
289 smb_io_port_info_1("", buffer, &(inf[i]), 0);
295 /**********************************************************************
296 Decode a PORT_INFO_2 struct from a NEW_BUFFER
297 **********************************************************************/
298 static void decode_port_info_2(NEW_BUFFER *buffer, uint32 returned,
304 inf=(PORT_INFO_2*)malloc(returned*sizeof(PORT_INFO_2));
306 prs_set_offset(&buffer->prs, 0);
308 for (i=0; i<returned; i++) {
309 smb_io_port_info_2("", buffer, &(inf[i]), 0);
315 static void decode_printer_driver_1(NEW_BUFFER *buffer, uint32 returned,
316 DRIVER_INFO_1 **info)
321 inf=(DRIVER_INFO_1 *)malloc(returned*sizeof(DRIVER_INFO_1));
323 buffer->prs.data_offset=0;
325 for (i=0; i<returned; i++) {
326 smb_io_printer_driver_info_1("", buffer, &(inf[i]), 0);
332 static void decode_printer_driver_2(NEW_BUFFER *buffer, uint32 returned,
333 DRIVER_INFO_2 **info)
338 inf=(DRIVER_INFO_2 *)malloc(returned*sizeof(DRIVER_INFO_2));
340 buffer->prs.data_offset=0;
342 for (i=0; i<returned; i++) {
343 smb_io_printer_driver_info_2("", buffer, &(inf[i]), 0);
349 static void decode_printer_driver_3(
358 inf=(DRIVER_INFO_3 *)malloc(returned*sizeof(DRIVER_INFO_3));
360 buffer->prs.data_offset=0;
362 for (i=0; i<returned; i++) {
363 smb_io_printer_driver_info_3("", buffer, &(inf[i]), 0);
369 static void decode_printerdriverdir_1 (
372 DRIVER_DIRECTORY_1 **info
375 DRIVER_DIRECTORY_1 *inf;
377 inf=(DRIVER_DIRECTORY_1 *)malloc(sizeof(DRIVER_DIRECTORY_1));
379 prs_set_offset(&buffer->prs, 0);
381 smb_io_driverdir_1("", buffer, inf, 0);
387 /* Enumerate printers */
389 uint32 cli_spoolss_enum_printers(struct cli_state *cli, uint32 flags,
390 uint32 level, int *returned,
391 PRINTER_INFO_CTR *ctr)
393 prs_struct qbuf, rbuf;
394 SPOOL_Q_ENUMPRINTERS q;
395 SPOOL_R_ENUMPRINTERS r;
404 fstrcpy (server, cli->desthost);
408 /* Initialise input parameters */
410 init_buffer(&buffer, needed, cli->mem_ctx);
412 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
413 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
415 make_spoolss_q_enumprinters(&q, flags, server, level, &buffer,
418 /* Marshall data and send request */
420 if (!spoolss_io_q_enumprinters("", &q, &qbuf, 0) ||
421 !rpc_api_pipe_req(cli, SPOOLSS_ENUMPRINTERS, &qbuf, &rbuf)) {
422 result = NT_STATUS_UNSUCCESSFUL;
426 /* Unmarshall response */
427 if (spoolss_io_r_enumprinters("", &r, &rbuf, 0)) {
431 /* Return output parameters */
433 if ((result = r.status) == NT_STATUS_NOPROBLEMO && r.returned > 0) {
435 *returned = r.returned;
439 decode_printer_info_1(r.buffer, r.returned,
443 decode_printer_info_2(r.buffer, r.returned,
447 decode_printer_info_3(r.buffer, r.returned,
457 } while (result == ERROR_INSUFFICIENT_BUFFER);
462 /* Enumerate printer ports */
463 uint32 cli_spoolss_enum_ports(struct cli_state *cli, uint32 level,
464 int *returned, PORT_INFO_CTR *ctr)
466 prs_struct qbuf, rbuf;
477 slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
481 /* Initialise input parameters */
483 init_buffer(&buffer, needed, cli->mem_ctx);
485 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
486 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
488 make_spoolss_q_enumports(&q, server, level, &buffer, needed);
490 /* Marshall data and send request */
492 if (!spoolss_io_q_enumports("", &q, &qbuf, 0) ||
493 !rpc_api_pipe_req(cli, SPOOLSS_ENUMPORTS, &qbuf, &rbuf)) {
494 result = NT_STATUS_UNSUCCESSFUL;
498 /* Unmarshall response */
499 if (spoolss_io_r_enumports("", &r, &rbuf, 0)) {
503 /* Return output parameters */
505 if ((result = r.status) == NT_STATUS_NOPROBLEMO &&
508 *returned = r.returned;
512 decode_port_info_1(r.buffer, r.returned,
516 decode_port_info_2(r.buffer, r.returned,
526 } while (result == ERROR_INSUFFICIENT_BUFFER);
531 /* Get printer info */
532 uint32 cli_spoolss_getprinter(struct cli_state *cli, POLICY_HND *pol,
533 uint32 level, PRINTER_INFO_CTR *ctr)
535 prs_struct qbuf, rbuf;
536 SPOOL_Q_GETPRINTER q;
537 SPOOL_R_GETPRINTER r;
546 /* Initialise input parameters */
548 init_buffer(&buffer, needed, cli->mem_ctx);
550 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
551 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
553 make_spoolss_q_getprinter(&q, pol, level, &buffer,
556 /* Marshall data and send request */
558 if (!spoolss_io_q_getprinter("", &q, &qbuf, 0) ||
559 !rpc_api_pipe_req(cli, SPOOLSS_GETPRINTER, &qbuf,
561 result = NT_STATUS_UNSUCCESSFUL;
565 /* Unmarshall response */
566 if (spoolss_io_r_getprinter("", &r, &rbuf, 0)) {
570 /* Return output parameters */
572 if ((result = r.status) == NT_STATUS_NOPROBLEMO) {
576 decode_printer_info_0(r.buffer, 1,
580 decode_printer_info_1(r.buffer, 1,
584 decode_printer_info_2(r.buffer, 1,
588 decode_printer_info_3(r.buffer, 1,
598 } while (result == ERROR_INSUFFICIENT_BUFFER);
603 /**********************************************************************
604 * Get installed printer drivers for a given printer
606 uint32 cli_spoolss_getprinterdriver (
607 struct cli_state *cli,
611 PRINTER_DRIVER_CTR *ctr
614 prs_struct qbuf, rbuf;
615 SPOOL_Q_GETPRINTERDRIVER2 q;
616 SPOOL_R_GETPRINTERDRIVER2 r;
618 uint32 needed = 1024;
625 fstrcpy (server, cli->desthost);
630 /* Initialise input parameters */
632 init_buffer(&buffer, needed, cli->mem_ctx);
634 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
635 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
638 /* write the request */
639 make_spoolss_q_getprinterdriver2(&q, pol, env, level, 2, 2, &buffer, needed);
641 /* Marshall data and send request */
642 if (!spoolss_io_q_getprinterdriver2 ("", &q, &qbuf, 0) ||
643 !rpc_api_pipe_req (cli, SPOOLSS_GETPRINTERDRIVER2, &qbuf, &rbuf))
645 result = NT_STATUS_UNSUCCESSFUL;
649 /* Unmarshall response */
650 if (spoolss_io_r_getprinterdriver2 ("", &r, &rbuf, 0))
655 /* Return output parameters */
656 if ((result = r.status) == NT_STATUS_NOPROBLEMO)
662 decode_printer_driver_1(r.buffer, 1, &ctr->info1);
665 decode_printer_driver_2(r.buffer, 1, &ctr->info2);
668 decode_printer_driver_3(r.buffer, 1, &ctr->info3);
677 } while (result == ERROR_INSUFFICIENT_BUFFER);
682 /**********************************************************************
683 * Get installed printer drivers for a given printer
685 uint32 cli_spoolss_enumprinterdrivers (
686 struct cli_state *cli,
690 PRINTER_DRIVER_CTR *ctr
693 prs_struct qbuf, rbuf;
694 SPOOL_Q_ENUMPRINTERDRIVERS q;
695 SPOOL_R_ENUMPRINTERDRIVERS r;
704 slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
709 /* Initialise input parameters */
710 init_buffer(&buffer, needed, cli->mem_ctx);
712 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
713 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
716 /* write the request */
717 make_spoolss_q_enumprinterdrivers(&q, server, env, level, &buffer, needed);
719 /* Marshall data and send request */
720 if (!spoolss_io_q_enumprinterdrivers ("", &q, &qbuf, 0) ||
721 !rpc_api_pipe_req (cli, SPOOLSS_ENUMPRINTERDRIVERS, &qbuf, &rbuf))
723 result = NT_STATUS_UNSUCCESSFUL;
727 /* Unmarshall response */
728 if (spoolss_io_r_enumprinterdrivers ("", &r, &rbuf, 0))
733 /* Return output parameters */
734 if (((result=r.status) == NT_STATUS_NOPROBLEMO) &&
737 *returned = r.returned;
742 decode_printer_driver_1(r.buffer, r.returned, &ctr->info1);
745 decode_printer_driver_2(r.buffer, r.returned, &ctr->info2);
748 decode_printer_driver_3(r.buffer, r.returned, &ctr->info3);
757 } while (result == ERROR_INSUFFICIENT_BUFFER);
763 /**********************************************************************
764 * Get installed printer drivers for a given printer
766 uint32 cli_spoolss_getprinterdriverdir (
767 struct cli_state *cli,
770 DRIVER_DIRECTORY_CTR *ctr
773 prs_struct qbuf, rbuf;
774 SPOOL_Q_GETPRINTERDRIVERDIR q;
775 SPOOL_R_GETPRINTERDRIVERDIR r;
784 slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
789 /* Initialise input parameters */
790 init_buffer(&buffer, needed, cli->mem_ctx);
792 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
793 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
796 /* write the request */
797 make_spoolss_q_getprinterdriverdir(&q, server, env, level, &buffer, needed);
799 /* Marshall data and send request */
800 if (!spoolss_io_q_getprinterdriverdir ("", &q, &qbuf, 0) ||
801 !rpc_api_pipe_req (cli, SPOOLSS_GETPRINTERDRIVERDIRECTORY, &qbuf, &rbuf))
803 result = NT_STATUS_UNSUCCESSFUL;
807 /* Unmarshall response */
808 if (spoolss_io_r_getprinterdriverdir ("", &r, &rbuf, 0))
813 /* Return output parameters */
814 if ((result=r.status) == NT_STATUS_NOPROBLEMO)
819 decode_printerdriverdir_1(r.buffer, 1, &ctr->info1);
828 } while (result == ERROR_INSUFFICIENT_BUFFER);
833 /**********************************************************************
834 * Install a printer driver
836 uint32 cli_spoolss_addprinterdriver (
837 struct cli_state *cli,
839 PRINTER_DRIVER_CTR *ctr
842 prs_struct qbuf, rbuf;
843 SPOOL_Q_ADDPRINTERDRIVER q;
844 SPOOL_R_ADDPRINTERDRIVER r;
851 slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
854 /* Initialise input parameters */
855 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
856 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
859 /* write the request */
860 make_spoolss_q_addprinterdriver (&q, server, level, ctr);
862 /* Marshall data and send request */
863 if (!spoolss_io_q_addprinterdriver ("", &q, &qbuf, 0) ||
864 !rpc_api_pipe_req (cli, SPOOLSS_ADDPRINTERDRIVER, &qbuf, &rbuf))
866 return NT_STATUS_UNSUCCESSFUL;
870 /* Unmarshall response */
871 if (!spoolss_io_r_addprinterdriver ("", &r, &rbuf, 0))
873 return NT_STATUS_UNSUCCESSFUL;
876 /* Return output parameters */
882 /**********************************************************************
885 uint32 cli_spoolss_addprinterex (
886 struct cli_state *cli,
888 PRINTER_INFO_CTR *ctr
891 prs_struct qbuf, rbuf;
892 SPOOL_Q_ADDPRINTEREX q;
893 SPOOL_R_ADDPRINTEREX r;
902 slprintf (client, sizeof(fstring), "\\\\%s", cli->desthost);
904 slprintf (server, sizeof(fstring), "\\\\%s", cli->desthost);
906 fstrcpy (user, cli->user_name);
909 /* Initialise input parameters */
910 prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL);
911 prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL);
914 /* write the request */
915 make_spoolss_q_addprinterex (&q, server, client, user, level, ctr);
917 /* Marshall data and send request */
918 if (!spoolss_io_q_addprinterex ("", &q, &qbuf, 0) ||
919 !rpc_api_pipe_req (cli, SPOOLSS_ADDPRINTEREX, &qbuf, &rbuf))
921 return NT_STATUS_UNSUCCESSFUL;
925 /* Unmarshall response */
926 if (!spoolss_io_r_addprinterex ("", &r, &rbuf, 0))
928 return NT_STATUS_UNSUCCESSFUL;
931 /* Return output parameters */