WHATSNEW: Update changes since 3.2.0rc1.
[Samba.git] / source / rpc_server / srv_spoolss_nt.c
bloba8aa33939338356d0aee61250f3cd5d82d6e1793
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
6 * Copyright (C) Jean François Micouleau 1998-2000,
7 * Copyright (C) Jeremy Allison 2001-2002,
8 * Copyright (C) Gerald Carter 2000-2004,
9 * Copyright (C) Tim Potter 2001-2002.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <http://www.gnu.org/licenses/>.
25 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
26 up, all the errors returned are DOS errors, not NT status codes. */
28 #include "includes.h"
30 extern userdom_struct current_user_info;
32 #undef DBGC_CLASS
33 #define DBGC_CLASS DBGC_RPC_SRV
35 #ifndef MAX_OPEN_PRINTER_EXS
36 #define MAX_OPEN_PRINTER_EXS 50
37 #endif
39 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
40 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
42 struct table_node {
43 const char *long_archi;
44 const char *short_archi;
45 int version;
48 static Printer_entry *printers_list;
50 typedef struct _counter_printer_0 {
51 struct _counter_printer_0 *next;
52 struct _counter_printer_0 *prev;
54 int snum;
55 uint32 counter;
56 } counter_printer_0;
58 static counter_printer_0 *counter_list;
60 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
61 static uint32 smb_connections=0;
64 /* in printing/nt_printing.c */
66 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
68 /* API table for Xcv Monitor functions */
70 struct xcv_api_table {
71 const char *name;
72 WERROR(*fn) (NT_USER_TOKEN *token, RPC_BUFFER *in, RPC_BUFFER *out, uint32 *needed);
76 /* translate between internal status numbers and NT status numbers */
77 static int nt_printj_status(int v)
79 switch (v) {
80 case LPQ_QUEUED:
81 return 0;
82 case LPQ_PAUSED:
83 return JOB_STATUS_PAUSED;
84 case LPQ_SPOOLING:
85 return JOB_STATUS_SPOOLING;
86 case LPQ_PRINTING:
87 return JOB_STATUS_PRINTING;
88 case LPQ_ERROR:
89 return JOB_STATUS_ERROR;
90 case LPQ_DELETING:
91 return JOB_STATUS_DELETING;
92 case LPQ_OFFLINE:
93 return JOB_STATUS_OFFLINE;
94 case LPQ_PAPEROUT:
95 return JOB_STATUS_PAPEROUT;
96 case LPQ_PRINTED:
97 return JOB_STATUS_PRINTED;
98 case LPQ_DELETED:
99 return JOB_STATUS_DELETED;
100 case LPQ_BLOCKED:
101 return JOB_STATUS_BLOCKED;
102 case LPQ_USER_INTERVENTION:
103 return JOB_STATUS_USER_INTERVENTION;
105 return 0;
108 static int nt_printq_status(int v)
110 switch (v) {
111 case LPQ_PAUSED:
112 return PRINTER_STATUS_PAUSED;
113 case LPQ_QUEUED:
114 case LPQ_SPOOLING:
115 case LPQ_PRINTING:
116 return 0;
118 return 0;
121 /****************************************************************************
122 Functions to handle SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
123 ****************************************************************************/
125 static void free_spool_notify_option(SPOOL_NOTIFY_OPTION **pp)
127 if (*pp == NULL)
128 return;
130 SAFE_FREE((*pp)->ctr.type);
131 SAFE_FREE(*pp);
134 /***************************************************************************
135 Disconnect from the client
136 ****************************************************************************/
138 static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
140 WERROR result;
143 * Tell the specific printing tdb we no longer want messages for this printer
144 * by deregistering our PID.
147 if (!print_notify_deregister_pid(snum))
148 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
150 /* weird if the test succeds !!! */
151 if (smb_connections==0) {
152 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
153 return;
156 result = rpccli_spoolss_reply_close_printer(notify_cli_pipe,
157 talloc_tos(),
158 handle);
160 if (!W_ERROR_IS_OK(result))
161 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
162 dos_errstr(result)));
164 /* if it's the last connection, deconnect the IPC$ share */
165 if (smb_connections==1) {
167 cli_shutdown( notify_cli_pipe->cli );
168 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
170 messaging_deregister(smbd_messaging_context(),
171 MSG_PRINTER_NOTIFY2, NULL);
173 /* Tell the connections db we're no longer interested in
174 * printer notify messages. */
176 register_message_flags( False, FLAG_MSG_PRINT_NOTIFY );
179 smb_connections--;
182 /****************************************************************************
183 Functions to free a printer entry datastruct.
184 ****************************************************************************/
186 static void free_printer_entry(void *ptr)
188 Printer_entry *Printer = (Printer_entry *)ptr;
190 if (Printer->notify.client_connected==True) {
191 int snum = -1;
193 if ( Printer->printer_type == SPLHND_SERVER) {
194 snum = -1;
195 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
196 } else if (Printer->printer_type == SPLHND_PRINTER) {
197 snum = print_queue_snum(Printer->sharename);
198 if (snum != -1)
199 srv_spoolss_replycloseprinter(snum,
200 &Printer->notify.client_hnd);
204 Printer->notify.flags=0;
205 Printer->notify.options=0;
206 Printer->notify.localmachine[0]='\0';
207 Printer->notify.printerlocal=0;
208 free_spool_notify_option(&Printer->notify.option);
209 Printer->notify.option=NULL;
210 Printer->notify.client_connected=False;
212 free_nt_devicemode( &Printer->nt_devmode );
213 free_a_printer( &Printer->printer_info, 2 );
215 talloc_destroy( Printer->ctx );
217 /* Remove from the internal list. */
218 DLIST_REMOVE(printers_list, Printer);
220 SAFE_FREE(Printer);
223 /****************************************************************************
224 Functions to duplicate a SPOOL_NOTIFY_OPTION struct stored in Printer_entry.
225 ****************************************************************************/
227 static SPOOL_NOTIFY_OPTION *dup_spool_notify_option(SPOOL_NOTIFY_OPTION *sp)
229 SPOOL_NOTIFY_OPTION *new_sp = NULL;
231 if (!sp)
232 return NULL;
234 new_sp = SMB_MALLOC_P(SPOOL_NOTIFY_OPTION);
235 if (!new_sp)
236 return NULL;
238 *new_sp = *sp;
240 if (sp->ctr.count) {
241 new_sp->ctr.type = (SPOOL_NOTIFY_OPTION_TYPE *)memdup(sp->ctr.type, sizeof(SPOOL_NOTIFY_OPTION_TYPE) * sp->ctr.count);
243 if (!new_sp->ctr.type) {
244 SAFE_FREE(new_sp);
245 return NULL;
249 return new_sp;
252 /****************************************************************************
253 find printer index by handle
254 ****************************************************************************/
256 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd)
258 Printer_entry *find_printer = NULL;
260 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
261 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
262 return NULL;
265 return find_printer;
268 /****************************************************************************
269 Close printer index by handle.
270 ****************************************************************************/
272 static bool close_printer_handle(pipes_struct *p, POLICY_HND *hnd)
274 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
276 if (!Printer) {
277 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
278 return False;
281 close_policy_hnd(p, hnd);
283 return True;
286 /****************************************************************************
287 Delete a printer given a handle.
288 ****************************************************************************/
290 WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename )
292 char *cmd = lp_deleteprinter_cmd();
293 char *command = NULL;
294 int ret;
295 SE_PRIV se_printop = SE_PRINT_OPERATOR;
296 bool is_print_op = False;
298 /* can't fail if we don't try */
300 if ( !*cmd )
301 return WERR_OK;
303 command = talloc_asprintf(ctx,
304 "%s \"%s\"",
305 cmd, sharename);
306 if (!command) {
307 return WERR_NOMEM;
309 if ( token )
310 is_print_op = user_has_privileges( token, &se_printop );
312 DEBUG(10,("Running [%s]\n", command));
314 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
316 if ( is_print_op )
317 become_root();
319 if ( (ret = smbrun(command, NULL)) == 0 ) {
320 /* Tell everyone we updated smb.conf. */
321 message_send_all(smbd_messaging_context(),
322 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
325 if ( is_print_op )
326 unbecome_root();
328 /********** END SePrintOperatorPrivlege BLOCK **********/
330 DEBUGADD(10,("returned [%d]\n", ret));
332 TALLOC_FREE(command);
334 if (ret != 0)
335 return WERR_BADFID; /* What to return here? */
337 /* go ahead and re-read the services immediately */
338 reload_services( False );
340 if ( lp_servicenumber( sharename ) < 0 )
341 return WERR_ACCESS_DENIED;
343 return WERR_OK;
346 /****************************************************************************
347 Delete a printer given a handle.
348 ****************************************************************************/
350 static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd)
352 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
354 if (!Printer) {
355 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
356 return WERR_BADFID;
360 * It turns out that Windows allows delete printer on a handle
361 * opened by an admin user, then used on a pipe handle created
362 * by an anonymous user..... but they're working on security.... riiight !
363 * JRA.
366 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
367 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
368 return WERR_ACCESS_DENIED;
371 /* this does not need a become root since the access check has been
372 done on the handle already */
374 if (del_a_printer( Printer->sharename ) != 0) {
375 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
376 return WERR_BADFID;
379 return delete_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, Printer->sharename );
382 /****************************************************************************
383 Return the snum of a printer corresponding to an handle.
384 ****************************************************************************/
386 static bool get_printer_snum(pipes_struct *p, POLICY_HND *hnd, int *number,
387 struct share_params **params)
389 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
391 if (!Printer) {
392 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(hnd)));
393 return False;
396 switch (Printer->printer_type) {
397 case SPLHND_PRINTER:
398 DEBUG(4,("short name:%s\n", Printer->sharename));
399 *number = print_queue_snum(Printer->sharename);
400 return (*number != -1);
401 case SPLHND_SERVER:
402 return False;
403 default:
404 return False;
408 /****************************************************************************
409 Set printer handle type.
410 Check if it's \\server or \\server\printer
411 ****************************************************************************/
413 static bool set_printer_hnd_printertype(Printer_entry *Printer, char *handlename)
415 DEBUG(3,("Setting printer type=%s\n", handlename));
417 if ( strlen(handlename) < 3 ) {
418 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
419 return False;
422 /* it's a print server */
423 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
424 DEBUGADD(4,("Printer is a print server\n"));
425 Printer->printer_type = SPLHND_SERVER;
427 /* it's a printer (set_printer_hnd_name() will handle port monitors */
428 else {
429 DEBUGADD(4,("Printer is a printer\n"));
430 Printer->printer_type = SPLHND_PRINTER;
433 return True;
436 /****************************************************************************
437 Set printer handle name.. Accept names like \\server, \\server\printer,
438 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
439 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
440 XcvDataPort() interface.
441 ****************************************************************************/
443 static bool set_printer_hnd_name(Printer_entry *Printer, char *handlename)
445 int snum;
446 int n_services=lp_numservices();
447 char *aprinter, *printername;
448 const char *servername;
449 fstring sname;
450 bool found=False;
451 NT_PRINTER_INFO_LEVEL *printer = NULL;
452 WERROR result;
454 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename, (unsigned long)strlen(handlename)));
456 aprinter = handlename;
457 if ( *handlename == '\\' ) {
458 servername = handlename + 2;
459 if ( (aprinter = strchr_m( handlename+2, '\\' )) != NULL ) {
460 *aprinter = '\0';
461 aprinter++;
464 else {
465 servername = "";
468 /* save the servername to fill in replies on this handle */
470 if ( !is_myname_or_ipaddr( servername ) )
471 return False;
473 fstrcpy( Printer->servername, servername );
475 if ( Printer->printer_type == SPLHND_SERVER )
476 return True;
478 if ( Printer->printer_type != SPLHND_PRINTER )
479 return False;
481 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
483 /* check for the Port Monitor Interface */
485 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
486 Printer->printer_type = SPLHND_PORTMON_TCP;
487 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
488 found = True;
490 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
491 Printer->printer_type = SPLHND_PORTMON_LOCAL;
492 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
493 found = True;
496 /* Search all sharenames first as this is easier than pulling
497 the printer_info_2 off of disk. Don't use find_service() since
498 that calls out to map_username() */
500 /* do another loop to look for printernames */
502 for (snum=0; !found && snum<n_services; snum++) {
504 /* no point going on if this is not a printer */
506 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
507 continue;
509 fstrcpy(sname, lp_servicename(snum));
510 if ( strequal( aprinter, sname ) ) {
511 found = True;
512 break;
515 /* no point looking up the printer object if
516 we aren't allowing printername != sharename */
518 if ( lp_force_printername(snum) )
519 continue;
521 fstrcpy(sname, lp_servicename(snum));
523 printer = NULL;
525 /* This call doesn't fill in the location or comment from
526 * a CUPS server for efficiency with large numbers of printers.
527 * JRA.
530 result = get_a_printer_search( NULL, &printer, 2, sname );
531 if ( !W_ERROR_IS_OK(result) ) {
532 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
533 sname, dos_errstr(result)));
534 continue;
537 /* printername is always returned as \\server\printername */
538 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
539 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
540 printer->info_2->printername));
541 free_a_printer( &printer, 2);
542 continue;
545 printername++;
547 if ( strequal(printername, aprinter) ) {
548 free_a_printer( &printer, 2);
549 found = True;
550 break;
553 DEBUGADD(10, ("printername: %s\n", printername));
555 free_a_printer( &printer, 2);
558 free_a_printer( &printer, 2);
560 if ( !found ) {
561 DEBUGADD(4,("Printer not found\n"));
562 return False;
565 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
567 fstrcpy(Printer->sharename, sname);
569 return True;
572 /****************************************************************************
573 Find first available printer slot. creates a printer handle for you.
574 ****************************************************************************/
576 static bool open_printer_hnd(pipes_struct *p, POLICY_HND *hnd, char *name, uint32 access_granted)
578 Printer_entry *new_printer;
580 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
582 if((new_printer=SMB_MALLOC_P(Printer_entry)) == NULL)
583 return False;
585 ZERO_STRUCTP(new_printer);
587 if (!create_policy_hnd(p, hnd, free_printer_entry, new_printer)) {
588 SAFE_FREE(new_printer);
589 return False;
592 /* Add to the internal list. */
593 DLIST_ADD(printers_list, new_printer);
595 new_printer->notify.option=NULL;
597 if ( !(new_printer->ctx = talloc_init("Printer Entry [%p]", hnd)) ) {
598 DEBUG(0,("open_printer_hnd: talloc_init() failed!\n"));
599 close_printer_handle(p, hnd);
600 return False;
603 if (!set_printer_hnd_printertype(new_printer, name)) {
604 close_printer_handle(p, hnd);
605 return False;
608 if (!set_printer_hnd_name(new_printer, name)) {
609 close_printer_handle(p, hnd);
610 return False;
613 new_printer->access_granted = access_granted;
615 DEBUG(5, ("%d printer handles active\n", (int)p->pipe_handles->count ));
617 return True;
620 /***************************************************************************
621 check to see if the client motify handle is monitoring the notification
622 given by (notify_type, notify_field).
623 **************************************************************************/
625 static bool is_monitoring_event_flags(uint32 flags, uint16 notify_type,
626 uint16 notify_field)
628 return True;
631 static bool is_monitoring_event(Printer_entry *p, uint16 notify_type,
632 uint16 notify_field)
634 SPOOL_NOTIFY_OPTION *option = p->notify.option;
635 uint32 i, j;
638 * Flags should always be zero when the change notify
639 * is registered by the client's spooler. A user Win32 app
640 * might use the flags though instead of the NOTIFY_OPTION_INFO
641 * --jerry
644 if (!option) {
645 return False;
648 if (p->notify.flags)
649 return is_monitoring_event_flags(
650 p->notify.flags, notify_type, notify_field);
652 for (i = 0; i < option->count; i++) {
654 /* Check match for notify_type */
656 if (option->ctr.type[i].type != notify_type)
657 continue;
659 /* Check match for field */
661 for (j = 0; j < option->ctr.type[i].count; j++) {
662 if (option->ctr.type[i].fields[j] == notify_field) {
663 return True;
668 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
669 p->servername, p->sharename, notify_type, notify_field));
671 return False;
674 /* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
676 static void notify_one_value(struct spoolss_notify_msg *msg,
677 SPOOL_NOTIFY_INFO_DATA *data,
678 TALLOC_CTX *mem_ctx)
680 data->notify_data.value[0] = msg->notify.value[0];
681 data->notify_data.value[1] = 0;
684 static void notify_string(struct spoolss_notify_msg *msg,
685 SPOOL_NOTIFY_INFO_DATA *data,
686 TALLOC_CTX *mem_ctx)
688 UNISTR2 unistr;
690 /* The length of the message includes the trailing \0 */
692 init_unistr2(&unistr, msg->notify.data, UNI_STR_TERMINATE);
694 data->notify_data.data.length = msg->len * 2;
695 data->notify_data.data.string = TALLOC_ARRAY(mem_ctx, uint16, msg->len);
697 if (!data->notify_data.data.string) {
698 data->notify_data.data.length = 0;
699 return;
702 memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
705 static void notify_system_time(struct spoolss_notify_msg *msg,
706 SPOOL_NOTIFY_INFO_DATA *data,
707 TALLOC_CTX *mem_ctx)
709 SYSTEMTIME systime;
710 prs_struct ps;
712 if (msg->len != sizeof(time_t)) {
713 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
714 msg->len));
715 return;
718 if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
719 DEBUG(5, ("notify_system_time: prs_init() failed\n"));
720 return;
723 if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
724 DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
725 prs_mem_free(&ps);
726 return;
729 if (!spoolss_io_system_time("", &ps, 0, &systime)) {
730 prs_mem_free(&ps);
731 return;
734 data->notify_data.data.length = prs_offset(&ps);
735 if (prs_offset(&ps)) {
736 data->notify_data.data.string = (uint16 *)
737 TALLOC(mem_ctx, prs_offset(&ps));
738 if (!data->notify_data.data.string) {
739 prs_mem_free(&ps);
740 return;
742 prs_copy_all_data_out((char *)data->notify_data.data.string, &ps);
743 } else {
744 data->notify_data.data.string = NULL;
747 prs_mem_free(&ps);
750 struct notify2_message_table {
751 const char *name;
752 void (*fn)(struct spoolss_notify_msg *msg,
753 SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
756 static struct notify2_message_table printer_notify_table[] = {
757 /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
758 /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
759 /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
760 /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
761 /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
762 /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
763 /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
764 /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
765 /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
766 /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
767 /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
768 /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
769 /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
770 /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
771 /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
772 /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
773 /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
774 /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
775 /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
778 static struct notify2_message_table job_notify_table[] = {
779 /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
780 /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
781 /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
782 /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
783 /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
784 /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
785 /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
786 /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
787 /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
788 /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
789 /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
790 /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
791 /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
792 /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
793 /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
794 /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
795 /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
796 /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
797 /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
798 /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
799 /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
800 /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
801 /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
802 /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
806 /***********************************************************************
807 Allocate talloc context for container object
808 **********************************************************************/
810 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
812 if ( !ctr )
813 return;
815 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
817 return;
820 /***********************************************************************
821 release all allocated memory and zero out structure
822 **********************************************************************/
824 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
826 if ( !ctr )
827 return;
829 if ( ctr->ctx )
830 talloc_destroy(ctr->ctx);
832 ZERO_STRUCTP(ctr);
834 return;
837 /***********************************************************************
838 **********************************************************************/
840 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
842 if ( !ctr )
843 return NULL;
845 return ctr->ctx;
848 /***********************************************************************
849 **********************************************************************/
851 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
853 if ( !ctr || !ctr->msg_groups )
854 return NULL;
856 if ( idx >= ctr->num_groups )
857 return NULL;
859 return &ctr->msg_groups[idx];
863 /***********************************************************************
864 How many groups of change messages do we have ?
865 **********************************************************************/
867 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
869 if ( !ctr )
870 return 0;
872 return ctr->num_groups;
875 /***********************************************************************
876 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
877 **********************************************************************/
879 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
881 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
882 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
883 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
884 int i, new_slot;
886 if ( !ctr || !msg )
887 return 0;
889 /* loop over all groups looking for a matching printer name */
891 for ( i=0; i<ctr->num_groups; i++ ) {
892 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
893 break;
896 /* add a new group? */
898 if ( i == ctr->num_groups ) {
899 ctr->num_groups++;
901 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
902 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
903 return 0;
905 ctr->msg_groups = groups;
907 /* clear the new entry and set the printer name */
909 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
910 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
913 /* add the change messages; 'i' is the correct index now regardless */
915 msg_grp = &ctr->msg_groups[i];
917 msg_grp->num_msgs++;
919 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
920 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
921 return 0;
923 msg_grp->msgs = msg_list;
925 new_slot = msg_grp->num_msgs-1;
926 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
928 /* need to allocate own copy of data */
930 if ( msg->len != 0 )
931 msg_grp->msgs[new_slot].notify.data = (char *)
932 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
934 return ctr->num_groups;
937 /***********************************************************************
938 Send a change notication message on all handles which have a call
939 back registered
940 **********************************************************************/
942 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
944 Printer_entry *p;
945 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
946 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
947 SPOOLSS_NOTIFY_MSG *messages;
948 int sending_msg_count;
950 if ( !msg_group ) {
951 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
952 return;
955 messages = msg_group->msgs;
957 if ( !messages ) {
958 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
959 return;
962 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
964 /* loop over all printers */
966 for (p = printers_list; p; p = p->next) {
967 SPOOL_NOTIFY_INFO_DATA *data;
968 uint32 data_len = 0;
969 uint32 id;
970 int i;
972 /* Is there notification on this handle? */
974 if ( !p->notify.client_connected )
975 continue;
977 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
979 /* For this printer? Print servers always receive
980 notifications. */
982 if ( ( p->printer_type == SPLHND_PRINTER ) &&
983 ( !strequal(msg_group->printername, p->sharename) ) )
984 continue;
986 DEBUG(10,("Our printer\n"));
988 /* allocate the max entries possible */
990 data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs);
991 if (!data) {
992 return;
995 ZERO_STRUCTP(data);
997 /* build the array of change notifications */
999 sending_msg_count = 0;
1001 for ( i=0; i<msg_group->num_msgs; i++ ) {
1002 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1004 /* Are we monitoring this event? */
1006 if (!is_monitoring_event(p, msg->type, msg->field))
1007 continue;
1009 sending_msg_count++;
1012 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1013 msg->type, msg->field, p->sharename));
1016 * if the is a printer notification handle and not a job notification
1017 * type, then set the id to 0. Other wise just use what was specified
1018 * in the message.
1020 * When registering change notification on a print server handle
1021 * we always need to send back the id (snum) matching the printer
1022 * for which the change took place. For change notify registered
1023 * on a printer handle, this does not matter and the id should be 0.
1025 * --jerry
1028 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1029 id = 0;
1030 else
1031 id = msg->id;
1034 /* Convert unix jobid to smb jobid */
1036 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1037 id = sysjob_to_jobid(msg->id);
1039 if (id == -1) {
1040 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1041 goto done;
1045 construct_info_data( &data[data_len], msg->type, msg->field, id );
1047 switch(msg->type) {
1048 case PRINTER_NOTIFY_TYPE:
1049 if ( printer_notify_table[msg->field].fn )
1050 printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1051 break;
1053 case JOB_NOTIFY_TYPE:
1054 if ( job_notify_table[msg->field].fn )
1055 job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
1056 break;
1058 default:
1059 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1060 goto done;
1063 data_len++;
1066 if ( sending_msg_count ) {
1067 rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd,
1068 data_len, data, p->notify.change, 0 );
1072 done:
1073 DEBUG(8,("send_notify2_changes: Exit...\n"));
1074 return;
1077 /***********************************************************************
1078 **********************************************************************/
1080 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1083 uint32 tv_sec, tv_usec;
1084 size_t offset = 0;
1086 /* Unpack message */
1088 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "f",
1089 msg->printer);
1091 offset += tdb_unpack((uint8 *)buf + offset, len - offset, "ddddddd",
1092 &tv_sec, &tv_usec,
1093 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1095 if (msg->len == 0)
1096 tdb_unpack((uint8 *)buf + offset, len - offset, "dd",
1097 &msg->notify.value[0], &msg->notify.value[1]);
1098 else
1099 tdb_unpack((uint8 *)buf + offset, len - offset, "B",
1100 &msg->len, &msg->notify.data);
1102 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1103 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1105 tv->tv_sec = tv_sec;
1106 tv->tv_usec = tv_usec;
1108 if (msg->len == 0)
1109 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1110 msg->notify.value[1]));
1111 else
1112 dump_data(3, (uint8 *)msg->notify.data, msg->len);
1114 return True;
1117 /********************************************************************
1118 Receive a notify2 message list
1119 ********************************************************************/
1121 static void receive_notify2_message_list(struct messaging_context *msg,
1122 void *private_data,
1123 uint32_t msg_type,
1124 struct server_id server_id,
1125 DATA_BLOB *data)
1127 size_t msg_count, i;
1128 char *buf = (char *)data->data;
1129 char *msg_ptr;
1130 size_t msg_len;
1131 SPOOLSS_NOTIFY_MSG notify;
1132 SPOOLSS_NOTIFY_MSG_CTR messages;
1133 int num_groups;
1135 if (data->length < 4) {
1136 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1137 return;
1140 msg_count = IVAL(buf, 0);
1141 msg_ptr = buf + 4;
1143 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1145 if (msg_count == 0) {
1146 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1147 return;
1150 /* initialize the container */
1152 ZERO_STRUCT( messages );
1153 notify_msg_ctr_init( &messages );
1156 * build message groups for each printer identified
1157 * in a change_notify msg. Remember that a PCN message
1158 * includes the handle returned for the srv_spoolss_replyopenprinter()
1159 * call. Therefore messages are grouped according to printer handle.
1162 for ( i=0; i<msg_count; i++ ) {
1163 struct timeval msg_tv;
1165 if (msg_ptr + 4 - buf > data->length) {
1166 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1167 return;
1170 msg_len = IVAL(msg_ptr,0);
1171 msg_ptr += 4;
1173 if (msg_ptr + msg_len - buf > data->length) {
1174 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1175 return;
1178 /* unpack messages */
1180 ZERO_STRUCT( notify );
1181 notify2_unpack_msg( &notify, &msg_tv, msg_ptr, msg_len );
1182 msg_ptr += msg_len;
1184 /* add to correct list in container */
1186 notify_msg_ctr_addmsg( &messages, &notify );
1188 /* free memory that might have been allocated by notify2_unpack_msg() */
1190 if ( notify.len != 0 )
1191 SAFE_FREE( notify.notify.data );
1194 /* process each group of messages */
1196 num_groups = notify_msg_ctr_numgroups( &messages );
1197 for ( i=0; i<num_groups; i++ )
1198 send_notify2_changes( &messages, i );
1201 /* cleanup */
1203 DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count ));
1205 notify_msg_ctr_destroy( &messages );
1207 return;
1210 /********************************************************************
1211 Send a message to ourself about new driver being installed
1212 so we can upgrade the information for each printer bound to this
1213 driver
1214 ********************************************************************/
1216 static bool srv_spoolss_drv_upgrade_printer(char* drivername)
1218 int len = strlen(drivername);
1220 if (!len)
1221 return False;
1223 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1224 drivername));
1226 messaging_send_buf(smbd_messaging_context(), procid_self(),
1227 MSG_PRINTER_DRVUPGRADE,
1228 (uint8 *)drivername, len+1);
1230 return True;
1233 /**********************************************************************
1234 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1235 over all printers, upgrading ones as necessary
1236 **********************************************************************/
1238 void do_drv_upgrade_printer(struct messaging_context *msg,
1239 void *private_data,
1240 uint32_t msg_type,
1241 struct server_id server_id,
1242 DATA_BLOB *data)
1244 fstring drivername;
1245 int snum;
1246 int n_services = lp_numservices();
1247 size_t len;
1249 len = MIN(data->length,sizeof(drivername)-1);
1250 strncpy(drivername, (const char *)data->data, len);
1252 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1254 /* Iterate the printer list */
1256 for (snum=0; snum<n_services; snum++)
1258 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1260 WERROR result;
1261 NT_PRINTER_INFO_LEVEL *printer = NULL;
1263 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1264 if (!W_ERROR_IS_OK(result))
1265 continue;
1267 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1269 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1271 /* all we care about currently is the change_id */
1273 result = mod_a_printer(printer, 2);
1274 if (!W_ERROR_IS_OK(result)) {
1275 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1276 dos_errstr(result)));
1280 free_a_printer(&printer, 2);
1284 /* all done */
1287 /********************************************************************
1288 Update the cache for all printq's with a registered client
1289 connection
1290 ********************************************************************/
1292 void update_monitored_printq_cache( void )
1294 Printer_entry *printer = printers_list;
1295 int snum;
1297 /* loop through all printers and update the cache where
1298 client_connected == True */
1299 while ( printer )
1301 if ( (printer->printer_type == SPLHND_PRINTER)
1302 && printer->notify.client_connected )
1304 snum = print_queue_snum(printer->sharename);
1305 print_queue_status( snum, NULL, NULL );
1308 printer = printer->next;
1311 return;
1313 /********************************************************************
1314 Send a message to ourself about new driver being installed
1315 so we can upgrade the information for each printer bound to this
1316 driver
1317 ********************************************************************/
1319 static bool srv_spoolss_reset_printerdata(char* drivername)
1321 int len = strlen(drivername);
1323 if (!len)
1324 return False;
1326 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1327 drivername));
1329 messaging_send_buf(smbd_messaging_context(), procid_self(),
1330 MSG_PRINTERDATA_INIT_RESET,
1331 (uint8 *)drivername, len+1);
1333 return True;
1336 /**********************************************************************
1337 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1338 over all printers, resetting printer data as neessary
1339 **********************************************************************/
1341 void reset_all_printerdata(struct messaging_context *msg,
1342 void *private_data,
1343 uint32_t msg_type,
1344 struct server_id server_id,
1345 DATA_BLOB *data)
1347 fstring drivername;
1348 int snum;
1349 int n_services = lp_numservices();
1350 size_t len;
1352 len = MIN( data->length, sizeof(drivername)-1 );
1353 strncpy( drivername, (const char *)data->data, len );
1355 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1357 /* Iterate the printer list */
1359 for ( snum=0; snum<n_services; snum++ )
1361 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1363 WERROR result;
1364 NT_PRINTER_INFO_LEVEL *printer = NULL;
1366 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1367 if ( !W_ERROR_IS_OK(result) )
1368 continue;
1371 * if the printer is bound to the driver,
1372 * then reset to the new driver initdata
1375 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1377 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1379 if ( !set_driver_init(printer, 2) ) {
1380 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1381 printer->info_2->printername, printer->info_2->drivername));
1384 result = mod_a_printer( printer, 2 );
1385 if ( !W_ERROR_IS_OK(result) ) {
1386 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1387 get_dos_error_msg(result)));
1391 free_a_printer( &printer, 2 );
1395 /* all done */
1397 return;
1400 /********************************************************************
1401 Copy routines used by convert_to_openprinterex()
1402 *******************************************************************/
1404 static DEVICEMODE* dup_devicemode(TALLOC_CTX *ctx, DEVICEMODE *devmode)
1406 DEVICEMODE *d;
1407 int len;
1409 if (!devmode)
1410 return NULL;
1412 DEBUG (8,("dup_devmode\n"));
1414 /* bulk copy first */
1416 d = (DEVICEMODE *)TALLOC_MEMDUP(ctx, devmode, sizeof(DEVICEMODE));
1417 if (!d)
1418 return NULL;
1420 /* dup the pointer members separately */
1422 len = unistrlen(devmode->devicename.buffer);
1423 if (len != -1) {
1424 d->devicename.buffer = TALLOC_ARRAY(ctx, uint16, len);
1425 if (!d->devicename.buffer) {
1426 return NULL;
1428 if (unistrcpy(d->devicename.buffer, devmode->devicename.buffer) != len)
1429 return NULL;
1433 len = unistrlen(devmode->formname.buffer);
1434 if (len != -1) {
1435 d->formname.buffer = TALLOC_ARRAY(ctx, uint16, len);
1436 if (!d->formname.buffer) {
1437 return NULL;
1439 if (unistrcpy(d->formname.buffer, devmode->formname.buffer) != len)
1440 return NULL;
1443 if (devmode->driverextra) {
1444 d->dev_private = (uint8 *)TALLOC_MEMDUP(ctx, devmode->dev_private,
1445 devmode->driverextra);
1446 if (!d->dev_private) {
1447 return NULL;
1449 } else {
1450 d->dev_private = NULL;
1452 return d;
1455 static void copy_devmode_ctr(TALLOC_CTX *ctx, DEVMODE_CTR *new_ctr, DEVMODE_CTR *ctr)
1457 if (!new_ctr || !ctr)
1458 return;
1460 DEBUG(8,("copy_devmode_ctr\n"));
1462 new_ctr->size = ctr->size;
1463 new_ctr->devmode_ptr = ctr->devmode_ptr;
1465 if(ctr->devmode_ptr)
1466 new_ctr->devmode = dup_devicemode(ctx, ctr->devmode);
1469 static void copy_printer_default(TALLOC_CTX *ctx, PRINTER_DEFAULT *new_def, PRINTER_DEFAULT *def)
1471 if (!new_def || !def)
1472 return;
1474 DEBUG(8,("copy_printer_defaults\n"));
1476 new_def->datatype_ptr = def->datatype_ptr;
1478 if (def->datatype_ptr)
1479 copy_unistr2(&new_def->datatype, &def->datatype);
1481 copy_devmode_ctr(ctx, &new_def->devmode_cont, &def->devmode_cont);
1483 new_def->access_required = def->access_required;
1486 /********************************************************************
1487 * Convert a SPOOL_Q_OPEN_PRINTER structure to a
1488 * SPOOL_Q_OPEN_PRINTER_EX structure
1489 ********************************************************************/
1491 static WERROR convert_to_openprinterex(TALLOC_CTX *ctx, SPOOL_Q_OPEN_PRINTER_EX *q_u_ex, SPOOL_Q_OPEN_PRINTER *q_u)
1493 if (!q_u_ex || !q_u)
1494 return WERR_OK;
1496 DEBUG(8,("convert_to_openprinterex\n"));
1498 if ( q_u->printername ) {
1499 q_u_ex->printername = TALLOC_ZERO_P( ctx, UNISTR2 );
1500 if (q_u_ex->printername == NULL)
1501 return WERR_NOMEM;
1502 copy_unistr2(q_u_ex->printername, q_u->printername);
1505 copy_printer_default(ctx, &q_u_ex->printer_default, &q_u->printer_default);
1507 return WERR_OK;
1510 /********************************************************************
1511 * spoolss_open_printer
1513 * called from the spoolss dispatcher
1514 ********************************************************************/
1516 WERROR _spoolss_open_printer(pipes_struct *p, SPOOL_Q_OPEN_PRINTER *q_u, SPOOL_R_OPEN_PRINTER *r_u)
1518 SPOOL_Q_OPEN_PRINTER_EX q_u_ex;
1519 SPOOL_R_OPEN_PRINTER_EX r_u_ex;
1521 if (!q_u || !r_u)
1522 return WERR_NOMEM;
1524 ZERO_STRUCT(q_u_ex);
1525 ZERO_STRUCT(r_u_ex);
1527 /* convert the OpenPrinter() call to OpenPrinterEx() */
1529 r_u_ex.status = convert_to_openprinterex(p->mem_ctx, &q_u_ex, q_u);
1530 if (!W_ERROR_IS_OK(r_u_ex.status))
1531 return r_u_ex.status;
1533 r_u_ex.status = _spoolss_open_printer_ex(p, &q_u_ex, &r_u_ex);
1535 /* convert back to OpenPrinter() */
1537 memcpy(r_u, &r_u_ex, sizeof(*r_u));
1539 if (W_ERROR_EQUAL(r_u->status, WERR_INVALID_PARAM)) {
1540 /* OpenPrinterEx returns this for a bad
1541 * printer name. We must return WERR_INVALID_PRINTER_NAME
1542 * instead.
1544 r_u->status = WERR_INVALID_PRINTER_NAME;
1546 return r_u->status;
1549 /********************************************************************
1550 ********************************************************************/
1552 WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
1554 PRINTER_DEFAULT *printer_default = &q_u->printer_default;
1555 POLICY_HND *handle = &r_u->handle;
1557 fstring name;
1558 int snum;
1559 Printer_entry *Printer=NULL;
1561 if (!q_u->printername) {
1562 return WERR_INVALID_PARAM;
1565 /* some sanity check because you can open a printer or a print server */
1566 /* aka: \\server\printer or \\server */
1568 unistr2_to_ascii(name, q_u->printername, sizeof(name));
1570 DEBUGADD(3,("checking name: %s\n",name));
1572 if (!open_printer_hnd(p, handle, name, 0)) {
1573 return WERR_INVALID_PARAM;
1576 Printer=find_printer_index_by_hnd(p, handle);
1577 if ( !Printer ) {
1578 DEBUG(0,(" _spoolss_open_printer_ex: logic error. Can't find printer "
1579 "handle we created for printer %s\n", name ));
1580 close_printer_handle(p,handle);
1581 return WERR_INVALID_PARAM;
1585 * First case: the user is opening the print server:
1587 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1588 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1590 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1591 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1592 * or if the user is listed in the smb.conf printer admin parameter.
1594 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1595 * client view printer folder, but does not show the MSAPW.
1597 * Note: this test needs code to check access rights here too. Jeremy
1598 * could you look at this?
1600 * Second case: the user is opening a printer:
1601 * NT doesn't let us connect to a printer if the connecting user
1602 * doesn't have print permission.
1604 * Third case: user is opening a Port Monitor
1605 * access checks same as opening a handle to the print server.
1608 switch (Printer->printer_type )
1610 case SPLHND_SERVER:
1611 case SPLHND_PORTMON_TCP:
1612 case SPLHND_PORTMON_LOCAL:
1613 /* Printserver handles use global struct... */
1615 snum = -1;
1617 /* Map standard access rights to object specific access rights */
1619 se_map_standard(&printer_default->access_required,
1620 &printserver_std_mapping);
1622 /* Deny any object specific bits that don't apply to print
1623 servers (i.e printer and job specific bits) */
1625 printer_default->access_required &= SPECIFIC_RIGHTS_MASK;
1627 if (printer_default->access_required &
1628 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1629 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1630 close_printer_handle(p, handle);
1631 return WERR_ACCESS_DENIED;
1634 /* Allow admin access */
1636 if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
1638 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1640 if (!lp_ms_add_printer_wizard()) {
1641 close_printer_handle(p, handle);
1642 return WERR_ACCESS_DENIED;
1645 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1646 and not a printer admin, then fail */
1648 if ((p->pipe_user.ut.uid != 0) &&
1649 !user_has_privileges(p->pipe_user.nt_user_token,
1650 &se_printop ) &&
1651 !token_contains_name_in_list(
1652 uidtoname(p->pipe_user.ut.uid), NULL,
1653 p->pipe_user.nt_user_token,
1654 lp_printer_admin(snum))) {
1655 close_printer_handle(p, handle);
1656 return WERR_ACCESS_DENIED;
1659 printer_default->access_required = SERVER_ACCESS_ADMINISTER;
1661 else
1663 printer_default->access_required = SERVER_ACCESS_ENUMERATE;
1666 DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
1667 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1669 /* We fall through to return WERR_OK */
1670 break;
1672 case SPLHND_PRINTER:
1673 /* NT doesn't let us connect to a printer if the connecting user
1674 doesn't have print permission. */
1676 if (!get_printer_snum(p, handle, &snum, NULL)) {
1677 close_printer_handle(p, handle);
1678 return WERR_BADFID;
1681 se_map_standard(&printer_default->access_required, &printer_std_mapping);
1683 /* map an empty access mask to the minimum access mask */
1684 if (printer_default->access_required == 0x0)
1685 printer_default->access_required = PRINTER_ACCESS_USE;
1688 * If we are not serving the printer driver for this printer,
1689 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1690 * will keep NT clients happy --jerry
1693 if (lp_use_client_driver(snum)
1694 && (printer_default->access_required & PRINTER_ACCESS_ADMINISTER))
1696 printer_default->access_required = PRINTER_ACCESS_USE;
1699 /* check smb.conf parameters and the the sec_desc */
1701 if ( !check_access(smbd_server_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1702 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1703 return WERR_ACCESS_DENIED;
1706 if (!user_ok_token(uidtoname(p->pipe_user.ut.uid),
1707 p->pipe_user.nt_user_token, snum) ||
1708 !print_access_check(&p->pipe_user, snum,
1709 printer_default->access_required)) {
1710 DEBUG(3, ("access DENIED for printer open\n"));
1711 close_printer_handle(p, handle);
1712 return WERR_ACCESS_DENIED;
1715 if ((printer_default->access_required & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1716 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1717 close_printer_handle(p, handle);
1718 return WERR_ACCESS_DENIED;
1721 if (printer_default->access_required & PRINTER_ACCESS_ADMINISTER)
1722 printer_default->access_required = PRINTER_ACCESS_ADMINISTER;
1723 else
1724 printer_default->access_required = PRINTER_ACCESS_USE;
1726 DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1727 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1729 break;
1731 default:
1732 /* sanity check to prevent programmer error */
1733 return WERR_BADFID;
1736 Printer->access_granted = printer_default->access_required;
1739 * If the client sent a devmode in the OpenPrinter() call, then
1740 * save it here in case we get a job submission on this handle
1743 if ( (Printer->printer_type != SPLHND_SERVER)
1744 && q_u->printer_default.devmode_cont.devmode_ptr )
1746 convert_devicemode( Printer->sharename, q_u->printer_default.devmode_cont.devmode,
1747 &Printer->nt_devmode );
1750 #if 0 /* JERRY -- I'm doubtful this is really effective */
1751 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1752 optimization in Windows 2000 clients --jerry */
1754 if ( (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
1755 && (RA_WIN2K == get_remote_arch()) )
1757 DEBUG(10,("_spoolss_open_printer_ex: Enabling LAN/WAN hack for Win2k clients.\n"));
1758 sys_usleep( 500000 );
1760 #endif
1762 return WERR_OK;
1765 /****************************************************************************
1766 ****************************************************************************/
1768 static bool convert_printer_info(const SPOOL_PRINTER_INFO_LEVEL *uni,
1769 NT_PRINTER_INFO_LEVEL *printer, uint32 level)
1771 bool ret;
1773 switch (level) {
1774 case 2:
1775 /* allocate memory if needed. Messy because
1776 convert_printer_info is used to update an existing
1777 printer or build a new one */
1779 if ( !printer->info_2 ) {
1780 printer->info_2 = TALLOC_ZERO_P( printer, NT_PRINTER_INFO_LEVEL_2 );
1781 if ( !printer->info_2 ) {
1782 DEBUG(0,("convert_printer_info: talloc() failed!\n"));
1783 return False;
1787 ret = uni_2_asc_printer_info_2(uni->info_2, printer->info_2);
1788 printer->info_2->setuptime = time(NULL);
1790 return ret;
1793 return False;
1796 static bool convert_printer_driver_info(const SPOOL_PRINTER_DRIVER_INFO_LEVEL *uni,
1797 NT_PRINTER_DRIVER_INFO_LEVEL *printer, uint32 level)
1799 bool result = True;
1801 switch (level) {
1802 case 3:
1803 printer->info_3=NULL;
1804 if (!uni_2_asc_printer_driver_3(uni->info_3, &printer->info_3))
1805 result = False;
1806 break;
1807 case 6:
1808 printer->info_6=NULL;
1809 if (!uni_2_asc_printer_driver_6(uni->info_6, &printer->info_6))
1810 result = False;
1811 break;
1812 default:
1813 break;
1816 return result;
1819 bool convert_devicemode(const char *printername, const DEVICEMODE *devmode,
1820 NT_DEVICEMODE **pp_nt_devmode)
1822 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1825 * Ensure nt_devmode is a valid pointer
1826 * as we will be overwriting it.
1829 if (nt_devmode == NULL) {
1830 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1831 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1832 return False;
1835 rpcstr_pull(nt_devmode->devicename,devmode->devicename.buffer, 31, -1, 0);
1836 rpcstr_pull(nt_devmode->formname,devmode->formname.buffer, 31, -1, 0);
1838 nt_devmode->specversion=devmode->specversion;
1839 nt_devmode->driverversion=devmode->driverversion;
1840 nt_devmode->size=devmode->size;
1841 nt_devmode->fields=devmode->fields;
1842 nt_devmode->orientation=devmode->orientation;
1843 nt_devmode->papersize=devmode->papersize;
1844 nt_devmode->paperlength=devmode->paperlength;
1845 nt_devmode->paperwidth=devmode->paperwidth;
1846 nt_devmode->scale=devmode->scale;
1847 nt_devmode->copies=devmode->copies;
1848 nt_devmode->defaultsource=devmode->defaultsource;
1849 nt_devmode->printquality=devmode->printquality;
1850 nt_devmode->color=devmode->color;
1851 nt_devmode->duplex=devmode->duplex;
1852 nt_devmode->yresolution=devmode->yresolution;
1853 nt_devmode->ttoption=devmode->ttoption;
1854 nt_devmode->collate=devmode->collate;
1856 nt_devmode->logpixels=devmode->logpixels;
1857 nt_devmode->bitsperpel=devmode->bitsperpel;
1858 nt_devmode->pelswidth=devmode->pelswidth;
1859 nt_devmode->pelsheight=devmode->pelsheight;
1860 nt_devmode->displayflags=devmode->displayflags;
1861 nt_devmode->displayfrequency=devmode->displayfrequency;
1862 nt_devmode->icmmethod=devmode->icmmethod;
1863 nt_devmode->icmintent=devmode->icmintent;
1864 nt_devmode->mediatype=devmode->mediatype;
1865 nt_devmode->dithertype=devmode->dithertype;
1866 nt_devmode->reserved1=devmode->reserved1;
1867 nt_devmode->reserved2=devmode->reserved2;
1868 nt_devmode->panningwidth=devmode->panningwidth;
1869 nt_devmode->panningheight=devmode->panningheight;
1872 * Only change private and driverextra if the incoming devmode
1873 * has a new one. JRA.
1876 if ((devmode->driverextra != 0) && (devmode->dev_private != NULL)) {
1877 SAFE_FREE(nt_devmode->nt_dev_private);
1878 nt_devmode->driverextra=devmode->driverextra;
1879 if((nt_devmode->nt_dev_private=SMB_MALLOC_ARRAY(uint8, nt_devmode->driverextra)) == NULL)
1880 return False;
1881 memcpy(nt_devmode->nt_dev_private, devmode->dev_private, nt_devmode->driverextra);
1884 *pp_nt_devmode = nt_devmode;
1886 return True;
1889 /********************************************************************
1890 * _spoolss_enddocprinter_internal.
1891 ********************************************************************/
1893 static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
1895 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1896 int snum;
1898 if (!Printer) {
1899 DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
1900 return WERR_BADFID;
1903 if (!get_printer_snum(p, handle, &snum, NULL))
1904 return WERR_BADFID;
1906 Printer->document_started=False;
1907 print_job_end(snum, Printer->jobid,NORMAL_CLOSE);
1908 /* error codes unhandled so far ... */
1910 return WERR_OK;
1913 /********************************************************************
1914 * api_spoolss_closeprinter
1915 ********************************************************************/
1917 WERROR _spoolss_closeprinter(pipes_struct *p, SPOOL_Q_CLOSEPRINTER *q_u, SPOOL_R_CLOSEPRINTER *r_u)
1919 POLICY_HND *handle = &q_u->handle;
1921 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1923 if (Printer && Printer->document_started)
1924 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1926 if (!close_printer_handle(p, handle))
1927 return WERR_BADFID;
1929 /* clear the returned printer handle. Observed behavior
1930 from Win2k server. Don't think this really matters.
1931 Previous code just copied the value of the closed
1932 handle. --jerry */
1934 memset(&r_u->handle, '\0', sizeof(r_u->handle));
1936 return WERR_OK;
1939 /********************************************************************
1940 * api_spoolss_deleteprinter
1942 ********************************************************************/
1944 WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL_R_DELETEPRINTER *r_u)
1946 POLICY_HND *handle = &q_u->handle;
1947 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
1948 WERROR result;
1950 if (Printer && Printer->document_started)
1951 _spoolss_enddocprinter_internal(p, handle); /* print job was not closed */
1953 memcpy(&r_u->handle, &q_u->handle, sizeof(r_u->handle));
1955 result = delete_printer_handle(p, handle);
1957 update_c_setprinter(False);
1959 return result;
1962 /*******************************************************************
1963 * static function to lookup the version id corresponding to an
1964 * long architecture string
1965 ******************************************************************/
1967 static int get_version_id (char * arch)
1969 int i;
1970 struct table_node archi_table[]= {
1972 {"Windows 4.0", "WIN40", 0 },
1973 {"Windows NT x86", "W32X86", 2 },
1974 {"Windows NT R4000", "W32MIPS", 2 },
1975 {"Windows NT Alpha_AXP", "W32ALPHA", 2 },
1976 {"Windows NT PowerPC", "W32PPC", 2 },
1977 {"Windows IA64", "IA64", 3 },
1978 {"Windows x64", "x64", 3 },
1979 {NULL, "", -1 }
1982 for (i=0; archi_table[i].long_archi != NULL; i++)
1984 if (strcmp(arch, archi_table[i].long_archi) == 0)
1985 return (archi_table[i].version);
1988 return -1;
1991 /********************************************************************
1992 * _spoolss_deleteprinterdriver
1993 ********************************************************************/
1995 WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
1997 fstring driver;
1998 fstring arch;
1999 NT_PRINTER_DRIVER_INFO_LEVEL info;
2000 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2001 int version;
2002 WERROR status;
2003 WERROR status_win2k = WERR_ACCESS_DENIED;
2004 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2006 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2007 and not a printer admin, then fail */
2009 if ( (p->pipe_user.ut.uid != 0)
2010 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2011 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2012 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2014 return WERR_ACCESS_DENIED;
2017 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2018 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2020 /* check that we have a valid driver name first */
2022 if ((version=get_version_id(arch)) == -1)
2023 return WERR_INVALID_ENVIRONMENT;
2025 ZERO_STRUCT(info);
2026 ZERO_STRUCT(info_win2k);
2028 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
2030 /* try for Win2k driver if "Windows NT x86" */
2032 if ( version == 2 ) {
2033 version = 3;
2034 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2035 status = WERR_UNKNOWN_PRINTER_DRIVER;
2036 goto done;
2039 /* otherwise it was a failure */
2040 else {
2041 status = WERR_UNKNOWN_PRINTER_DRIVER;
2042 goto done;
2047 if (printer_driver_in_use(info.info_3)) {
2048 status = WERR_PRINTER_DRIVER_IN_USE;
2049 goto done;
2052 if ( version == 2 )
2054 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2056 /* if we get to here, we now have 2 driver info structures to remove */
2057 /* remove the Win2k driver first*/
2059 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, False );
2060 free_a_printer_driver( info_win2k, 3 );
2062 /* this should not have failed---if it did, report to client */
2063 if ( !W_ERROR_IS_OK(status_win2k) )
2065 status = status_win2k;
2066 goto done;
2071 status = delete_printer_driver(info.info_3, &p->pipe_user, version, False);
2073 /* if at least one of the deletes succeeded return OK */
2075 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2076 status = WERR_OK;
2078 done:
2079 free_a_printer_driver( info, 3 );
2081 return status;
2084 /********************************************************************
2085 * spoolss_deleteprinterdriverex
2086 ********************************************************************/
2088 WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
2090 fstring driver;
2091 fstring arch;
2092 NT_PRINTER_DRIVER_INFO_LEVEL info;
2093 NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
2094 int version;
2095 uint32 flags = q_u->delete_flags;
2096 bool delete_files;
2097 WERROR status;
2098 WERROR status_win2k = WERR_ACCESS_DENIED;
2099 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2101 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2102 and not a printer admin, then fail */
2104 if ( (p->pipe_user.ut.uid != 0)
2105 && !user_has_privileges(p->pipe_user.nt_user_token, &se_printop )
2106 && !token_contains_name_in_list( uidtoname(p->pipe_user.ut.uid),
2107 NULL, p->pipe_user.nt_user_token, lp_printer_admin(-1)) )
2109 return WERR_ACCESS_DENIED;
2112 unistr2_to_ascii(driver, &q_u->driver, sizeof(driver));
2113 unistr2_to_ascii(arch, &q_u->arch, sizeof(arch));
2115 /* check that we have a valid driver name first */
2116 if ((version=get_version_id(arch)) == -1) {
2117 /* this is what NT returns */
2118 return WERR_INVALID_ENVIRONMENT;
2121 if ( flags & DPD_DELETE_SPECIFIC_VERSION )
2122 version = q_u->version;
2124 ZERO_STRUCT(info);
2125 ZERO_STRUCT(info_win2k);
2127 status = get_a_printer_driver(&info, 3, driver, arch, version);
2129 if ( !W_ERROR_IS_OK(status) )
2132 * if the client asked for a specific version,
2133 * or this is something other than Windows NT x86,
2134 * then we've failed
2137 if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2138 goto done;
2140 /* try for Win2k driver if "Windows NT x86" */
2142 version = 3;
2143 if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
2144 status = WERR_UNKNOWN_PRINTER_DRIVER;
2145 goto done;
2149 if ( printer_driver_in_use(info.info_3) ) {
2150 status = WERR_PRINTER_DRIVER_IN_USE;
2151 goto done;
2155 * we have a couple of cases to consider.
2156 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2157 * then the delete should fail if **any** files overlap with
2158 * other drivers
2159 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2160 * non-overlapping files
2161 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2162 * is set, the do not delete any files
2163 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2166 delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2168 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2170 if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2171 /* no idea of the correct error here */
2172 status = WERR_ACCESS_DENIED;
2173 goto done;
2177 /* also check for W32X86/3 if necessary; maybe we already have? */
2179 if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2180 if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
2183 if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
2184 /* no idea of the correct error here */
2185 free_a_printer_driver( info_win2k, 3 );
2186 status = WERR_ACCESS_DENIED;
2187 goto done;
2190 /* if we get to here, we now have 2 driver info structures to remove */
2191 /* remove the Win2k driver first*/
2193 status_win2k = delete_printer_driver(info_win2k.info_3, &p->pipe_user, 3, delete_files);
2194 free_a_printer_driver( info_win2k, 3 );
2196 /* this should not have failed---if it did, report to client */
2198 if ( !W_ERROR_IS_OK(status_win2k) )
2199 goto done;
2203 status = delete_printer_driver(info.info_3, &p->pipe_user, version, delete_files);
2205 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2206 status = WERR_OK;
2207 done:
2208 free_a_printer_driver( info, 3 );
2210 return status;
2214 /****************************************************************************
2215 Internal routine for retreiving printerdata
2216 ***************************************************************************/
2218 static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
2219 const char *key, const char *value, uint32 *type, uint8 **data,
2220 uint32 *needed, uint32 in_size )
2222 REGISTRY_VALUE *val;
2223 uint32 size;
2224 int data_len;
2226 if ( !(val = get_printer_data( printer->info_2, key, value)) )
2227 return WERR_BADFILE;
2229 *type = regval_type( val );
2231 DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
2233 size = regval_size( val );
2235 /* copy the min(in_size, len) */
2237 if ( in_size ) {
2238 data_len = (size > in_size) ? in_size : size*sizeof(uint8);
2240 /* special case for 0 length values */
2241 if ( data_len ) {
2242 if ( (*data = (uint8 *)TALLOC_MEMDUP(ctx, regval_data_p(val), data_len)) == NULL )
2243 return WERR_NOMEM;
2245 else {
2246 if ( (*data = (uint8 *)TALLOC_ZERO(ctx, in_size)) == NULL )
2247 return WERR_NOMEM;
2250 else
2251 *data = NULL;
2253 *needed = size;
2255 DEBUG(5,("get_printer_dataex: copy done\n"));
2257 return WERR_OK;
2260 /****************************************************************************
2261 Internal routine for removing printerdata
2262 ***************************************************************************/
2264 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2266 return delete_printer_data( printer->info_2, key, value );
2269 /****************************************************************************
2270 Internal routine for storing printerdata
2271 ***************************************************************************/
2273 WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value,
2274 uint32 type, uint8 *data, int real_len )
2276 /* the registry objects enforce uniqueness based on value name */
2278 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2281 /********************************************************************
2282 GetPrinterData on a printer server Handle.
2283 ********************************************************************/
2285 static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
2287 int i;
2289 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2291 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2292 *type = REG_DWORD;
2293 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2294 return WERR_NOMEM;
2295 SIVAL(*data, 0, 0x00);
2296 *needed = 0x4;
2297 return WERR_OK;
2300 if (!StrCaseCmp(value, "BeepEnabled")) {
2301 *type = REG_DWORD;
2302 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2303 return WERR_NOMEM;
2304 SIVAL(*data, 0, 0x00);
2305 *needed = 0x4;
2306 return WERR_OK;
2309 if (!StrCaseCmp(value, "EventLog")) {
2310 *type = REG_DWORD;
2311 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2312 return WERR_NOMEM;
2313 /* formally was 0x1b */
2314 SIVAL(*data, 0, 0x0);
2315 *needed = 0x4;
2316 return WERR_OK;
2319 if (!StrCaseCmp(value, "NetPopup")) {
2320 *type = REG_DWORD;
2321 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2322 return WERR_NOMEM;
2323 SIVAL(*data, 0, 0x00);
2324 *needed = 0x4;
2325 return WERR_OK;
2328 if (!StrCaseCmp(value, "MajorVersion")) {
2329 *type = REG_DWORD;
2330 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2331 return WERR_NOMEM;
2333 /* Windows NT 4.0 seems to not allow uploading of drivers
2334 to a server that reports 0x3 as the MajorVersion.
2335 need to investigate more how Win2k gets around this .
2336 -- jerry */
2338 if ( RA_WINNT == get_remote_arch() )
2339 SIVAL(*data, 0, 2);
2340 else
2341 SIVAL(*data, 0, 3);
2343 *needed = 0x4;
2344 return WERR_OK;
2347 if (!StrCaseCmp(value, "MinorVersion")) {
2348 *type = REG_DWORD;
2349 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2350 return WERR_NOMEM;
2351 SIVAL(*data, 0, 0);
2352 *needed = 0x4;
2353 return WERR_OK;
2356 /* REG_BINARY
2357 * uint32 size = 0x114
2358 * uint32 major = 5
2359 * uint32 minor = [0|1]
2360 * uint32 build = [2195|2600]
2361 * extra unicode string = e.g. "Service Pack 3"
2363 if (!StrCaseCmp(value, "OSVersion")) {
2364 *type = REG_BINARY;
2365 *needed = 0x114;
2367 if ( !(*data = TALLOC_ZERO_ARRAY(ctx, uint8, (*needed > in_size) ? *needed:in_size )) )
2368 return WERR_NOMEM;
2370 SIVAL(*data, 0, *needed); /* size */
2371 SIVAL(*data, 4, 5); /* Windows 2000 == 5.0 */
2372 SIVAL(*data, 8, 0);
2373 SIVAL(*data, 12, 2195); /* build */
2375 /* leave extra string empty */
2377 return WERR_OK;
2381 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2382 const char *string="C:\\PRINTERS";
2383 *type = REG_SZ;
2384 *needed = 2*(strlen(string)+1);
2385 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2386 return WERR_NOMEM;
2387 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2389 /* it's done by hand ready to go on the wire */
2390 for (i=0; i<strlen(string); i++) {
2391 (*data)[2*i]=string[i];
2392 (*data)[2*i+1]='\0';
2394 return WERR_OK;
2397 if (!StrCaseCmp(value, "Architecture")) {
2398 const char *string="Windows NT x86";
2399 *type = REG_SZ;
2400 *needed = 2*(strlen(string)+1);
2401 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2402 return WERR_NOMEM;
2403 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2404 for (i=0; i<strlen(string); i++) {
2405 (*data)[2*i]=string[i];
2406 (*data)[2*i+1]='\0';
2408 return WERR_OK;
2411 if (!StrCaseCmp(value, "DsPresent")) {
2412 *type = REG_DWORD;
2413 if ( !(*data = TALLOC_ARRAY(ctx, uint8, sizeof(uint32) )) )
2414 return WERR_NOMEM;
2416 /* only show the publish check box if we are a
2417 memeber of a AD domain */
2419 if ( lp_security() == SEC_ADS )
2420 SIVAL(*data, 0, 0x01);
2421 else
2422 SIVAL(*data, 0, 0x00);
2424 *needed = 0x4;
2425 return WERR_OK;
2428 if (!StrCaseCmp(value, "DNSMachineName")) {
2429 const char *hostname = get_mydnsfullname();
2431 if (!hostname)
2432 return WERR_BADFILE;
2433 *type = REG_SZ;
2434 *needed = 2*(strlen(hostname)+1);
2435 if((*data = (uint8 *)TALLOC(ctx, (*needed > in_size) ? *needed:in_size )) == NULL)
2436 return WERR_NOMEM;
2437 memset(*data, 0, (*needed > in_size) ? *needed:in_size);
2438 for (i=0; i<strlen(hostname); i++) {
2439 (*data)[2*i]=hostname[i];
2440 (*data)[2*i+1]='\0';
2442 return WERR_OK;
2446 return WERR_BADFILE;
2449 /********************************************************************
2450 * spoolss_getprinterdata
2451 ********************************************************************/
2453 WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
2455 POLICY_HND *handle = &q_u->handle;
2456 UNISTR2 *valuename = &q_u->valuename;
2457 uint32 in_size = q_u->size;
2458 uint32 *type = &r_u->type;
2459 uint32 *out_size = &r_u->size;
2460 uint8 **data = &r_u->data;
2461 uint32 *needed = &r_u->needed;
2462 WERROR status;
2463 fstring value;
2464 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
2465 NT_PRINTER_INFO_LEVEL *printer = NULL;
2466 int snum = 0;
2469 * Reminder: when it's a string, the length is in BYTES
2470 * even if UNICODE is negociated.
2472 * JFM, 4/19/1999
2475 *out_size = in_size;
2477 /* in case of problem, return some default values */
2479 *needed = 0;
2480 *type = 0;
2482 DEBUG(4,("_spoolss_getprinterdata\n"));
2484 if ( !Printer ) {
2485 DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2486 status = WERR_BADFID;
2487 goto done;
2490 unistr2_to_ascii(value, valuename, sizeof(value));
2492 if ( Printer->printer_type == SPLHND_SERVER )
2493 status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
2494 else
2496 if ( !get_printer_snum(p,handle, &snum, NULL) ) {
2497 status = WERR_BADFID;
2498 goto done;
2501 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
2502 if ( !W_ERROR_IS_OK(status) )
2503 goto done;
2505 /* XP sends this and wants to change id value from the PRINTER_INFO_0 */
2507 if ( strequal(value, "ChangeId") ) {
2508 *type = REG_DWORD;
2509 *needed = sizeof(uint32);
2510 if ( (*data = (uint8*)TALLOC(p->mem_ctx, sizeof(uint32))) == NULL) {
2511 status = WERR_NOMEM;
2512 goto done;
2514 SIVAL( *data, 0, printer->info_2->changeid );
2515 status = WERR_OK;
2517 else
2518 status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
2521 if (*needed > *out_size)
2522 status = WERR_MORE_DATA;
2524 done:
2525 if ( !W_ERROR_IS_OK(status) )
2527 DEBUG(5, ("error %d: allocating %d\n", W_ERROR_V(status),*out_size));
2529 /* reply this param doesn't exist */
2531 if ( *out_size ) {
2532 if((*data=(uint8 *)TALLOC_ZERO_ARRAY(p->mem_ctx, uint8, *out_size)) == NULL) {
2533 if ( printer )
2534 free_a_printer( &printer, 2 );
2535 return WERR_NOMEM;
2537 } else {
2538 *data = NULL;
2542 /* cleanup & exit */
2544 if ( printer )
2545 free_a_printer( &printer, 2 );
2547 return status;
2550 /*********************************************************
2551 Connect to the client machine.
2552 **********************************************************/
2554 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2555 struct sockaddr_storage *client_ss, const char *remote_machine)
2557 NTSTATUS ret;
2558 struct cli_state *the_cli;
2559 struct sockaddr_storage rm_addr;
2561 if ( is_zero_addr(client_ss) ) {
2562 if ( !resolve_name( remote_machine, &rm_addr, 0x20) ) {
2563 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2564 return False;
2567 if (ismyaddr(&rm_addr)) {
2568 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2569 return False;
2571 } else {
2572 char addr[INET6_ADDRSTRLEN];
2573 rm_addr = *client_ss;
2574 print_sockaddr(addr, sizeof(addr), &rm_addr);
2575 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2576 addr));
2579 /* setup the connection */
2581 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2582 &rm_addr, 0, "IPC$", "IPC",
2583 "", /* username */
2584 "", /* domain */
2585 "", /* password */
2586 0, lp_client_signing(), NULL );
2588 if ( !NT_STATUS_IS_OK( ret ) ) {
2589 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2590 remote_machine ));
2591 return False;
2594 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2595 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2596 cli_shutdown(the_cli);
2597 return False;
2601 * Ok - we have an anonymous connection to the IPC$ share.
2602 * Now start the NT Domain stuff :-).
2605 if ( !(*pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret)) ) {
2606 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2607 remote_machine, nt_errstr(ret)));
2608 cli_shutdown(the_cli);
2609 return False;
2612 /* make sure to save the cli_state pointer. Keep its own talloc_ctx */
2614 (*pp_pipe)->cli = the_cli;
2616 return True;
2619 /***************************************************************************
2620 Connect to the client.
2621 ****************************************************************************/
2623 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2624 uint32 localprinter, uint32 type,
2625 POLICY_HND *handle, struct sockaddr_storage *client_ss)
2627 WERROR result;
2630 * If it's the first connection, contact the client
2631 * and connect to the IPC$ share anonymously
2633 if (smb_connections==0) {
2634 fstring unix_printer;
2636 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2638 if ( !spoolss_connect_to_client( &notify_cli_pipe, client_ss, unix_printer ))
2639 return False;
2641 messaging_register(smbd_messaging_context(), NULL,
2642 MSG_PRINTER_NOTIFY2,
2643 receive_notify2_message_list);
2644 /* Tell the connections db we're now interested in printer
2645 * notify messages. */
2646 register_message_flags( True, FLAG_MSG_PRINT_NOTIFY );
2650 * Tell the specific printing tdb we want messages for this printer
2651 * by registering our PID.
2654 if (!print_notify_register_pid(snum))
2655 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2657 smb_connections++;
2659 result = rpccli_spoolss_reply_open_printer(notify_cli_pipe,
2660 talloc_tos(),
2661 printer,
2662 localprinter,
2663 type,
2664 handle);
2666 if (!W_ERROR_IS_OK(result))
2667 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2668 dos_errstr(result)));
2670 return (W_ERROR_IS_OK(result));
2673 /********************************************************************
2674 * _spoolss_rffpcnex
2675 * ReplyFindFirstPrinterChangeNotifyEx
2677 * before replying OK: status=0 a rpc call is made to the workstation
2678 * asking ReplyOpenPrinter
2680 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2681 * called from api_spoolss_rffpcnex
2682 ********************************************************************/
2684 WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNEX *r_u)
2686 POLICY_HND *handle = &q_u->handle;
2687 uint32 flags = q_u->flags;
2688 uint32 options = q_u->options;
2689 UNISTR2 *localmachine = &q_u->localmachine;
2690 uint32 printerlocal = q_u->printerlocal;
2691 int snum = -1;
2692 SPOOL_NOTIFY_OPTION *option = q_u->option;
2693 struct sockaddr_storage client_ss;
2695 /* store the notify value in the printer struct */
2697 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
2699 if (!Printer) {
2700 DEBUG(2,("_spoolss_rffpcnex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
2701 return WERR_BADFID;
2704 Printer->notify.flags=flags;
2705 Printer->notify.options=options;
2706 Printer->notify.printerlocal=printerlocal;
2708 if (Printer->notify.option)
2709 free_spool_notify_option(&Printer->notify.option);
2711 Printer->notify.option=dup_spool_notify_option(option);
2713 unistr2_to_ascii(Printer->notify.localmachine, localmachine,
2714 sizeof(Printer->notify.localmachine));
2716 /* Connect to the client machine and send a ReplyOpenPrinter */
2718 if ( Printer->printer_type == SPLHND_SERVER)
2719 snum = -1;
2720 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2721 !get_printer_snum(p, handle, &snum, NULL) )
2722 return WERR_BADFID;
2724 if (!interpret_string_addr(&client_ss,
2725 p->conn->client_address,
2726 AI_NUMERICHOST)) {
2727 return WERR_SERVER_UNAVAILABLE;
2730 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2731 Printer->notify.printerlocal, 1,
2732 &Printer->notify.client_hnd, &client_ss))
2733 return WERR_SERVER_UNAVAILABLE;
2735 Printer->notify.client_connected=True;
2737 return WERR_OK;
2740 /*******************************************************************
2741 * fill a notify_info_data with the servername
2742 ********************************************************************/
2744 void spoolss_notify_server_name(int snum,
2745 SPOOL_NOTIFY_INFO_DATA *data,
2746 print_queue_struct *queue,
2747 NT_PRINTER_INFO_LEVEL *printer,
2748 TALLOC_CTX *mem_ctx)
2750 smb_ucs2_t *temp = NULL;
2751 uint32 len;
2753 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->servername);
2754 if (len == (uint32)-1) {
2755 len = 0;
2758 data->notify_data.data.length = len;
2759 if (len) {
2760 data->notify_data.data.string = (uint16 *)temp;
2761 } else {
2762 data->notify_data.data.string = NULL;
2766 /*******************************************************************
2767 * fill a notify_info_data with the printername (not including the servername).
2768 ********************************************************************/
2770 void spoolss_notify_printer_name(int snum,
2771 SPOOL_NOTIFY_INFO_DATA *data,
2772 print_queue_struct *queue,
2773 NT_PRINTER_INFO_LEVEL *printer,
2774 TALLOC_CTX *mem_ctx)
2776 smb_ucs2_t *temp = NULL;
2777 uint32 len;
2779 /* the notify name should not contain the \\server\ part */
2780 char *p = strrchr(printer->info_2->printername, '\\');
2782 if (!p) {
2783 p = printer->info_2->printername;
2784 } else {
2785 p++;
2788 len = rpcstr_push_talloc(mem_ctx, &temp, p);
2789 if (len == (uint32)-1) {
2790 len = 0;
2793 data->notify_data.data.length = len;
2794 if (len) {
2795 data->notify_data.data.string = (uint16 *)temp;
2796 } else {
2797 data->notify_data.data.string = NULL;
2801 /*******************************************************************
2802 * fill a notify_info_data with the servicename
2803 ********************************************************************/
2805 void spoolss_notify_share_name(int snum,
2806 SPOOL_NOTIFY_INFO_DATA *data,
2807 print_queue_struct *queue,
2808 NT_PRINTER_INFO_LEVEL *printer,
2809 TALLOC_CTX *mem_ctx)
2811 smb_ucs2_t *temp = NULL;
2812 uint32 len;
2814 len = rpcstr_push_talloc(mem_ctx, &temp, lp_servicename(snum));
2815 if (len == (uint32)-1) {
2816 len = 0;
2819 data->notify_data.data.length = len;
2820 if (len) {
2821 data->notify_data.data.string = (uint16 *)temp;
2822 } else {
2823 data->notify_data.data.string = NULL;
2828 /*******************************************************************
2829 * fill a notify_info_data with the port name
2830 ********************************************************************/
2832 void spoolss_notify_port_name(int snum,
2833 SPOOL_NOTIFY_INFO_DATA *data,
2834 print_queue_struct *queue,
2835 NT_PRINTER_INFO_LEVEL *printer,
2836 TALLOC_CTX *mem_ctx)
2838 smb_ucs2_t *temp = NULL;
2839 uint32 len;
2841 /* even if it's strange, that's consistant in all the code */
2843 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->portname);
2844 if (len == (uint32)-1) {
2845 len = 0;
2848 data->notify_data.data.length = len;
2849 if (len) {
2850 data->notify_data.data.string = (uint16 *)temp;
2851 } else {
2852 data->notify_data.data.string = NULL;
2856 /*******************************************************************
2857 * fill a notify_info_data with the printername
2858 * but it doesn't exist, have to see what to do
2859 ********************************************************************/
2861 void spoolss_notify_driver_name(int snum,
2862 SPOOL_NOTIFY_INFO_DATA *data,
2863 print_queue_struct *queue,
2864 NT_PRINTER_INFO_LEVEL *printer,
2865 TALLOC_CTX *mem_ctx)
2867 smb_ucs2_t *temp = NULL;
2868 uint32 len;
2870 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->drivername);
2871 if (len == (uint32)-1) {
2872 len = 0;
2875 data->notify_data.data.length = len;
2876 if (len) {
2877 data->notify_data.data.string = (uint16 *)temp;
2878 } else {
2879 data->notify_data.data.string = NULL;
2883 /*******************************************************************
2884 * fill a notify_info_data with the comment
2885 ********************************************************************/
2887 void spoolss_notify_comment(int snum,
2888 SPOOL_NOTIFY_INFO_DATA *data,
2889 print_queue_struct *queue,
2890 NT_PRINTER_INFO_LEVEL *printer,
2891 TALLOC_CTX *mem_ctx)
2893 smb_ucs2_t *temp = NULL;
2894 uint32 len;
2896 if (*printer->info_2->comment == '\0')
2897 len = rpcstr_push_talloc(mem_ctx, &temp, lp_comment(snum));
2898 else
2899 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->comment);
2901 if (len == (uint32)-1) {
2902 len = 0;
2904 data->notify_data.data.length = len;
2905 if (len) {
2906 data->notify_data.data.string = (uint16 *)temp;
2907 } else {
2908 data->notify_data.data.string = NULL;
2912 /*******************************************************************
2913 * fill a notify_info_data with the comment
2914 * location = "Room 1, floor 2, building 3"
2915 ********************************************************************/
2917 void spoolss_notify_location(int snum,
2918 SPOOL_NOTIFY_INFO_DATA *data,
2919 print_queue_struct *queue,
2920 NT_PRINTER_INFO_LEVEL *printer,
2921 TALLOC_CTX *mem_ctx)
2923 smb_ucs2_t *temp = NULL;
2924 uint32 len;
2926 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->location);
2927 if (len == (uint32)-1) {
2928 len = 0;
2931 data->notify_data.data.length = len;
2932 if (len) {
2933 data->notify_data.data.string = (uint16 *)temp;
2934 } else {
2935 data->notify_data.data.string = NULL;
2939 /*******************************************************************
2940 * fill a notify_info_data with the device mode
2941 * jfm:xxxx don't to it for know but that's a real problem !!!
2942 ********************************************************************/
2944 static void spoolss_notify_devmode(int snum,
2945 SPOOL_NOTIFY_INFO_DATA *data,
2946 print_queue_struct *queue,
2947 NT_PRINTER_INFO_LEVEL *printer,
2948 TALLOC_CTX *mem_ctx)
2950 /* for a dummy implementation we have to zero the fields */
2951 data->notify_data.data.length = 0;
2952 data->notify_data.data.string = NULL;
2955 /*******************************************************************
2956 * fill a notify_info_data with the separator file name
2957 ********************************************************************/
2959 void spoolss_notify_sepfile(int snum,
2960 SPOOL_NOTIFY_INFO_DATA *data,
2961 print_queue_struct *queue,
2962 NT_PRINTER_INFO_LEVEL *printer,
2963 TALLOC_CTX *mem_ctx)
2965 smb_ucs2_t *temp = NULL;
2966 uint32 len;
2968 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->sepfile);
2969 if (len == (uint32)-1) {
2970 len = 0;
2973 data->notify_data.data.length = len;
2974 if (len) {
2975 data->notify_data.data.string = (uint16 *)temp;
2976 } else {
2977 data->notify_data.data.string = NULL;
2981 /*******************************************************************
2982 * fill a notify_info_data with the print processor
2983 * jfm:xxxx return always winprint to indicate we don't do anything to it
2984 ********************************************************************/
2986 void spoolss_notify_print_processor(int snum,
2987 SPOOL_NOTIFY_INFO_DATA *data,
2988 print_queue_struct *queue,
2989 NT_PRINTER_INFO_LEVEL *printer,
2990 TALLOC_CTX *mem_ctx)
2992 smb_ucs2_t *temp = NULL;
2993 uint32 len;
2995 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->printprocessor);
2996 if (len == (uint32)-1) {
2997 len = 0;
3000 data->notify_data.data.length = len;
3001 if (len) {
3002 data->notify_data.data.string = (uint16 *)temp;
3003 } else {
3004 data->notify_data.data.string = NULL;
3008 /*******************************************************************
3009 * fill a notify_info_data with the print processor options
3010 * jfm:xxxx send an empty string
3011 ********************************************************************/
3013 void spoolss_notify_parameters(int snum,
3014 SPOOL_NOTIFY_INFO_DATA *data,
3015 print_queue_struct *queue,
3016 NT_PRINTER_INFO_LEVEL *printer,
3017 TALLOC_CTX *mem_ctx)
3019 smb_ucs2_t *temp = NULL;
3020 uint32 len;
3022 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->parameters);
3023 if (len == (uint32)-1) {
3024 len = 0;
3027 data->notify_data.data.length = len;
3028 if (len) {
3029 data->notify_data.data.string = (uint16 *)temp;
3030 } else {
3031 data->notify_data.data.string = NULL;
3035 /*******************************************************************
3036 * fill a notify_info_data with the data type
3037 * jfm:xxxx always send RAW as data type
3038 ********************************************************************/
3040 void spoolss_notify_datatype(int snum,
3041 SPOOL_NOTIFY_INFO_DATA *data,
3042 print_queue_struct *queue,
3043 NT_PRINTER_INFO_LEVEL *printer,
3044 TALLOC_CTX *mem_ctx)
3046 smb_ucs2_t *temp = NULL;
3047 uint32 len;
3049 len = rpcstr_push_talloc(mem_ctx, &temp, printer->info_2->datatype);
3050 if (len == (uint32)-1) {
3051 len = 0;
3054 data->notify_data.data.length = len;
3055 if (len) {
3056 data->notify_data.data.string = (uint16 *)temp;
3057 } else {
3058 data->notify_data.data.string = NULL;
3062 /*******************************************************************
3063 * fill a notify_info_data with the security descriptor
3064 * jfm:xxxx send an null pointer to say no security desc
3065 * have to implement security before !
3066 ********************************************************************/
3068 static void spoolss_notify_security_desc(int snum,
3069 SPOOL_NOTIFY_INFO_DATA *data,
3070 print_queue_struct *queue,
3071 NT_PRINTER_INFO_LEVEL *printer,
3072 TALLOC_CTX *mem_ctx)
3074 data->notify_data.sd.size = printer->info_2->secdesc_buf->sd_size;
3075 data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sd ) ;
3078 /*******************************************************************
3079 * fill a notify_info_data with the attributes
3080 * jfm:xxxx a samba printer is always shared
3081 ********************************************************************/
3083 void spoolss_notify_attributes(int snum,
3084 SPOOL_NOTIFY_INFO_DATA *data,
3085 print_queue_struct *queue,
3086 NT_PRINTER_INFO_LEVEL *printer,
3087 TALLOC_CTX *mem_ctx)
3089 data->notify_data.value[0] = printer->info_2->attributes;
3090 data->notify_data.value[1] = 0;
3093 /*******************************************************************
3094 * fill a notify_info_data with the priority
3095 ********************************************************************/
3097 static void spoolss_notify_priority(int snum,
3098 SPOOL_NOTIFY_INFO_DATA *data,
3099 print_queue_struct *queue,
3100 NT_PRINTER_INFO_LEVEL *printer,
3101 TALLOC_CTX *mem_ctx)
3103 data->notify_data.value[0] = printer->info_2->priority;
3104 data->notify_data.value[1] = 0;
3107 /*******************************************************************
3108 * fill a notify_info_data with the default priority
3109 ********************************************************************/
3111 static void spoolss_notify_default_priority(int snum,
3112 SPOOL_NOTIFY_INFO_DATA *data,
3113 print_queue_struct *queue,
3114 NT_PRINTER_INFO_LEVEL *printer,
3115 TALLOC_CTX *mem_ctx)
3117 data->notify_data.value[0] = printer->info_2->default_priority;
3118 data->notify_data.value[1] = 0;
3121 /*******************************************************************
3122 * fill a notify_info_data with the start time
3123 ********************************************************************/
3125 static void spoolss_notify_start_time(int snum,
3126 SPOOL_NOTIFY_INFO_DATA *data,
3127 print_queue_struct *queue,
3128 NT_PRINTER_INFO_LEVEL *printer,
3129 TALLOC_CTX *mem_ctx)
3131 data->notify_data.value[0] = printer->info_2->starttime;
3132 data->notify_data.value[1] = 0;
3135 /*******************************************************************
3136 * fill a notify_info_data with the until time
3137 ********************************************************************/
3139 static void spoolss_notify_until_time(int snum,
3140 SPOOL_NOTIFY_INFO_DATA *data,
3141 print_queue_struct *queue,
3142 NT_PRINTER_INFO_LEVEL *printer,
3143 TALLOC_CTX *mem_ctx)
3145 data->notify_data.value[0] = printer->info_2->untiltime;
3146 data->notify_data.value[1] = 0;
3149 /*******************************************************************
3150 * fill a notify_info_data with the status
3151 ********************************************************************/
3153 static void spoolss_notify_status(int snum,
3154 SPOOL_NOTIFY_INFO_DATA *data,
3155 print_queue_struct *queue,
3156 NT_PRINTER_INFO_LEVEL *printer,
3157 TALLOC_CTX *mem_ctx)
3159 print_status_struct status;
3161 print_queue_length(snum, &status);
3162 data->notify_data.value[0]=(uint32) status.status;
3163 data->notify_data.value[1] = 0;
3166 /*******************************************************************
3167 * fill a notify_info_data with the number of jobs queued
3168 ********************************************************************/
3170 void spoolss_notify_cjobs(int snum,
3171 SPOOL_NOTIFY_INFO_DATA *data,
3172 print_queue_struct *queue,
3173 NT_PRINTER_INFO_LEVEL *printer,
3174 TALLOC_CTX *mem_ctx)
3176 data->notify_data.value[0] = print_queue_length(snum, NULL);
3177 data->notify_data.value[1] = 0;
3180 /*******************************************************************
3181 * fill a notify_info_data with the average ppm
3182 ********************************************************************/
3184 static void spoolss_notify_average_ppm(int snum,
3185 SPOOL_NOTIFY_INFO_DATA *data,
3186 print_queue_struct *queue,
3187 NT_PRINTER_INFO_LEVEL *printer,
3188 TALLOC_CTX *mem_ctx)
3190 /* always respond 8 pages per minutes */
3191 /* a little hard ! */
3192 data->notify_data.value[0] = printer->info_2->averageppm;
3193 data->notify_data.value[1] = 0;
3196 /*******************************************************************
3197 * fill a notify_info_data with username
3198 ********************************************************************/
3200 static void spoolss_notify_username(int snum,
3201 SPOOL_NOTIFY_INFO_DATA *data,
3202 print_queue_struct *queue,
3203 NT_PRINTER_INFO_LEVEL *printer,
3204 TALLOC_CTX *mem_ctx)
3206 smb_ucs2_t *temp = NULL;
3207 uint32 len;
3209 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_user);
3210 if (len == (uint32)-1) {
3211 len = 0;
3214 data->notify_data.data.length = len;
3215 if (len) {
3216 data->notify_data.data.string = (uint16 *)temp;
3217 } else {
3218 data->notify_data.data.string = NULL;
3222 /*******************************************************************
3223 * fill a notify_info_data with job status
3224 ********************************************************************/
3226 static void spoolss_notify_job_status(int snum,
3227 SPOOL_NOTIFY_INFO_DATA *data,
3228 print_queue_struct *queue,
3229 NT_PRINTER_INFO_LEVEL *printer,
3230 TALLOC_CTX *mem_ctx)
3232 data->notify_data.value[0]=nt_printj_status(queue->status);
3233 data->notify_data.value[1] = 0;
3236 /*******************************************************************
3237 * fill a notify_info_data with job name
3238 ********************************************************************/
3240 static void spoolss_notify_job_name(int snum,
3241 SPOOL_NOTIFY_INFO_DATA *data,
3242 print_queue_struct *queue,
3243 NT_PRINTER_INFO_LEVEL *printer,
3244 TALLOC_CTX *mem_ctx)
3246 smb_ucs2_t *temp = NULL;
3247 uint32 len;
3249 len = rpcstr_push_talloc(mem_ctx, &temp, queue->fs_file);
3250 if (len == (uint32)-1) {
3251 len = 0;
3254 data->notify_data.data.length = len;
3255 if (len) {
3256 data->notify_data.data.string = (uint16 *)temp;
3257 } else {
3258 data->notify_data.data.string = NULL;
3262 /*******************************************************************
3263 * fill a notify_info_data with job status
3264 ********************************************************************/
3266 static void spoolss_notify_job_status_string(int snum,
3267 SPOOL_NOTIFY_INFO_DATA *data,
3268 print_queue_struct *queue,
3269 NT_PRINTER_INFO_LEVEL *printer,
3270 TALLOC_CTX *mem_ctx)
3273 * Now we're returning job status codes we just return a "" here. JRA.
3276 const char *p = "";
3277 smb_ucs2_t *temp = NULL;
3278 uint32 len;
3280 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
3281 p = "unknown";
3283 switch (queue->status) {
3284 case LPQ_QUEUED:
3285 p = "Queued";
3286 break;
3287 case LPQ_PAUSED:
3288 p = ""; /* NT provides the paused string */
3289 break;
3290 case LPQ_SPOOLING:
3291 p = "Spooling";
3292 break;
3293 case LPQ_PRINTING:
3294 p = "Printing";
3295 break;
3297 #endif /* NO LONGER NEEDED. */
3299 len = rpcstr_push_talloc(mem_ctx, &temp, p);
3300 if (len == (uint32)-1) {
3301 len = 0;
3304 data->notify_data.data.length = len;
3305 if (len) {
3306 data->notify_data.data.string = (uint16 *)temp;
3307 } else {
3308 data->notify_data.data.string = NULL;
3312 /*******************************************************************
3313 * fill a notify_info_data with job time
3314 ********************************************************************/
3316 static void spoolss_notify_job_time(int snum,
3317 SPOOL_NOTIFY_INFO_DATA *data,
3318 print_queue_struct *queue,
3319 NT_PRINTER_INFO_LEVEL *printer,
3320 TALLOC_CTX *mem_ctx)
3322 data->notify_data.value[0]=0x0;
3323 data->notify_data.value[1]=0;
3326 /*******************************************************************
3327 * fill a notify_info_data with job size
3328 ********************************************************************/
3330 static void spoolss_notify_job_size(int snum,
3331 SPOOL_NOTIFY_INFO_DATA *data,
3332 print_queue_struct *queue,
3333 NT_PRINTER_INFO_LEVEL *printer,
3334 TALLOC_CTX *mem_ctx)
3336 data->notify_data.value[0]=queue->size;
3337 data->notify_data.value[1]=0;
3340 /*******************************************************************
3341 * fill a notify_info_data with page info
3342 ********************************************************************/
3343 static void spoolss_notify_total_pages(int snum,
3344 SPOOL_NOTIFY_INFO_DATA *data,
3345 print_queue_struct *queue,
3346 NT_PRINTER_INFO_LEVEL *printer,
3347 TALLOC_CTX *mem_ctx)
3349 data->notify_data.value[0]=queue->page_count;
3350 data->notify_data.value[1]=0;
3353 /*******************************************************************
3354 * fill a notify_info_data with pages printed info.
3355 ********************************************************************/
3356 static void spoolss_notify_pages_printed(int snum,
3357 SPOOL_NOTIFY_INFO_DATA *data,
3358 print_queue_struct *queue,
3359 NT_PRINTER_INFO_LEVEL *printer,
3360 TALLOC_CTX *mem_ctx)
3362 data->notify_data.value[0]=0; /* Add code when back-end tracks this */
3363 data->notify_data.value[1]=0;
3366 /*******************************************************************
3367 Fill a notify_info_data with job position.
3368 ********************************************************************/
3370 static void spoolss_notify_job_position(int snum,
3371 SPOOL_NOTIFY_INFO_DATA *data,
3372 print_queue_struct *queue,
3373 NT_PRINTER_INFO_LEVEL *printer,
3374 TALLOC_CTX *mem_ctx)
3376 data->notify_data.value[0]=queue->job;
3377 data->notify_data.value[1]=0;
3380 /*******************************************************************
3381 Fill a notify_info_data with submitted time.
3382 ********************************************************************/
3384 static void spoolss_notify_submitted_time(int snum,
3385 SPOOL_NOTIFY_INFO_DATA *data,
3386 print_queue_struct *queue,
3387 NT_PRINTER_INFO_LEVEL *printer,
3388 TALLOC_CTX *mem_ctx)
3390 struct tm *t;
3391 uint32 len;
3392 SYSTEMTIME st;
3393 char *p;
3395 t=gmtime(&queue->time);
3397 len = sizeof(SYSTEMTIME);
3399 data->notify_data.data.length = len;
3400 data->notify_data.data.string = (uint16 *)TALLOC(mem_ctx, len);
3402 if (!data->notify_data.data.string) {
3403 data->notify_data.data.length = 0;
3404 return;
3407 make_systemtime(&st, t);
3410 * Systemtime must be linearized as a set of UINT16's.
3411 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
3414 p = (char *)data->notify_data.data.string;
3415 SSVAL(p, 0, st.year);
3416 SSVAL(p, 2, st.month);
3417 SSVAL(p, 4, st.dayofweek);
3418 SSVAL(p, 6, st.day);
3419 SSVAL(p, 8, st.hour);
3420 SSVAL(p, 10, st.minute);
3421 SSVAL(p, 12, st.second);
3422 SSVAL(p, 14, st.milliseconds);
3425 struct s_notify_info_data_table
3427 uint16 type;
3428 uint16 field;
3429 const char *name;
3430 uint32 size;
3431 void (*fn) (int snum, SPOOL_NOTIFY_INFO_DATA *data,
3432 print_queue_struct *queue,
3433 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3436 /* A table describing the various print notification constants and
3437 whether the notification data is a pointer to a variable sized
3438 buffer, a one value uint32 or a two value uint32. */
3440 static const struct s_notify_info_data_table notify_info_data_table[] =
3442 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3443 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3444 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
3445 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3446 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3447 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
3448 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
3449 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3450 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
3451 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3452 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3453 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3454 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
3455 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
3456 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3457 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
3458 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3459 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3460 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
3461 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
3462 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
3463 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
3464 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
3465 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
3466 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
3467 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
3468 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
3469 { JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
3470 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
3471 { JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
3472 { JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
3473 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
3474 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
3475 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
3476 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
3477 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
3478 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
3479 { JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
3480 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
3481 { JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
3482 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
3483 { JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
3484 { JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
3485 { JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
3486 { JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
3487 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
3488 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
3489 { JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
3490 { JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
3491 { PRINT_TABLE_END, 0x0, NULL, 0x0, NULL },
3494 /*******************************************************************
3495 Return the size of info_data structure.
3496 ********************************************************************/
3498 static uint32 size_of_notify_info_data(uint16 type, uint16 field)
3500 int i=0;
3502 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3503 if ( (notify_info_data_table[i].type == type)
3504 && (notify_info_data_table[i].field == field) ) {
3505 switch(notify_info_data_table[i].size) {
3506 case NOTIFY_ONE_VALUE:
3507 case NOTIFY_TWO_VALUE:
3508 return 1;
3509 case NOTIFY_STRING:
3510 return 2;
3512 /* The only pointer notify data I have seen on
3513 the wire is the submitted time and this has
3514 the notify size set to 4. -tpot */
3516 case NOTIFY_POINTER:
3517 return 4;
3519 case NOTIFY_SECDESC:
3520 return 5;
3525 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3527 return 0;
3530 /*******************************************************************
3531 Return the type of notify_info_data.
3532 ********************************************************************/
3534 static uint32 type_of_notify_info_data(uint16 type, uint16 field)
3536 uint32 i=0;
3538 for (i = 0; i < (sizeof(notify_info_data_table)/sizeof(struct s_notify_info_data_table)); i++) {
3539 if (notify_info_data_table[i].type == type &&
3540 notify_info_data_table[i].field == field)
3541 return notify_info_data_table[i].size;
3544 return 0;
3547 /****************************************************************************
3548 ****************************************************************************/
3550 static bool search_notify(uint16 type, uint16 field, int *value)
3552 int i;
3554 for (i = 0; notify_info_data_table[i].type != PRINT_TABLE_END; i++) {
3555 if (notify_info_data_table[i].type == type &&
3556 notify_info_data_table[i].field == field &&
3557 notify_info_data_table[i].fn != NULL) {
3558 *value = i;
3559 return True;
3563 return False;
3566 /****************************************************************************
3567 ****************************************************************************/
3569 void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 field, int id)
3571 info_data->type = type;
3572 info_data->field = field;
3573 info_data->reserved = 0;
3575 info_data->size = size_of_notify_info_data(type, field);
3576 info_data->enc_type = type_of_notify_info_data(type, field);
3578 info_data->id = id;
3581 /*******************************************************************
3583 * fill a notify_info struct with info asked
3585 ********************************************************************/
3587 static bool construct_notify_printer_info(Printer_entry *print_hnd, SPOOL_NOTIFY_INFO *info, int
3588 snum, SPOOL_NOTIFY_OPTION_TYPE
3589 *option_type, uint32 id,
3590 TALLOC_CTX *mem_ctx)
3592 int field_num,j;
3593 uint16 type;
3594 uint16 field;
3596 SPOOL_NOTIFY_INFO_DATA *current_data;
3597 NT_PRINTER_INFO_LEVEL *printer = NULL;
3598 print_queue_struct *queue=NULL;
3600 type=option_type->type;
3602 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3603 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3604 option_type->count, lp_servicename(snum)));
3606 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3607 return False;
3609 for(field_num=0; field_num<option_type->count; field_num++) {
3610 field = option_type->fields[field_num];
3612 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3614 if (!search_notify(type, field, &j) )
3615 continue;
3617 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3618 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3619 free_a_printer(&printer, 2);
3620 return False;
3623 current_data = &info->data[info->count];
3625 construct_info_data(current_data, type, field, id);
3627 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3628 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3630 notify_info_data_table[j].fn(snum, current_data, queue,
3631 printer, mem_ctx);
3633 info->count++;
3636 free_a_printer(&printer, 2);
3637 return True;
3640 /*******************************************************************
3642 * fill a notify_info struct with info asked
3644 ********************************************************************/
3646 static bool construct_notify_jobs_info(print_queue_struct *queue,
3647 SPOOL_NOTIFY_INFO *info,
3648 NT_PRINTER_INFO_LEVEL *printer,
3649 int snum, SPOOL_NOTIFY_OPTION_TYPE
3650 *option_type, uint32 id,
3651 TALLOC_CTX *mem_ctx)
3653 int field_num,j;
3654 uint16 type;
3655 uint16 field;
3657 SPOOL_NOTIFY_INFO_DATA *current_data;
3659 DEBUG(4,("construct_notify_jobs_info\n"));
3661 type = option_type->type;
3663 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3664 (option_type->type==PRINTER_NOTIFY_TYPE?"PRINTER_NOTIFY_TYPE":"JOB_NOTIFY_TYPE"),
3665 option_type->count));
3667 for(field_num=0; field_num<option_type->count; field_num++) {
3668 field = option_type->fields[field_num];
3670 if (!search_notify(type, field, &j) )
3671 continue;
3673 if((info->data=SMB_REALLOC_ARRAY(info->data, SPOOL_NOTIFY_INFO_DATA, info->count+1)) == NULL) {
3674 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3675 return False;
3678 current_data=&(info->data[info->count]);
3680 construct_info_data(current_data, type, field, id);
3681 notify_info_data_table[j].fn(snum, current_data, queue,
3682 printer, mem_ctx);
3683 info->count++;
3686 return True;
3690 * JFM: The enumeration is not that simple, it's even non obvious.
3692 * let's take an example: I want to monitor the PRINTER SERVER for
3693 * the printer's name and the number of jobs currently queued.
3694 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3695 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3697 * I have 3 printers on the back of my server.
3699 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3700 * structures.
3701 * Number Data Id
3702 * 1 printer 1 name 1
3703 * 2 printer 1 cjob 1
3704 * 3 printer 2 name 2
3705 * 4 printer 2 cjob 2
3706 * 5 printer 3 name 3
3707 * 6 printer 3 name 3
3709 * that's the print server case, the printer case is even worse.
3712 /*******************************************************************
3714 * enumerate all printers on the printserver
3715 * fill a notify_info struct with info asked
3717 ********************************************************************/
3719 static WERROR printserver_notify_info(pipes_struct *p, POLICY_HND *hnd,
3720 SPOOL_NOTIFY_INFO *info,
3721 TALLOC_CTX *mem_ctx)
3723 int snum;
3724 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3725 int n_services=lp_numservices();
3726 int i;
3727 SPOOL_NOTIFY_OPTION *option;
3728 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3730 DEBUG(4,("printserver_notify_info\n"));
3732 if (!Printer)
3733 return WERR_BADFID;
3735 option=Printer->notify.option;
3736 info->version=2;
3737 info->data=NULL;
3738 info->count=0;
3740 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3741 sending a ffpcn() request first */
3743 if ( !option )
3744 return WERR_BADFID;
3746 for (i=0; i<option->count; i++) {
3747 option_type=&(option->ctr.type[i]);
3749 if (option_type->type!=PRINTER_NOTIFY_TYPE)
3750 continue;
3752 for (snum=0; snum<n_services; snum++)
3754 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3755 construct_notify_printer_info ( Printer, info, snum, option_type, snum, mem_ctx );
3759 #if 0
3761 * Debugging information, don't delete.
3764 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3765 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3766 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3768 for (i=0; i<info->count; i++) {
3769 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3770 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3771 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3773 #endif
3775 return WERR_OK;
3778 /*******************************************************************
3780 * fill a notify_info struct with info asked
3782 ********************************************************************/
3784 static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY_INFO *info,
3785 TALLOC_CTX *mem_ctx)
3787 int snum;
3788 Printer_entry *Printer=find_printer_index_by_hnd(p, hnd);
3789 int i;
3790 uint32 id;
3791 SPOOL_NOTIFY_OPTION *option;
3792 SPOOL_NOTIFY_OPTION_TYPE *option_type;
3793 int count,j;
3794 print_queue_struct *queue=NULL;
3795 print_status_struct status;
3797 DEBUG(4,("printer_notify_info\n"));
3799 if (!Printer)
3800 return WERR_BADFID;
3802 option=Printer->notify.option;
3803 id = 0x0;
3804 info->version=2;
3805 info->data=NULL;
3806 info->count=0;
3808 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3809 sending a ffpcn() request first */
3811 if ( !option )
3812 return WERR_BADFID;
3814 get_printer_snum(p, hnd, &snum, NULL);
3816 for (i=0; i<option->count; i++) {
3817 option_type=&option->ctr.type[i];
3819 switch ( option_type->type ) {
3820 case PRINTER_NOTIFY_TYPE:
3821 if(construct_notify_printer_info(Printer, info, snum,
3822 option_type, id,
3823 mem_ctx))
3824 id--;
3825 break;
3827 case JOB_NOTIFY_TYPE: {
3828 NT_PRINTER_INFO_LEVEL *printer = NULL;
3830 count = print_queue_status(snum, &queue, &status);
3832 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3833 goto done;
3835 for (j=0; j<count; j++) {
3836 construct_notify_jobs_info(&queue[j], info,
3837 printer, snum,
3838 option_type,
3839 queue[j].job,
3840 mem_ctx);
3843 free_a_printer(&printer, 2);
3845 done:
3846 SAFE_FREE(queue);
3847 break;
3853 * Debugging information, don't delete.
3856 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3857 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3858 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3860 for (i=0; i<info->count; i++) {
3861 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3862 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3863 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3866 return WERR_OK;
3869 /********************************************************************
3870 * spoolss_rfnpcnex
3871 ********************************************************************/
3873 WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
3875 POLICY_HND *handle = &q_u->handle;
3876 SPOOL_NOTIFY_INFO *info = &r_u->info;
3878 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
3879 WERROR result = WERR_BADFID;
3881 /* we always have a NOTIFY_INFO struct */
3882 r_u->info_ptr=0x1;
3884 if (!Printer) {
3885 DEBUG(2,("_spoolss_rfnpcnex: Invalid handle (%s:%u:%u).\n",
3886 OUR_HANDLE(handle)));
3887 goto done;
3890 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3893 * We are now using the change value, and
3894 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3895 * I don't have a global notification system, I'm sending back all the
3896 * informations even when _NOTHING_ has changed.
3899 /* We need to keep track of the change value to send back in
3900 RRPCN replies otherwise our updates are ignored. */
3902 Printer->notify.fnpcn = True;
3904 if (Printer->notify.client_connected) {
3905 DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
3906 Printer->notify.change = q_u->change;
3909 /* just ignore the SPOOL_NOTIFY_OPTION */
3911 switch (Printer->printer_type) {
3912 case SPLHND_SERVER:
3913 result = printserver_notify_info(p, handle, info, p->mem_ctx);
3914 break;
3916 case SPLHND_PRINTER:
3917 result = printer_notify_info(p, handle, info, p->mem_ctx);
3918 break;
3921 Printer->notify.fnpcn = False;
3923 done:
3924 return result;
3927 /********************************************************************
3928 * construct_printer_info_0
3929 * fill a printer_info_0 struct
3930 ********************************************************************/
3932 static bool construct_printer_info_0(Printer_entry *print_hnd, PRINTER_INFO_0 *printer, int snum)
3934 char *chaine = NULL;
3935 int count;
3936 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
3937 counter_printer_0 *session_counter;
3938 uint32 global_counter;
3939 struct tm *t;
3940 time_t setuptime;
3941 print_status_struct status;
3942 TALLOC_CTX *ctx = talloc_tos();
3944 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
3945 return False;
3947 init_unistr(&printer->printername, ntprinter->info_2->printername);
3949 chaine = talloc_asprintf(ctx, "\\\\%s", get_server_name(print_hnd));
3950 if (!chaine) {
3951 free_a_printer(&ntprinter,2);
3952 return false;
3955 count = print_queue_length(snum, &status);
3957 /* check if we already have a counter for this printer */
3958 for(session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3959 if (session_counter->snum == snum)
3960 break;
3963 init_unistr(&printer->servername, chaine);
3965 /* it's the first time, add it to the list */
3966 if (session_counter==NULL) {
3967 if((session_counter=SMB_MALLOC_P(counter_printer_0)) == NULL) {
3968 free_a_printer(&ntprinter, 2);
3969 return False;
3971 ZERO_STRUCTP(session_counter);
3972 session_counter->snum=snum;
3973 session_counter->counter=0;
3974 DLIST_ADD(counter_list, session_counter);
3977 /* increment it */
3978 session_counter->counter++;
3980 /* JFM:
3981 * the global_counter should be stored in a TDB as it's common to all the clients
3982 * and should be zeroed on samba startup
3984 global_counter=session_counter->counter;
3985 printer->cjobs = count;
3986 printer->total_jobs = 0;
3987 printer->total_bytes = 0;
3989 setuptime = (time_t)ntprinter->info_2->setuptime;
3990 t=gmtime(&setuptime);
3992 printer->year = t->tm_year+1900;
3993 printer->month = t->tm_mon+1;
3994 printer->dayofweek = t->tm_wday;
3995 printer->day = t->tm_mday;
3996 printer->hour = t->tm_hour;
3997 printer->minute = t->tm_min;
3998 printer->second = t->tm_sec;
3999 printer->milliseconds = 0;
4001 printer->global_counter = global_counter;
4002 printer->total_pages = 0;
4004 /* in 2.2 we reported ourselves as 0x0004 and 0x0565 */
4005 printer->major_version = 0x0005; /* NT 5 */
4006 printer->build_version = 0x0893; /* build 2195 */
4008 printer->unknown7 = 0x1;
4009 printer->unknown8 = 0x0;
4010 printer->unknown9 = 0x0;
4011 printer->session_counter = session_counter->counter;
4012 printer->unknown11 = 0x0;
4013 printer->printer_errors = 0x0; /* number of print failure */
4014 printer->unknown13 = 0x0;
4015 printer->unknown14 = 0x1;
4016 printer->unknown15 = 0x024a; /* 586 Pentium ? */
4017 printer->unknown16 = 0x0;
4018 printer->change_id = ntprinter->info_2->changeid; /* ChangeID in milliseconds*/
4019 printer->unknown18 = 0x0;
4020 printer->status = nt_printq_status(status.status);
4021 printer->unknown20 = 0x0;
4022 printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */
4023 printer->unknown22 = 0x0;
4024 printer->unknown23 = 0x6; /* 6 ???*/
4025 printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */
4026 printer->unknown25 = 0;
4027 printer->unknown26 = 0;
4028 printer->unknown27 = 0;
4029 printer->unknown28 = 0;
4030 printer->unknown29 = 0;
4032 free_a_printer(&ntprinter,2);
4033 return (True);
4036 /********************************************************************
4037 * construct_printer_info_1
4038 * fill a printer_info_1 struct
4039 ********************************************************************/
4040 static bool construct_printer_info_1(Printer_entry *print_hnd, uint32 flags, PRINTER_INFO_1 *printer, int snum)
4042 char *chaine = NULL;
4043 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4044 TALLOC_CTX *ctx = talloc_tos();
4046 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4047 return false;
4049 printer->flags=flags;
4051 if (*ntprinter->info_2->comment == '\0') {
4052 init_unistr(&printer->comment, lp_comment(snum));
4053 chaine = talloc_asprintf(ctx,
4054 "%s,%s,%s", ntprinter->info_2->printername,
4055 ntprinter->info_2->drivername, lp_comment(snum));
4057 else {
4058 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4059 chaine = talloc_asprintf(ctx,
4060 "%s,%s,%s", ntprinter->info_2->printername,
4061 ntprinter->info_2->drivername, ntprinter->info_2->comment);
4064 if (!chaine) {
4065 free_a_printer(&ntprinter,2);
4066 return false;
4069 init_unistr(&printer->description, chaine);
4070 init_unistr(&printer->name, ntprinter->info_2->printername);
4072 free_a_printer(&ntprinter,2);
4074 return True;
4077 /****************************************************************************
4078 Free a DEVMODE struct.
4079 ****************************************************************************/
4081 static void free_dev_mode(DEVICEMODE *dev)
4083 if (dev == NULL)
4084 return;
4086 SAFE_FREE(dev->dev_private);
4087 SAFE_FREE(dev);
4091 /****************************************************************************
4092 Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
4093 should be valid upon entry
4094 ****************************************************************************/
4096 static bool convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
4098 if ( !devmode || !ntdevmode )
4099 return False;
4101 init_unistr(&devmode->devicename, ntdevmode->devicename);
4103 init_unistr(&devmode->formname, ntdevmode->formname);
4105 devmode->specversion = ntdevmode->specversion;
4106 devmode->driverversion = ntdevmode->driverversion;
4107 devmode->size = ntdevmode->size;
4108 devmode->driverextra = ntdevmode->driverextra;
4109 devmode->fields = ntdevmode->fields;
4111 devmode->orientation = ntdevmode->orientation;
4112 devmode->papersize = ntdevmode->papersize;
4113 devmode->paperlength = ntdevmode->paperlength;
4114 devmode->paperwidth = ntdevmode->paperwidth;
4115 devmode->scale = ntdevmode->scale;
4116 devmode->copies = ntdevmode->copies;
4117 devmode->defaultsource = ntdevmode->defaultsource;
4118 devmode->printquality = ntdevmode->printquality;
4119 devmode->color = ntdevmode->color;
4120 devmode->duplex = ntdevmode->duplex;
4121 devmode->yresolution = ntdevmode->yresolution;
4122 devmode->ttoption = ntdevmode->ttoption;
4123 devmode->collate = ntdevmode->collate;
4124 devmode->icmmethod = ntdevmode->icmmethod;
4125 devmode->icmintent = ntdevmode->icmintent;
4126 devmode->mediatype = ntdevmode->mediatype;
4127 devmode->dithertype = ntdevmode->dithertype;
4129 if (ntdevmode->nt_dev_private != NULL) {
4130 if ((devmode->dev_private=(uint8 *)memdup(ntdevmode->nt_dev_private, ntdevmode->driverextra)) == NULL)
4131 return False;
4134 return True;
4137 /****************************************************************************
4138 Create a DEVMODE struct. Returns malloced memory.
4139 ****************************************************************************/
4141 DEVICEMODE *construct_dev_mode(const char *servicename)
4143 NT_PRINTER_INFO_LEVEL *printer = NULL;
4144 DEVICEMODE *devmode = NULL;
4146 DEBUG(7,("construct_dev_mode\n"));
4148 DEBUGADD(8,("getting printer characteristics\n"));
4150 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, servicename)))
4151 return NULL;
4153 if ( !printer->info_2->devmode ) {
4154 DEBUG(5, ("BONG! There was no device mode!\n"));
4155 goto done;
4158 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) == NULL) {
4159 DEBUG(2,("construct_dev_mode: malloc fail.\n"));
4160 goto done;
4163 ZERO_STRUCTP(devmode);
4165 DEBUGADD(8,("loading DEVICEMODE\n"));
4167 if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
4168 free_dev_mode( devmode );
4169 devmode = NULL;
4172 done:
4173 free_a_printer(&printer,2);
4175 return devmode;
4178 /********************************************************************
4179 * construct_printer_info_2
4180 * fill a printer_info_2 struct
4181 ********************************************************************/
4183 static bool construct_printer_info_2(Printer_entry *print_hnd, PRINTER_INFO_2 *printer, int snum)
4185 int count;
4186 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4188 print_status_struct status;
4190 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4191 return False;
4193 count = print_queue_length(snum, &status);
4195 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4196 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4197 init_unistr(&printer->sharename, lp_servicename(snum)); /* sharename */
4198 init_unistr(&printer->portname, ntprinter->info_2->portname); /* port */
4199 init_unistr(&printer->drivername, ntprinter->info_2->drivername); /* drivername */
4201 if (*ntprinter->info_2->comment == '\0')
4202 init_unistr(&printer->comment, lp_comment(snum)); /* comment */
4203 else
4204 init_unistr(&printer->comment, ntprinter->info_2->comment); /* saved comment. */
4206 init_unistr(&printer->location, ntprinter->info_2->location); /* location */
4207 init_unistr(&printer->sepfile, ntprinter->info_2->sepfile); /* separator file */
4208 init_unistr(&printer->printprocessor, ntprinter->info_2->printprocessor);/* print processor */
4209 init_unistr(&printer->datatype, ntprinter->info_2->datatype); /* datatype */
4210 init_unistr(&printer->parameters, ntprinter->info_2->parameters); /* parameters (of print processor) */
4212 printer->attributes = ntprinter->info_2->attributes;
4214 printer->priority = ntprinter->info_2->priority; /* priority */
4215 printer->defaultpriority = ntprinter->info_2->default_priority; /* default priority */
4216 printer->starttime = ntprinter->info_2->starttime; /* starttime */
4217 printer->untiltime = ntprinter->info_2->untiltime; /* untiltime */
4218 printer->status = nt_printq_status(status.status); /* status */
4219 printer->cjobs = count; /* jobs */
4220 printer->averageppm = ntprinter->info_2->averageppm; /* average pages per minute */
4222 if ( !(printer->devmode = construct_dev_mode(
4223 lp_const_servicename(snum))) )
4224 DEBUG(8, ("Returning NULL Devicemode!\n"));
4226 printer->secdesc = NULL;
4228 if ( ntprinter->info_2->secdesc_buf
4229 && ntprinter->info_2->secdesc_buf->sd_size != 0 )
4231 /* don't use talloc_steal() here unless you do a deep steal of all
4232 the SEC_DESC members */
4234 printer->secdesc = dup_sec_desc( talloc_tos(),
4235 ntprinter->info_2->secdesc_buf->sd );
4238 free_a_printer(&ntprinter, 2);
4240 return True;
4243 /********************************************************************
4244 * construct_printer_info_3
4245 * fill a printer_info_3 struct
4246 ********************************************************************/
4248 static bool construct_printer_info_3(Printer_entry *print_hnd, PRINTER_INFO_3 **pp_printer, int snum)
4250 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4251 PRINTER_INFO_3 *printer = NULL;
4253 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4254 return False;
4256 *pp_printer = NULL;
4257 if ((printer = SMB_MALLOC_P(PRINTER_INFO_3)) == NULL) {
4258 DEBUG(2,("construct_printer_info_3: malloc fail.\n"));
4259 free_a_printer(&ntprinter, 2);
4260 return False;
4263 ZERO_STRUCTP(printer);
4265 /* These are the components of the SD we are returning. */
4267 if (ntprinter->info_2->secdesc_buf && ntprinter->info_2->secdesc_buf->sd_size != 0) {
4268 /* don't use talloc_steal() here unless you do a deep steal of all
4269 the SEC_DESC members */
4271 printer->secdesc = dup_sec_desc( talloc_tos(),
4272 ntprinter->info_2->secdesc_buf->sd );
4275 free_a_printer(&ntprinter, 2);
4277 *pp_printer = printer;
4278 return True;
4281 /********************************************************************
4282 * construct_printer_info_4
4283 * fill a printer_info_4 struct
4284 ********************************************************************/
4286 static bool construct_printer_info_4(Printer_entry *print_hnd, PRINTER_INFO_4 *printer, int snum)
4288 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4290 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4291 return False;
4293 init_unistr(&printer->printername, ntprinter->info_2->printername); /* printername*/
4294 init_unistr(&printer->servername, ntprinter->info_2->servername); /* servername*/
4295 printer->attributes = ntprinter->info_2->attributes;
4297 free_a_printer(&ntprinter, 2);
4298 return True;
4301 /********************************************************************
4302 * construct_printer_info_5
4303 * fill a printer_info_5 struct
4304 ********************************************************************/
4306 static bool construct_printer_info_5(Printer_entry *print_hnd, PRINTER_INFO_5 *printer, int snum)
4308 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4310 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2, lp_const_servicename(snum))))
4311 return False;
4313 init_unistr(&printer->printername, ntprinter->info_2->printername);
4314 init_unistr(&printer->portname, ntprinter->info_2->portname);
4315 printer->attributes = ntprinter->info_2->attributes;
4317 /* these two are not used by NT+ according to MSDN */
4319 printer->device_not_selected_timeout = 0x0; /* have seen 0x3a98 */
4320 printer->transmission_retry_timeout = 0x0; /* have seen 0xafc8 */
4322 free_a_printer(&ntprinter, 2);
4324 return True;
4327 /********************************************************************
4328 * construct_printer_info_6
4329 * fill a printer_info_6 struct
4330 ********************************************************************/
4332 static bool construct_printer_info_6(Printer_entry *print_hnd,
4333 PRINTER_INFO_6 *printer,
4334 int snum)
4336 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
4337 int count;
4338 print_status_struct status;
4340 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &ntprinter, 2,
4341 lp_const_servicename(snum))))
4342 return False;
4344 count = print_queue_length(snum, &status);
4346 printer->status = nt_printq_status(status.status);
4348 free_a_printer(&ntprinter, 2);
4350 return True;
4353 /********************************************************************
4354 * construct_printer_info_7
4355 * fill a printer_info_7 struct
4356 ********************************************************************/
4358 static bool construct_printer_info_7(Printer_entry *print_hnd, PRINTER_INFO_7 *printer, int snum)
4360 char *guid_str = NULL;
4361 struct GUID guid;
4363 if (is_printer_published(print_hnd, snum, &guid)) {
4364 if (asprintf(&guid_str, "{%s}",
4365 smb_uuid_string(talloc_tos(), guid)) == -1) {
4366 return false;
4368 strupper_m(guid_str);
4369 init_unistr(&printer->guid, guid_str);
4370 SAFE_FREE(guid_str);
4371 printer->action = SPOOL_DS_PUBLISH;
4372 } else {
4373 init_unistr(&printer->guid, "");
4374 printer->action = SPOOL_DS_UNPUBLISH;
4377 return True;
4380 /********************************************************************
4381 Spoolss_enumprinters.
4382 ********************************************************************/
4384 static WERROR enum_all_printers_info_1(uint32 flags, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4386 int snum;
4387 int i;
4388 int n_services=lp_numservices();
4389 PRINTER_INFO_1 *printers=NULL;
4390 PRINTER_INFO_1 current_prt;
4391 WERROR result = WERR_OK;
4393 DEBUG(4,("enum_all_printers_info_1\n"));
4395 for (snum=0; snum<n_services; snum++) {
4396 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4397 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4399 if (construct_printer_info_1(NULL, flags, &current_prt, snum)) {
4400 if((printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_1, *returned +1)) == NULL) {
4401 DEBUG(2,("enum_all_printers_info_1: failed to enlarge printers buffer!\n"));
4402 *returned=0;
4403 return WERR_NOMEM;
4405 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_1\n", *returned));
4407 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_1));
4408 (*returned)++;
4413 /* check the required size. */
4414 for (i=0; i<*returned; i++)
4415 (*needed) += spoolss_size_printer_info_1(&printers[i]);
4417 if (*needed > offered) {
4418 result = WERR_INSUFFICIENT_BUFFER;
4419 goto out;
4422 if (!rpcbuf_alloc_size(buffer, *needed)) {
4423 result = WERR_NOMEM;
4424 goto out;
4427 /* fill the buffer with the structures */
4428 for (i=0; i<*returned; i++)
4429 smb_io_printer_info_1("", buffer, &printers[i], 0);
4431 out:
4432 /* clear memory */
4434 SAFE_FREE(printers);
4436 if ( !W_ERROR_IS_OK(result) )
4437 *returned = 0;
4439 return result;
4442 /********************************************************************
4443 enum_all_printers_info_1_local.
4444 *********************************************************************/
4446 static WERROR enum_all_printers_info_1_local(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4448 DEBUG(4,("enum_all_printers_info_1_local\n"));
4450 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4453 /********************************************************************
4454 enum_all_printers_info_1_name.
4455 *********************************************************************/
4457 static WERROR enum_all_printers_info_1_name(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4459 char *s = name;
4461 DEBUG(4,("enum_all_printers_info_1_name\n"));
4463 if ((name[0] == '\\') && (name[1] == '\\'))
4464 s = name + 2;
4466 if (is_myname_or_ipaddr(s)) {
4467 return enum_all_printers_info_1(PRINTER_ENUM_ICON8, buffer, offered, needed, returned);
4469 else
4470 return WERR_INVALID_NAME;
4473 #if 0 /* JERRY -- disabled for now. Don't think this is used, tested, or correct */
4474 /********************************************************************
4475 enum_all_printers_info_1_remote.
4476 *********************************************************************/
4478 static WERROR enum_all_printers_info_1_remote(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4480 PRINTER_INFO_1 *printer;
4481 fstring printername;
4482 fstring desc;
4483 fstring comment;
4484 DEBUG(4,("enum_all_printers_info_1_remote\n"));
4485 WERROR result = WERR_OK;
4487 /* JFM: currently it's more a place holder than anything else.
4488 * In the spooler world there is a notion of server registration.
4489 * the print servers are registered on the PDC (in the same domain)
4491 * We should have a TDB here. The registration is done thru an
4492 * undocumented RPC call.
4495 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4496 return WERR_NOMEM;
4498 *returned=1;
4500 slprintf(printername, sizeof(printername)-1,"Windows NT Remote Printers!!\\\\%s", name);
4501 slprintf(desc, sizeof(desc)-1,"%s", name);
4502 slprintf(comment, sizeof(comment)-1, "Logged on Domain");
4504 init_unistr(&printer->description, desc);
4505 init_unistr(&printer->name, printername);
4506 init_unistr(&printer->comment, comment);
4507 printer->flags=PRINTER_ENUM_ICON3|PRINTER_ENUM_CONTAINER;
4509 /* check the required size. */
4510 *needed += spoolss_size_printer_info_1(printer);
4512 if (*needed > offered) {
4513 result = WERR_INSUFFICIENT_BUFFER;
4514 goto out;
4517 if (!rpcbuf_alloc_size(buffer, *needed)) {
4518 result = WERR_NOMEM;
4519 goto out;
4522 /* fill the buffer with the structures */
4523 smb_io_printer_info_1("", buffer, printer, 0);
4525 out:
4526 /* clear memory */
4527 SAFE_FREE(printer);
4529 if ( !W_ERROR_IS_OK(result) )
4530 *returned = 0;
4532 return result;
4535 #endif
4537 /********************************************************************
4538 enum_all_printers_info_1_network.
4539 *********************************************************************/
4541 static WERROR enum_all_printers_info_1_network(fstring name, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4543 char *s = name;
4545 DEBUG(4,("enum_all_printers_info_1_network\n"));
4547 /* If we respond to a enum_printers level 1 on our name with flags
4548 set to PRINTER_ENUM_REMOTE with a list of printers then these
4549 printers incorrectly appear in the APW browse list.
4550 Specifically the printers for the server appear at the workgroup
4551 level where all the other servers in the domain are
4552 listed. Windows responds to this call with a
4553 WERR_CAN_NOT_COMPLETE so we should do the same. */
4555 if (name[0] == '\\' && name[1] == '\\')
4556 s = name + 2;
4558 if (is_myname_or_ipaddr(s))
4559 return WERR_CAN_NOT_COMPLETE;
4561 return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);
4564 /********************************************************************
4565 * api_spoolss_enumprinters
4567 * called from api_spoolss_enumprinters (see this to understand)
4568 ********************************************************************/
4570 static WERROR enum_all_printers_info_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
4572 int snum;
4573 int i;
4574 int n_services=lp_numservices();
4575 PRINTER_INFO_2 *printers=NULL;
4576 PRINTER_INFO_2 current_prt;
4577 WERROR result = WERR_OK;
4579 *returned = 0;
4581 for (snum=0; snum<n_services; snum++) {
4582 if (lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) ) {
4583 DEBUG(4,("Found a printer in smb.conf: %s[%x]\n", lp_servicename(snum), snum));
4585 if (construct_printer_info_2(NULL, &current_prt, snum)) {
4586 if ( !(printers=SMB_REALLOC_ARRAY(printers, PRINTER_INFO_2, *returned +1)) ) {
4587 DEBUG(2,("enum_all_printers_info_2: failed to enlarge printers buffer!\n"));
4588 *returned = 0;
4589 return WERR_NOMEM;
4592 DEBUG(4,("ReAlloced memory for [%d] PRINTER_INFO_2\n", *returned + 1));
4594 memcpy(&printers[*returned], &current_prt, sizeof(PRINTER_INFO_2));
4596 (*returned)++;
4601 /* check the required size. */
4602 for (i=0; i<*returned; i++)
4603 (*needed) += spoolss_size_printer_info_2(&printers[i]);
4605 if (*needed > offered) {
4606 result = WERR_INSUFFICIENT_BUFFER;
4607 goto out;
4610 if (!rpcbuf_alloc_size(buffer, *needed)) {
4611 result = WERR_NOMEM;
4612 goto out;
4615 /* fill the buffer with the structures */
4616 for (i=0; i<*returned; i++)
4617 smb_io_printer_info_2("", buffer, &(printers[i]), 0);
4619 out:
4620 /* clear memory */
4622 for (i=0; i<*returned; i++)
4623 free_devmode(printers[i].devmode);
4625 SAFE_FREE(printers);
4627 if ( !W_ERROR_IS_OK(result) )
4628 *returned = 0;
4630 return result;
4633 /********************************************************************
4634 * handle enumeration of printers at level 1
4635 ********************************************************************/
4637 static WERROR enumprinters_level1( uint32 flags, fstring name,
4638 RPC_BUFFER *buffer, uint32 offered,
4639 uint32 *needed, uint32 *returned)
4641 /* Not all the flags are equals */
4643 if (flags & PRINTER_ENUM_LOCAL)
4644 return enum_all_printers_info_1_local(buffer, offered, needed, returned);
4646 if (flags & PRINTER_ENUM_NAME)
4647 return enum_all_printers_info_1_name(name, buffer, offered, needed, returned);
4649 #if 0 /* JERRY - disabled for now */
4650 if (flags & PRINTER_ENUM_REMOTE)
4651 return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);
4652 #endif
4654 if (flags & PRINTER_ENUM_NETWORK)
4655 return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);
4657 return WERR_OK; /* NT4sp5 does that */
4660 /********************************************************************
4661 * handle enumeration of printers at level 2
4662 ********************************************************************/
4664 static WERROR enumprinters_level2( uint32 flags, fstring servername,
4665 RPC_BUFFER *buffer, uint32 offered,
4666 uint32 *needed, uint32 *returned)
4668 char *s = servername;
4670 if (flags & PRINTER_ENUM_LOCAL) {
4671 return enum_all_printers_info_2(buffer, offered, needed, returned);
4674 if (flags & PRINTER_ENUM_NAME) {
4675 if ((servername[0] == '\\') && (servername[1] == '\\'))
4676 s = servername + 2;
4677 if (is_myname_or_ipaddr(s))
4678 return enum_all_printers_info_2(buffer, offered, needed, returned);
4679 else
4680 return WERR_INVALID_NAME;
4683 if (flags & PRINTER_ENUM_REMOTE)
4684 return WERR_UNKNOWN_LEVEL;
4686 return WERR_OK;
4689 /********************************************************************
4690 * handle enumeration of printers at level 5
4691 ********************************************************************/
4693 static WERROR enumprinters_level5( uint32 flags, fstring servername,
4694 RPC_BUFFER *buffer, uint32 offered,
4695 uint32 *needed, uint32 *returned)
4697 /* return enum_all_printers_info_5(buffer, offered, needed, returned);*/
4698 return WERR_OK;
4701 /********************************************************************
4702 * api_spoolss_enumprinters
4704 * called from api_spoolss_enumprinters (see this to understand)
4705 ********************************************************************/
4707 WERROR _spoolss_enumprinters( pipes_struct *p, SPOOL_Q_ENUMPRINTERS *q_u, SPOOL_R_ENUMPRINTERS *r_u)
4709 uint32 flags = q_u->flags;
4710 UNISTR2 *servername = &q_u->servername;
4711 uint32 level = q_u->level;
4712 RPC_BUFFER *buffer = NULL;
4713 uint32 offered = q_u->offered;
4714 uint32 *needed = &r_u->needed;
4715 uint32 *returned = &r_u->returned;
4717 fstring name;
4719 /* that's an [in out] buffer */
4721 if (!q_u->buffer && (offered!=0)) {
4722 return WERR_INVALID_PARAM;
4725 rpcbuf_move(q_u->buffer, &r_u->buffer);
4726 buffer = r_u->buffer;
4728 DEBUG(4,("_spoolss_enumprinters\n"));
4730 *needed=0;
4731 *returned=0;
4734 * Level 1:
4735 * flags==PRINTER_ENUM_NAME
4736 * if name=="" then enumerates all printers
4737 * if name!="" then enumerate the printer
4738 * flags==PRINTER_ENUM_REMOTE
4739 * name is NULL, enumerate printers
4740 * Level 2: name!="" enumerates printers, name can't be NULL
4741 * Level 3: doesn't exist
4742 * Level 4: does a local registry lookup
4743 * Level 5: same as Level 2
4746 unistr2_to_ascii(name, servername, sizeof(name));
4747 strupper_m(name);
4749 switch (level) {
4750 case 1:
4751 return enumprinters_level1(flags, name, buffer, offered, needed, returned);
4752 case 2:
4753 return enumprinters_level2(flags, name, buffer, offered, needed, returned);
4754 case 5:
4755 return enumprinters_level5(flags, name, buffer, offered, needed, returned);
4756 case 3:
4757 case 4:
4758 break;
4760 return WERR_UNKNOWN_LEVEL;
4763 /****************************************************************************
4764 ****************************************************************************/
4766 static WERROR getprinter_level_0(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4768 PRINTER_INFO_0 *printer=NULL;
4769 WERROR result = WERR_OK;
4771 if((printer=SMB_MALLOC_P(PRINTER_INFO_0)) == NULL)
4772 return WERR_NOMEM;
4774 construct_printer_info_0(print_hnd, printer, snum);
4776 /* check the required size. */
4777 *needed += spoolss_size_printer_info_0(printer);
4779 if (*needed > offered) {
4780 result = WERR_INSUFFICIENT_BUFFER;
4781 goto out;
4784 if (!rpcbuf_alloc_size(buffer, *needed)) {
4785 result = WERR_NOMEM;
4786 goto out;
4789 /* fill the buffer with the structures */
4790 smb_io_printer_info_0("", buffer, printer, 0);
4792 out:
4793 /* clear memory */
4795 SAFE_FREE(printer);
4797 return result;
4800 /****************************************************************************
4801 ****************************************************************************/
4803 static WERROR getprinter_level_1(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4805 PRINTER_INFO_1 *printer=NULL;
4806 WERROR result = WERR_OK;
4808 if((printer=SMB_MALLOC_P(PRINTER_INFO_1)) == NULL)
4809 return WERR_NOMEM;
4811 construct_printer_info_1(print_hnd, PRINTER_ENUM_ICON8, printer, snum);
4813 /* check the required size. */
4814 *needed += spoolss_size_printer_info_1(printer);
4816 if (*needed > offered) {
4817 result = WERR_INSUFFICIENT_BUFFER;
4818 goto out;
4821 if (!rpcbuf_alloc_size(buffer, *needed)) {
4822 result = WERR_NOMEM;
4823 goto out;
4826 /* fill the buffer with the structures */
4827 smb_io_printer_info_1("", buffer, printer, 0);
4829 out:
4830 /* clear memory */
4831 SAFE_FREE(printer);
4833 return result;
4836 /****************************************************************************
4837 ****************************************************************************/
4839 static WERROR getprinter_level_2(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4841 PRINTER_INFO_2 *printer=NULL;
4842 WERROR result = WERR_OK;
4844 if((printer=SMB_MALLOC_P(PRINTER_INFO_2))==NULL)
4845 return WERR_NOMEM;
4847 construct_printer_info_2(print_hnd, printer, snum);
4849 /* check the required size. */
4850 *needed += spoolss_size_printer_info_2(printer);
4852 if (*needed > offered) {
4853 result = WERR_INSUFFICIENT_BUFFER;
4854 goto out;
4857 if (!rpcbuf_alloc_size(buffer, *needed)) {
4858 result = WERR_NOMEM;
4859 goto out;
4862 /* fill the buffer with the structures */
4863 if (!smb_io_printer_info_2("", buffer, printer, 0))
4864 result = WERR_NOMEM;
4866 out:
4867 /* clear memory */
4868 free_printer_info_2(printer);
4870 return result;
4873 /****************************************************************************
4874 ****************************************************************************/
4876 static WERROR getprinter_level_3(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4878 PRINTER_INFO_3 *printer=NULL;
4879 WERROR result = WERR_OK;
4881 if (!construct_printer_info_3(print_hnd, &printer, snum))
4882 return WERR_NOMEM;
4884 /* check the required size. */
4885 *needed += spoolss_size_printer_info_3(printer);
4887 if (*needed > offered) {
4888 result = WERR_INSUFFICIENT_BUFFER;
4889 goto out;
4892 if (!rpcbuf_alloc_size(buffer, *needed)) {
4893 result = WERR_NOMEM;
4894 goto out;
4897 /* fill the buffer with the structures */
4898 smb_io_printer_info_3("", buffer, printer, 0);
4900 out:
4901 /* clear memory */
4902 free_printer_info_3(printer);
4904 return result;
4907 /****************************************************************************
4908 ****************************************************************************/
4910 static WERROR getprinter_level_4(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4912 PRINTER_INFO_4 *printer=NULL;
4913 WERROR result = WERR_OK;
4915 if((printer=SMB_MALLOC_P(PRINTER_INFO_4))==NULL)
4916 return WERR_NOMEM;
4918 if (!construct_printer_info_4(print_hnd, printer, snum)) {
4919 SAFE_FREE(printer);
4920 return WERR_NOMEM;
4923 /* check the required size. */
4924 *needed += spoolss_size_printer_info_4(printer);
4926 if (*needed > offered) {
4927 result = WERR_INSUFFICIENT_BUFFER;
4928 goto out;
4931 if (!rpcbuf_alloc_size(buffer, *needed)) {
4932 result = WERR_NOMEM;
4933 goto out;
4936 /* fill the buffer with the structures */
4937 smb_io_printer_info_4("", buffer, printer, 0);
4939 out:
4940 /* clear memory */
4941 free_printer_info_4(printer);
4943 return result;
4946 /****************************************************************************
4947 ****************************************************************************/
4949 static WERROR getprinter_level_5(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
4951 PRINTER_INFO_5 *printer=NULL;
4952 WERROR result = WERR_OK;
4954 if((printer=SMB_MALLOC_P(PRINTER_INFO_5))==NULL)
4955 return WERR_NOMEM;
4957 if (!construct_printer_info_5(print_hnd, printer, snum)) {
4958 free_printer_info_5(printer);
4959 return WERR_NOMEM;
4962 /* check the required size. */
4963 *needed += spoolss_size_printer_info_5(printer);
4965 if (*needed > offered) {
4966 result = WERR_INSUFFICIENT_BUFFER;
4967 goto out;
4970 if (!rpcbuf_alloc_size(buffer, *needed)) {
4971 result = WERR_NOMEM;
4972 goto out;
4975 /* fill the buffer with the structures */
4976 smb_io_printer_info_5("", buffer, printer, 0);
4978 out:
4979 /* clear memory */
4980 free_printer_info_5(printer);
4982 return result;
4985 static WERROR getprinter_level_6(Printer_entry *print_hnd,
4986 int snum,
4987 RPC_BUFFER *buffer, uint32 offered,
4988 uint32 *needed)
4990 PRINTER_INFO_6 *printer;
4991 WERROR result = WERR_OK;
4993 if ((printer = SMB_MALLOC_P(PRINTER_INFO_6)) == NULL) {
4994 return WERR_NOMEM;
4997 if (!construct_printer_info_6(print_hnd, printer, snum)) {
4998 free_printer_info_6(printer);
4999 return WERR_NOMEM;
5002 /* check the required size. */
5003 *needed += spoolss_size_printer_info_6(printer);
5005 if (*needed > offered) {
5006 result = WERR_INSUFFICIENT_BUFFER;
5007 goto out;
5010 if (!rpcbuf_alloc_size(buffer, *needed)) {
5011 result = WERR_NOMEM;
5012 goto out;
5015 /* fill the buffer with the structures */
5016 smb_io_printer_info_6("", buffer, printer, 0);
5018 out:
5019 /* clear memory */
5020 free_printer_info_6(printer);
5022 return result;
5025 static WERROR getprinter_level_7(Printer_entry *print_hnd, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5027 PRINTER_INFO_7 *printer=NULL;
5028 WERROR result = WERR_OK;
5030 if((printer=SMB_MALLOC_P(PRINTER_INFO_7))==NULL)
5031 return WERR_NOMEM;
5033 if (!construct_printer_info_7(print_hnd, printer, snum))
5034 return WERR_NOMEM;
5036 /* check the required size. */
5037 *needed += spoolss_size_printer_info_7(printer);
5039 if (*needed > offered) {
5040 result = WERR_INSUFFICIENT_BUFFER;
5041 goto out;
5044 if (!rpcbuf_alloc_size(buffer, *needed)) {
5045 result = WERR_NOMEM;
5046 goto out;
5050 /* fill the buffer with the structures */
5051 smb_io_printer_info_7("", buffer, printer, 0);
5053 out:
5054 /* clear memory */
5055 free_printer_info_7(printer);
5057 return result;
5060 /****************************************************************************
5061 ****************************************************************************/
5063 WERROR _spoolss_getprinter(pipes_struct *p, SPOOL_Q_GETPRINTER *q_u, SPOOL_R_GETPRINTER *r_u)
5065 POLICY_HND *handle = &q_u->handle;
5066 uint32 level = q_u->level;
5067 RPC_BUFFER *buffer = NULL;
5068 uint32 offered = q_u->offered;
5069 uint32 *needed = &r_u->needed;
5070 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
5072 int snum;
5074 /* that's an [in out] buffer */
5076 if (!q_u->buffer && (offered!=0)) {
5077 return WERR_INVALID_PARAM;
5080 rpcbuf_move(q_u->buffer, &r_u->buffer);
5081 buffer = r_u->buffer;
5083 *needed=0;
5085 if (!get_printer_snum(p, handle, &snum, NULL))
5086 return WERR_BADFID;
5088 switch (level) {
5089 case 0:
5090 return getprinter_level_0(Printer, snum, buffer, offered, needed);
5091 case 1:
5092 return getprinter_level_1(Printer, snum, buffer, offered, needed);
5093 case 2:
5094 return getprinter_level_2(Printer, snum, buffer, offered, needed);
5095 case 3:
5096 return getprinter_level_3(Printer, snum, buffer, offered, needed);
5097 case 4:
5098 return getprinter_level_4(Printer, snum, buffer, offered, needed);
5099 case 5:
5100 return getprinter_level_5(Printer, snum, buffer, offered, needed);
5101 case 6:
5102 return getprinter_level_6(Printer, snum, buffer, offered, needed);
5103 case 7:
5104 return getprinter_level_7(Printer, snum, buffer, offered, needed);
5106 return WERR_UNKNOWN_LEVEL;
5109 /********************************************************************
5110 * fill a DRIVER_INFO_1 struct
5111 ********************************************************************/
5113 static void fill_printer_driver_info_1(DRIVER_INFO_1 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername, fstring architecture)
5115 init_unistr( &info->name, driver.info_3->name);
5118 /********************************************************************
5119 * construct_printer_driver_info_1
5120 ********************************************************************/
5122 static WERROR construct_printer_driver_info_1(DRIVER_INFO_1 *info, int snum, fstring servername, fstring architecture, uint32 version)
5124 NT_PRINTER_INFO_LEVEL *printer = NULL;
5125 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5127 ZERO_STRUCT(driver);
5129 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5130 return WERR_INVALID_PRINTER_NAME;
5132 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5133 free_a_printer(&printer, 2);
5134 return WERR_UNKNOWN_PRINTER_DRIVER;
5137 fill_printer_driver_info_1(info, driver, servername, architecture);
5139 free_a_printer(&printer,2);
5141 return WERR_OK;
5144 /********************************************************************
5145 * construct_printer_driver_info_2
5146 * fill a printer_info_2 struct
5147 ********************************************************************/
5149 static void fill_printer_driver_info_2(DRIVER_INFO_2 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5151 TALLOC_CTX *ctx = talloc_tos();
5152 char *temp = NULL;
5154 info->version=driver.info_3->cversion;
5156 init_unistr( &info->name, driver.info_3->name );
5157 init_unistr( &info->architecture, driver.info_3->environment );
5160 if (strlen(driver.info_3->driverpath)) {
5161 temp = talloc_asprintf(ctx,
5162 "\\\\%s%s",
5163 servername,
5164 driver.info_3->driverpath);
5165 init_unistr( &info->driverpath, temp );
5166 } else {
5167 init_unistr( &info->driverpath, "" );
5170 TALLOC_FREE(temp);
5171 if (strlen(driver.info_3->datafile)) {
5172 temp = talloc_asprintf(ctx,
5173 "\\\\%s%s",
5174 servername,
5175 driver.info_3->datafile);
5176 init_unistr( &info->datafile, temp );
5177 } else
5178 init_unistr( &info->datafile, "" );
5180 TALLOC_FREE(temp);
5181 if (strlen(driver.info_3->configfile)) {
5182 temp = talloc_asprintf(ctx,
5183 "\\\\%s%s",
5184 servername,
5185 driver.info_3->configfile);
5186 init_unistr( &info->configfile, temp );
5187 } else
5188 init_unistr( &info->configfile, "" );
5191 /********************************************************************
5192 * construct_printer_driver_info_2
5193 * fill a printer_info_2 struct
5194 ********************************************************************/
5196 static WERROR construct_printer_driver_info_2(DRIVER_INFO_2 *info, int snum, fstring servername, fstring architecture, uint32 version)
5198 NT_PRINTER_INFO_LEVEL *printer = NULL;
5199 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5201 ZERO_STRUCT(printer);
5202 ZERO_STRUCT(driver);
5204 if (!W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_const_servicename(snum))))
5205 return WERR_INVALID_PRINTER_NAME;
5207 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version))) {
5208 free_a_printer(&printer, 2);
5209 return WERR_UNKNOWN_PRINTER_DRIVER;
5212 fill_printer_driver_info_2(info, driver, servername);
5214 free_a_printer(&printer,2);
5216 return WERR_OK;
5219 /********************************************************************
5220 * copy a strings array and convert to UNICODE
5222 * convert an array of ascii string to a UNICODE string
5223 ********************************************************************/
5225 static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, const char *servername)
5227 int i=0;
5228 int j=0;
5229 const char *v;
5230 char *line = NULL;
5231 TALLOC_CTX *ctx = talloc_tos();
5233 DEBUG(6,("init_unistr_array\n"));
5234 *uni_array=NULL;
5236 while (true) {
5237 if ( !char_array ) {
5238 v = "";
5239 } else {
5240 v = char_array[i];
5241 if (!v)
5242 v = ""; /* hack to handle null lists */
5245 /* hack to allow this to be used in places other than when generating
5246 the list of dependent files */
5248 TALLOC_FREE(line);
5249 if ( servername ) {
5250 line = talloc_asprintf(ctx,
5251 "\\\\%s%s",
5252 servername,
5254 } else {
5255 line = talloc_strdup(ctx, v);
5258 if (!line) {
5259 SAFE_FREE(*uni_array);
5260 return 0;
5262 DEBUGADD(6,("%d:%s:%lu\n", i, line, (unsigned long)strlen(line)));
5264 /* add one extra unit16 for the second terminating NULL */
5266 if ( (*uni_array=SMB_REALLOC_ARRAY(*uni_array, uint16, j+1+strlen(line)+2)) == NULL ) {
5267 DEBUG(2,("init_unistr_array: Realloc error\n" ));
5268 return 0;
5271 if ( !strlen(v) )
5272 break;
5274 j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
5275 i++;
5278 if (*uni_array) {
5279 /* special case for ""; we need to add both NULL's here */
5280 if (!j)
5281 (*uni_array)[j++]=0x0000;
5282 (*uni_array)[j]=0x0000;
5285 DEBUGADD(6,("last one:done\n"));
5287 /* return size of array in uint16's */
5289 return j+1;
5292 /********************************************************************
5293 * construct_printer_info_3
5294 * fill a printer_info_3 struct
5295 ********************************************************************/
5297 static void fill_printer_driver_info_3(DRIVER_INFO_3 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5299 char *temp = NULL;
5300 TALLOC_CTX *ctx = talloc_tos();
5302 ZERO_STRUCTP(info);
5304 info->version=driver.info_3->cversion;
5306 init_unistr( &info->name, driver.info_3->name );
5307 init_unistr( &info->architecture, driver.info_3->environment );
5309 if (strlen(driver.info_3->driverpath)) {
5310 temp = talloc_asprintf(ctx,
5311 "\\\\%s%s",
5312 servername,
5313 driver.info_3->driverpath);
5314 init_unistr( &info->driverpath, temp );
5315 } else
5316 init_unistr( &info->driverpath, "" );
5318 TALLOC_FREE(temp);
5319 if (strlen(driver.info_3->datafile)) {
5320 temp = talloc_asprintf(ctx,
5321 "\\\\%s%s",
5322 servername,
5323 driver.info_3->datafile);
5324 init_unistr( &info->datafile, temp );
5325 } else
5326 init_unistr( &info->datafile, "" );
5328 TALLOC_FREE(temp);
5329 if (strlen(driver.info_3->configfile)) {
5330 temp = talloc_asprintf(ctx,
5331 "\\\\%s%s",
5332 servername,
5333 driver.info_3->configfile);
5334 init_unistr( &info->configfile, temp );
5335 } else
5336 init_unistr( &info->configfile, "" );
5338 TALLOC_FREE(temp);
5339 if (strlen(driver.info_3->helpfile)) {
5340 temp = talloc_asprintf(ctx,
5341 "\\\\%s%s",
5342 servername,
5343 driver.info_3->helpfile);
5344 init_unistr( &info->helpfile, temp );
5345 } else
5346 init_unistr( &info->helpfile, "" );
5348 TALLOC_FREE(temp);
5349 init_unistr( &info->monitorname, driver.info_3->monitorname );
5350 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5352 info->dependentfiles=NULL;
5353 init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
5356 /********************************************************************
5357 * construct_printer_info_3
5358 * fill a printer_info_3 struct
5359 ********************************************************************/
5361 static WERROR construct_printer_driver_info_3(DRIVER_INFO_3 *info, int snum, fstring servername, fstring architecture, uint32 version)
5363 NT_PRINTER_INFO_LEVEL *printer = NULL;
5364 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5365 WERROR status;
5366 ZERO_STRUCT(driver);
5368 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5369 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5370 if (!W_ERROR_IS_OK(status))
5371 return WERR_INVALID_PRINTER_NAME;
5373 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5374 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5376 #if 0 /* JERRY */
5379 * I put this code in during testing. Helpful when commenting out the
5380 * support for DRIVER_INFO_6 in regards to win2k. Not needed in general
5381 * as win2k always queries the driver using an infor level of 6.
5382 * I've left it in (but ifdef'd out) because I'll probably
5383 * use it in experimentation again in the future. --jerry 22/01/2002
5386 if (!W_ERROR_IS_OK(status)) {
5388 * Is this a W2k client ?
5390 if (version == 3) {
5391 /* Yes - try again with a WinNT driver. */
5392 version = 2;
5393 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5394 DEBUG(8,("construct_printer_driver_info_3: status: %s\n", dos_errstr(status)));
5396 #endif
5398 if (!W_ERROR_IS_OK(status)) {
5399 free_a_printer(&printer,2);
5400 return WERR_UNKNOWN_PRINTER_DRIVER;
5403 #if 0 /* JERRY */
5405 #endif
5408 fill_printer_driver_info_3(info, driver, servername);
5410 free_a_printer(&printer,2);
5412 return WERR_OK;
5415 /********************************************************************
5416 * construct_printer_info_6
5417 * fill a printer_info_6 struct - we know that driver is really level 3. This sucks. JRA.
5418 ********************************************************************/
5420 static void fill_printer_driver_info_6(DRIVER_INFO_6 *info, NT_PRINTER_DRIVER_INFO_LEVEL driver, fstring servername)
5422 char *temp = NULL;
5423 fstring nullstr;
5424 TALLOC_CTX *ctx = talloc_tos();
5426 ZERO_STRUCTP(info);
5427 memset(&nullstr, '\0', sizeof(fstring));
5429 info->version=driver.info_3->cversion;
5431 init_unistr( &info->name, driver.info_3->name );
5432 init_unistr( &info->architecture, driver.info_3->environment );
5434 if (strlen(driver.info_3->driverpath)) {
5435 temp = talloc_asprintf(ctx,
5436 "\\\\%s%s",
5437 servername,
5438 driver.info_3->driverpath);
5439 init_unistr( &info->driverpath, temp );
5440 } else
5441 init_unistr( &info->driverpath, "" );
5443 TALLOC_FREE(temp);
5444 if (strlen(driver.info_3->datafile)) {
5445 temp = talloc_asprintf(ctx,
5446 "\\\\%s%s",
5447 servername,
5448 driver.info_3->datafile);
5449 init_unistr( &info->datafile, temp );
5450 } else
5451 init_unistr( &info->datafile, "" );
5453 TALLOC_FREE(temp);
5454 if (strlen(driver.info_3->configfile)) {
5455 temp = talloc_asprintf(ctx,
5456 "\\\\%s%s",
5457 servername,
5458 driver.info_3->configfile);
5459 init_unistr( &info->configfile, temp );
5460 } else
5461 init_unistr( &info->configfile, "" );
5463 TALLOC_FREE(temp);
5464 if (strlen(driver.info_3->helpfile)) {
5465 temp = talloc_asprintf(ctx,
5466 "\\\\%s%s",
5467 servername,
5468 driver.info_3->helpfile);
5469 init_unistr( &info->helpfile, temp );
5470 } else
5471 init_unistr( &info->helpfile, "" );
5473 TALLOC_FREE(temp);
5474 init_unistr( &info->monitorname, driver.info_3->monitorname );
5475 init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
5477 info->dependentfiles = NULL;
5478 init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
5480 info->previousdrivernames=NULL;
5481 init_unistr_array(&info->previousdrivernames, &nullstr, servername);
5483 info->driver_date=0;
5485 info->padding=0;
5486 info->driver_version_low=0;
5487 info->driver_version_high=0;
5489 init_unistr( &info->mfgname, "");
5490 init_unistr( &info->oem_url, "");
5491 init_unistr( &info->hardware_id, "");
5492 init_unistr( &info->provider, "");
5495 /********************************************************************
5496 * construct_printer_info_6
5497 * fill a printer_info_6 struct
5498 ********************************************************************/
5500 static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
5501 fstring servername, fstring architecture, uint32 version)
5503 NT_PRINTER_INFO_LEVEL *printer = NULL;
5504 NT_PRINTER_DRIVER_INFO_LEVEL driver;
5505 WERROR status;
5507 ZERO_STRUCT(driver);
5509 status=get_a_printer(NULL, &printer, 2, lp_const_servicename(snum) );
5511 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5513 if (!W_ERROR_IS_OK(status))
5514 return WERR_INVALID_PRINTER_NAME;
5516 status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5518 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5520 if (!W_ERROR_IS_OK(status))
5523 * Is this a W2k client ?
5526 if (version < 3) {
5527 free_a_printer(&printer,2);
5528 return WERR_UNKNOWN_PRINTER_DRIVER;
5531 /* Yes - try again with a WinNT driver. */
5532 version = 2;
5533 status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
5534 DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
5535 if (!W_ERROR_IS_OK(status)) {
5536 free_a_printer(&printer,2);
5537 return WERR_UNKNOWN_PRINTER_DRIVER;
5541 fill_printer_driver_info_6(info, driver, servername);
5543 free_a_printer(&printer,2);
5544 free_a_printer_driver(driver, 3);
5546 return WERR_OK;
5549 /****************************************************************************
5550 ****************************************************************************/
5552 static void free_printer_driver_info_3(DRIVER_INFO_3 *info)
5554 SAFE_FREE(info->dependentfiles);
5557 /****************************************************************************
5558 ****************************************************************************/
5560 static void free_printer_driver_info_6(DRIVER_INFO_6 *info)
5562 SAFE_FREE(info->dependentfiles);
5565 /****************************************************************************
5566 ****************************************************************************/
5568 static WERROR getprinterdriver2_level1(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5570 DRIVER_INFO_1 *info=NULL;
5571 WERROR result;
5573 if((info=SMB_MALLOC_P(DRIVER_INFO_1)) == NULL)
5574 return WERR_NOMEM;
5576 result = construct_printer_driver_info_1(info, snum, servername, architecture, version);
5577 if (!W_ERROR_IS_OK(result))
5578 goto out;
5580 /* check the required size. */
5581 *needed += spoolss_size_printer_driver_info_1(info);
5583 if (*needed > offered) {
5584 result = WERR_INSUFFICIENT_BUFFER;
5585 goto out;
5588 if (!rpcbuf_alloc_size(buffer, *needed)) {
5589 result = WERR_NOMEM;
5590 goto out;
5593 /* fill the buffer with the structures */
5594 smb_io_printer_driver_info_1("", buffer, info, 0);
5596 out:
5597 /* clear memory */
5598 SAFE_FREE(info);
5600 return result;
5603 /****************************************************************************
5604 ****************************************************************************/
5606 static WERROR getprinterdriver2_level2(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5608 DRIVER_INFO_2 *info=NULL;
5609 WERROR result;
5611 if((info=SMB_MALLOC_P(DRIVER_INFO_2)) == NULL)
5612 return WERR_NOMEM;
5614 result = construct_printer_driver_info_2(info, snum, servername, architecture, version);
5615 if (!W_ERROR_IS_OK(result))
5616 goto out;
5618 /* check the required size. */
5619 *needed += spoolss_size_printer_driver_info_2(info);
5621 if (*needed > offered) {
5622 result = WERR_INSUFFICIENT_BUFFER;
5623 goto out;
5626 if (!rpcbuf_alloc_size(buffer, *needed)) {
5627 result = WERR_NOMEM;
5628 goto out;
5631 /* fill the buffer with the structures */
5632 smb_io_printer_driver_info_2("", buffer, info, 0);
5634 out:
5635 /* clear memory */
5636 SAFE_FREE(info);
5638 return result;
5641 /****************************************************************************
5642 ****************************************************************************/
5644 static WERROR getprinterdriver2_level3(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5646 DRIVER_INFO_3 info;
5647 WERROR result;
5649 ZERO_STRUCT(info);
5651 result = construct_printer_driver_info_3(&info, snum, servername, architecture, version);
5652 if (!W_ERROR_IS_OK(result))
5653 goto out;
5655 /* check the required size. */
5656 *needed += spoolss_size_printer_driver_info_3(&info);
5658 if (*needed > offered) {
5659 result = WERR_INSUFFICIENT_BUFFER;
5660 goto out;
5663 if (!rpcbuf_alloc_size(buffer, *needed)) {
5664 result = WERR_NOMEM;
5665 goto out;
5668 /* fill the buffer with the structures */
5669 smb_io_printer_driver_info_3("", buffer, &info, 0);
5671 out:
5672 free_printer_driver_info_3(&info);
5674 return result;
5677 /****************************************************************************
5678 ****************************************************************************/
5680 static WERROR getprinterdriver2_level6(fstring servername, fstring architecture, uint32 version, int snum, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
5682 DRIVER_INFO_6 info;
5683 WERROR result;
5685 ZERO_STRUCT(info);
5687 result = construct_printer_driver_info_6(&info, snum, servername, architecture, version);
5688 if (!W_ERROR_IS_OK(result))
5689 goto out;
5691 /* check the required size. */
5692 *needed += spoolss_size_printer_driver_info_6(&info);
5694 if (*needed > offered) {
5695 result = WERR_INSUFFICIENT_BUFFER;
5696 goto out;
5699 if (!rpcbuf_alloc_size(buffer, *needed)) {
5700 result = WERR_NOMEM;
5701 goto out;
5704 /* fill the buffer with the structures */
5705 smb_io_printer_driver_info_6("", buffer, &info, 0);
5707 out:
5708 free_printer_driver_info_6(&info);
5710 return result;
5713 /****************************************************************************
5714 ****************************************************************************/
5716 WERROR _spoolss_getprinterdriver2(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVER2 *q_u, SPOOL_R_GETPRINTERDRIVER2 *r_u)
5718 POLICY_HND *handle = &q_u->handle;
5719 UNISTR2 *uni_arch = &q_u->architecture;
5720 uint32 level = q_u->level;
5721 uint32 clientmajorversion = q_u->clientmajorversion;
5722 RPC_BUFFER *buffer = NULL;
5723 uint32 offered = q_u->offered;
5724 uint32 *needed = &r_u->needed;
5725 uint32 *servermajorversion = &r_u->servermajorversion;
5726 uint32 *serverminorversion = &r_u->serverminorversion;
5727 Printer_entry *printer;
5729 fstring servername;
5730 fstring architecture;
5731 int snum;
5733 /* that's an [in out] buffer */
5735 if (!q_u->buffer && (offered!=0)) {
5736 return WERR_INVALID_PARAM;
5739 rpcbuf_move(q_u->buffer, &r_u->buffer);
5740 buffer = r_u->buffer;
5742 DEBUG(4,("_spoolss_getprinterdriver2\n"));
5744 if ( !(printer = find_printer_index_by_hnd( p, handle )) ) {
5745 DEBUG(0,("_spoolss_getprinterdriver2: invalid printer handle!\n"));
5746 return WERR_INVALID_PRINTER_NAME;
5749 *needed = 0;
5750 *servermajorversion = 0;
5751 *serverminorversion = 0;
5753 fstrcpy(servername, get_server_name( printer ));
5754 unistr2_to_ascii(architecture, uni_arch, sizeof(architecture));
5756 if (!get_printer_snum(p, handle, &snum, NULL))
5757 return WERR_BADFID;
5759 switch (level) {
5760 case 1:
5761 return getprinterdriver2_level1(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5762 case 2:
5763 return getprinterdriver2_level2(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5764 case 3:
5765 return getprinterdriver2_level3(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5766 case 6:
5767 return getprinterdriver2_level6(servername, architecture, clientmajorversion, snum, buffer, offered, needed);
5768 #if 0 /* JERRY */
5769 case 101:
5770 /* apparently this call is the equivalent of
5771 EnumPrinterDataEx() for the DsDriver key */
5772 break;
5773 #endif
5776 return WERR_UNKNOWN_LEVEL;
5779 /****************************************************************************
5780 ****************************************************************************/
5782 WERROR _spoolss_startpageprinter(pipes_struct *p, SPOOL_Q_STARTPAGEPRINTER *q_u, SPOOL_R_STARTPAGEPRINTER *r_u)
5784 POLICY_HND *handle = &q_u->handle;
5786 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5788 if (!Printer) {
5789 DEBUG(3,("Error in startpageprinter printer handle\n"));
5790 return WERR_BADFID;
5793 Printer->page_started=True;
5794 return WERR_OK;
5797 /****************************************************************************
5798 ****************************************************************************/
5800 WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
5802 POLICY_HND *handle = &q_u->handle;
5803 int snum;
5805 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5807 if (!Printer) {
5808 DEBUG(2,("_spoolss_endpageprinter: Invalid handle (%s:%u:%u).\n",OUR_HANDLE(handle)));
5809 return WERR_BADFID;
5812 if (!get_printer_snum(p, handle, &snum, NULL))
5813 return WERR_BADFID;
5815 Printer->page_started=False;
5816 print_job_endpage(snum, Printer->jobid);
5818 return WERR_OK;
5821 /********************************************************************
5822 * api_spoolss_getprinter
5823 * called from the spoolss dispatcher
5825 ********************************************************************/
5827 WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
5829 POLICY_HND *handle = &q_u->handle;
5830 DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
5831 uint32 *jobid = &r_u->jobid;
5832 TALLOC_CTX *ctx = p->mem_ctx;
5833 DOC_INFO_1 *info_1 = &docinfo->doc_info_1;
5834 int snum;
5835 char *jobname = NULL;
5836 fstring datatype;
5837 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5839 if (!Printer) {
5840 DEBUG(2,("_spoolss_startdocprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5841 return WERR_BADFID;
5845 * a nice thing with NT is it doesn't listen to what you tell it.
5846 * when asked to send _only_ RAW datas, it tries to send datas
5847 * in EMF format.
5849 * So I add checks like in NT Server ...
5852 if (info_1->p_datatype != 0) {
5853 unistr2_to_ascii(datatype, &info_1->datatype, sizeof(datatype));
5854 if (strcmp(datatype, "RAW") != 0) {
5855 (*jobid)=0;
5856 return WERR_INVALID_DATATYPE;
5860 /* get the share number of the printer */
5861 if (!get_printer_snum(p, handle, &snum, NULL)) {
5862 return WERR_BADFID;
5865 jobname = unistr2_to_ascii_talloc(ctx, &info_1->docname);
5867 Printer->jobid = print_job_start(&p->pipe_user, snum, jobname, Printer->nt_devmode);
5869 /* An error occured in print_job_start() so return an appropriate
5870 NT error code. */
5872 if (Printer->jobid == -1) {
5873 return map_werror_from_unix(errno);
5876 Printer->document_started=True;
5877 (*jobid) = Printer->jobid;
5879 return WERR_OK;
5882 /********************************************************************
5883 * api_spoolss_getprinter
5884 * called from the spoolss dispatcher
5886 ********************************************************************/
5888 WERROR _spoolss_enddocprinter(pipes_struct *p, SPOOL_Q_ENDDOCPRINTER *q_u, SPOOL_R_ENDDOCPRINTER *r_u)
5890 POLICY_HND *handle = &q_u->handle;
5892 return _spoolss_enddocprinter_internal(p, handle);
5895 /****************************************************************************
5896 ****************************************************************************/
5898 WERROR _spoolss_writeprinter(pipes_struct *p, SPOOL_Q_WRITEPRINTER *q_u, SPOOL_R_WRITEPRINTER *r_u)
5900 POLICY_HND *handle = &q_u->handle;
5901 uint32 buffer_size = q_u->buffer_size;
5902 uint8 *buffer = q_u->buffer;
5903 uint32 *buffer_written = &q_u->buffer_size2;
5904 int snum;
5905 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5907 if (!Printer) {
5908 DEBUG(2,("_spoolss_writeprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5909 r_u->buffer_written = q_u->buffer_size2;
5910 return WERR_BADFID;
5913 if (!get_printer_snum(p, handle, &snum, NULL))
5914 return WERR_BADFID;
5916 (*buffer_written) = (uint32)print_job_write(snum, Printer->jobid, (const char *)buffer,
5917 (SMB_OFF_T)-1, (size_t)buffer_size);
5918 if (*buffer_written == (uint32)-1) {
5919 r_u->buffer_written = 0;
5920 if (errno == ENOSPC)
5921 return WERR_NO_SPOOL_SPACE;
5922 else
5923 return WERR_ACCESS_DENIED;
5926 r_u->buffer_written = q_u->buffer_size2;
5928 return WERR_OK;
5931 /********************************************************************
5932 * api_spoolss_getprinter
5933 * called from the spoolss dispatcher
5935 ********************************************************************/
5937 static WERROR control_printer(POLICY_HND *handle, uint32 command,
5938 pipes_struct *p)
5940 int snum;
5941 WERROR errcode = WERR_BADFUNC;
5942 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5944 if (!Printer) {
5945 DEBUG(2,("control_printer: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
5946 return WERR_BADFID;
5949 if (!get_printer_snum(p, handle, &snum, NULL))
5950 return WERR_BADFID;
5952 switch (command) {
5953 case PRINTER_CONTROL_PAUSE:
5954 if (print_queue_pause(&p->pipe_user, snum, &errcode)) {
5955 errcode = WERR_OK;
5957 break;
5958 case PRINTER_CONTROL_RESUME:
5959 case PRINTER_CONTROL_UNPAUSE:
5960 if (print_queue_resume(&p->pipe_user, snum, &errcode)) {
5961 errcode = WERR_OK;
5963 break;
5964 case PRINTER_CONTROL_PURGE:
5965 if (print_queue_purge(&p->pipe_user, snum, &errcode)) {
5966 errcode = WERR_OK;
5968 break;
5969 default:
5970 return WERR_UNKNOWN_LEVEL;
5973 return errcode;
5976 /********************************************************************
5977 * api_spoolss_abortprinter
5978 * From MSDN: "Deletes printer's spool file if printer is configured
5979 * for spooling"
5980 ********************************************************************/
5982 WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
5984 POLICY_HND *handle = &q_u->handle;
5985 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
5986 int snum;
5987 WERROR errcode = WERR_OK;
5989 if (!Printer) {
5990 DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
5991 return WERR_BADFID;
5994 if (!get_printer_snum(p, handle, &snum, NULL))
5995 return WERR_BADFID;
5997 print_job_delete( &p->pipe_user, snum, Printer->jobid, &errcode );
5999 return errcode;
6002 /********************************************************************
6003 * called by spoolss_api_setprinter
6004 * when updating a printer description
6005 ********************************************************************/
6007 static WERROR update_printer_sec(POLICY_HND *handle, uint32 level,
6008 const SPOOL_PRINTER_INFO_LEVEL *info,
6009 pipes_struct *p, SEC_DESC_BUF *secdesc_ctr)
6011 SEC_DESC_BUF *new_secdesc_ctr = NULL, *old_secdesc_ctr = NULL;
6012 WERROR result;
6013 int snum;
6015 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6017 if (!Printer || !get_printer_snum(p, handle, &snum, NULL)) {
6018 DEBUG(2,("update_printer_sec: Invalid handle (%s:%u:%u)\n",
6019 OUR_HANDLE(handle)));
6021 result = WERR_BADFID;
6022 goto done;
6025 if (!secdesc_ctr) {
6026 DEBUG(10,("update_printer_sec: secdesc_ctr is NULL !\n"));
6027 result = WERR_INVALID_PARAM;
6028 goto done;
6031 /* Check the user has permissions to change the security
6032 descriptor. By experimentation with two NT machines, the user
6033 requires Full Access to the printer to change security
6034 information. */
6036 if ( Printer->access_granted != PRINTER_ACCESS_ADMINISTER ) {
6037 DEBUG(4,("update_printer_sec: updated denied by printer permissions\n"));
6038 result = WERR_ACCESS_DENIED;
6039 goto done;
6042 /* NT seems to like setting the security descriptor even though
6043 nothing may have actually changed. */
6045 if ( !nt_printing_getsec(p->mem_ctx, Printer->sharename, &old_secdesc_ctr)) {
6046 DEBUG(2,("update_printer_sec: nt_printing_getsec() failed\n"));
6047 result = WERR_BADFID;
6048 goto done;
6051 if (DEBUGLEVEL >= 10) {
6052 SEC_ACL *the_acl;
6053 int i;
6055 the_acl = old_secdesc_ctr->sd->dacl;
6056 DEBUG(10, ("old_secdesc_ctr for %s has %d aces:\n",
6057 PRINTERNAME(snum), the_acl->num_aces));
6059 for (i = 0; i < the_acl->num_aces; i++) {
6060 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6061 &the_acl->aces[i].trustee),
6062 the_acl->aces[i].access_mask));
6065 the_acl = secdesc_ctr->sd->dacl;
6067 if (the_acl) {
6068 DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
6069 PRINTERNAME(snum), the_acl->num_aces));
6071 for (i = 0; i < the_acl->num_aces; i++) {
6072 DEBUG(10, ("%s 0x%08x\n", sid_string_dbg(
6073 &the_acl->aces[i].trustee),
6074 the_acl->aces[i].access_mask));
6076 } else {
6077 DEBUG(10, ("dacl for secdesc_ctr is NULL\n"));
6081 new_secdesc_ctr = sec_desc_merge(p->mem_ctx, secdesc_ctr, old_secdesc_ctr);
6082 if (!new_secdesc_ctr) {
6083 result = WERR_NOMEM;
6084 goto done;
6087 if (sec_desc_equal(new_secdesc_ctr->sd, old_secdesc_ctr->sd)) {
6088 result = WERR_OK;
6089 goto done;
6092 result = nt_printing_setsec(Printer->sharename, new_secdesc_ctr);
6094 done:
6096 return result;
6099 /********************************************************************
6100 Canonicalize printer info from a client
6102 ATTN: It does not matter what we set the servername to hear
6103 since we do the necessary work in get_a_printer() to set it to
6104 the correct value based on what the client sent in the
6105 _spoolss_open_printer_ex().
6106 ********************************************************************/
6108 static bool check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum)
6110 fstring printername;
6111 const char *p;
6113 DEBUG(5,("check_printer_ok: servername=%s printername=%s sharename=%s "
6114 "portname=%s drivername=%s comment=%s location=%s\n",
6115 info->servername, info->printername, info->sharename,
6116 info->portname, info->drivername, info->comment, info->location));
6118 /* we force some elements to "correct" values */
6119 slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", global_myname());
6120 fstrcpy(info->sharename, lp_servicename(snum));
6122 /* check to see if we allow printername != sharename */
6124 if ( lp_force_printername(snum) ) {
6125 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6126 global_myname(), info->sharename );
6127 } else {
6129 /* make sure printername is in \\server\printername format */
6131 fstrcpy( printername, info->printername );
6132 p = printername;
6133 if ( printername[0] == '\\' && printername[1] == '\\' ) {
6134 if ( (p = strchr_m( &printername[2], '\\' )) != NULL )
6135 p++;
6138 slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
6139 global_myname(), p );
6142 info->attributes |= PRINTER_ATTRIBUTE_SAMBA;
6143 info->attributes &= ~PRINTER_ATTRIBUTE_NOT_SAMBA;
6147 return True;
6150 /****************************************************************************
6151 ****************************************************************************/
6153 WERROR add_port_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *portname, const char *uri )
6155 char *cmd = lp_addport_cmd();
6156 char *command = NULL;
6157 int ret;
6158 int fd;
6159 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6160 bool is_print_op = False;
6162 if ( !*cmd ) {
6163 return WERR_ACCESS_DENIED;
6166 command = talloc_asprintf(ctx,
6167 "%s \"%s\" \"%s\"", cmd, portname, uri );
6168 if (!command) {
6169 return WERR_NOMEM;
6172 if ( token )
6173 is_print_op = user_has_privileges( token, &se_printop );
6175 DEBUG(10,("Running [%s]\n", command));
6177 /********* BEGIN SePrintOperatorPrivilege **********/
6179 if ( is_print_op )
6180 become_root();
6182 ret = smbrun(command, &fd);
6184 if ( is_print_op )
6185 unbecome_root();
6187 /********* END SePrintOperatorPrivilege **********/
6189 DEBUGADD(10,("returned [%d]\n", ret));
6191 TALLOC_FREE(command);
6193 if ( ret != 0 ) {
6194 if (fd != -1)
6195 close(fd);
6196 return WERR_ACCESS_DENIED;
6199 return WERR_OK;
6202 /****************************************************************************
6203 ****************************************************************************/
6205 bool add_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
6207 char *cmd = lp_addprinter_cmd();
6208 char **qlines;
6209 char *command = NULL;
6210 int numlines;
6211 int ret;
6212 int fd;
6213 SE_PRIV se_printop = SE_PRINT_OPERATOR;
6214 bool is_print_op = False;
6215 char *remote_machine = talloc_strdup(ctx, "%m");
6217 if (!remote_machine) {
6218 return false;
6220 remote_machine = talloc_sub_basic(ctx,
6221 current_user_info.smb_name,
6222 current_user_info.domain,
6223 remote_machine);
6224 if (!remote_machine) {
6225 return false;
6228 command = talloc_asprintf(ctx,
6229 "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
6230 cmd, printer->info_2->printername, printer->info_2->sharename,
6231 printer->info_2->portname, printer->info_2->drivername,
6232 printer->info_2->location, printer->info_2->comment, remote_machine);
6233 if (!command) {
6234 return false;
6237 if ( token )
6238 is_print_op = user_has_privileges( token, &se_printop );
6240 DEBUG(10,("Running [%s]\n", command));
6242 /********* BEGIN SePrintOperatorPrivilege **********/
6244 if ( is_print_op )
6245 become_root();
6247 if ( (ret = smbrun(command, &fd)) == 0 ) {
6248 /* Tell everyone we updated smb.conf. */
6249 message_send_all(smbd_messaging_context(),
6250 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
6253 if ( is_print_op )
6254 unbecome_root();
6256 /********* END SePrintOperatorPrivilege **********/
6258 DEBUGADD(10,("returned [%d]\n", ret));
6260 TALLOC_FREE(command);
6261 TALLOC_FREE(remote_machine);
6263 if ( ret != 0 ) {
6264 if (fd != -1)
6265 close(fd);
6266 return False;
6269 /* reload our services immediately */
6270 reload_services( False );
6272 numlines = 0;
6273 /* Get lines and convert them back to dos-codepage */
6274 qlines = fd_lines_load(fd, &numlines, 0);
6275 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
6276 close(fd);
6278 /* Set the portname to what the script says the portname should be. */
6279 /* but don't require anything to be return from the script exit a good error code */
6281 if (numlines) {
6282 /* Set the portname to what the script says the portname should be. */
6283 strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
6284 DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
6287 file_lines_free(qlines);
6288 return True;
6292 /********************************************************************
6293 * Called by spoolss_api_setprinter
6294 * when updating a printer description.
6295 ********************************************************************/
6297 static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,
6298 const SPOOL_PRINTER_INFO_LEVEL *info,
6299 DEVICEMODE *devmode)
6301 int snum;
6302 NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
6303 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6304 WERROR result;
6305 UNISTR2 buffer;
6306 fstring asc_buffer;
6308 DEBUG(8,("update_printer\n"));
6310 result = WERR_OK;
6312 if (!Printer) {
6313 result = WERR_BADFID;
6314 goto done;
6317 if (!get_printer_snum(p, handle, &snum, NULL)) {
6318 result = WERR_BADFID;
6319 goto done;
6322 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))) ||
6323 (!W_ERROR_IS_OK(get_a_printer(Printer, &old_printer, 2, lp_const_servicename(snum))))) {
6324 result = WERR_BADFID;
6325 goto done;
6328 DEBUGADD(8,("Converting info_2 struct\n"));
6331 * convert_printer_info converts the incoming
6332 * info from the client and overwrites the info
6333 * just read from the tdb in the pointer 'printer'.
6336 if (!convert_printer_info(info, printer, level)) {
6337 result = WERR_NOMEM;
6338 goto done;
6341 if (devmode) {
6342 /* we have a valid devmode
6343 convert it and link it*/
6345 DEBUGADD(8,("update_printer: Converting the devicemode struct\n"));
6346 if (!convert_devicemode(printer->info_2->printername, devmode,
6347 &printer->info_2->devmode)) {
6348 result = WERR_NOMEM;
6349 goto done;
6353 /* Do sanity check on the requested changes for Samba */
6355 if (!check_printer_ok(printer->info_2, snum)) {
6356 result = WERR_INVALID_PARAM;
6357 goto done;
6360 /* FIXME!!! If the driver has changed we really should verify that
6361 it is installed before doing much else --jerry */
6363 /* Check calling user has permission to update printer description */
6365 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
6366 DEBUG(3, ("update_printer: printer property change denied by handle\n"));
6367 result = WERR_ACCESS_DENIED;
6368 goto done;
6371 /* Call addprinter hook */
6372 /* Check changes to see if this is really needed */
6374 if ( *lp_addprinter_cmd()
6375 && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
6376 || !strequal(printer->info_2->comment, old_printer->info_2->comment)
6377 || !strequal(printer->info_2->portname, old_printer->info_2->portname)
6378 || !strequal(printer->info_2->location, old_printer->info_2->location)) )
6380 /* add_printer_hook() will call reload_services() */
6382 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
6383 result = WERR_ACCESS_DENIED;
6384 goto done;
6389 * When a *new* driver is bound to a printer, the drivername is used to
6390 * lookup previously saved driver initialization info, which is then
6391 * bound to the printer, simulating what happens in the Windows arch.
6393 if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
6395 if (!set_driver_init(printer, 2))
6397 DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
6398 printer->info_2->drivername));
6401 DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
6402 printer->info_2->drivername));
6404 notify_printer_driver(snum, printer->info_2->drivername);
6408 * flag which changes actually occured. This is a small subset of
6409 * all the possible changes. We also have to update things in the
6410 * DsSpooler key.
6413 if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) {
6414 init_unistr2( &buffer, printer->info_2->comment, UNI_STR_TERMINATE);
6415 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "description",
6416 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6418 notify_printer_comment(snum, printer->info_2->comment);
6421 if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) {
6422 init_unistr2( &buffer, printer->info_2->sharename, UNI_STR_TERMINATE);
6423 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shareName",
6424 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6426 notify_printer_sharename(snum, printer->info_2->sharename);
6429 if (!strequal(printer->info_2->printername, old_printer->info_2->printername)) {
6430 char *pname;
6432 if ( (pname = strchr_m( printer->info_2->printername+2, '\\' )) != NULL )
6433 pname++;
6434 else
6435 pname = printer->info_2->printername;
6438 init_unistr2( &buffer, pname, UNI_STR_TERMINATE);
6439 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "printerName",
6440 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6442 notify_printer_printername( snum, pname );
6445 if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) {
6446 init_unistr2( &buffer, printer->info_2->portname, UNI_STR_TERMINATE);
6447 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "portName",
6448 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6450 notify_printer_port(snum, printer->info_2->portname);
6453 if (!strequal(printer->info_2->location, old_printer->info_2->location)) {
6454 init_unistr2( &buffer, printer->info_2->location, UNI_STR_TERMINATE);
6455 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "location",
6456 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6458 notify_printer_location(snum, printer->info_2->location);
6461 /* here we need to update some more DsSpooler keys */
6462 /* uNCName, serverName, shortServerName */
6464 init_unistr2( &buffer, global_myname(), UNI_STR_TERMINATE);
6465 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "serverName",
6466 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6467 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "shortServerName",
6468 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6470 slprintf( asc_buffer, sizeof(asc_buffer)-1, "\\\\%s\\%s",
6471 global_myname(), printer->info_2->sharename );
6472 init_unistr2( &buffer, asc_buffer, UNI_STR_TERMINATE);
6473 set_printer_dataex( printer, SPOOL_DSSPOOLER_KEY, "uNCName",
6474 REG_SZ, (uint8*)buffer.buffer, buffer.uni_str_len*2 );
6476 /* Update printer info */
6477 result = mod_a_printer(printer, 2);
6479 done:
6480 free_a_printer(&printer, 2);
6481 free_a_printer(&old_printer, 2);
6484 return result;
6487 /****************************************************************************
6488 ****************************************************************************/
6489 static WERROR publish_or_unpublish_printer(pipes_struct *p, POLICY_HND *handle,
6490 const SPOOL_PRINTER_INFO_LEVEL *info)
6492 #ifdef HAVE_ADS
6493 SPOOL_PRINTER_INFO_LEVEL_7 *info7 = info->info_7;
6494 int snum;
6495 Printer_entry *Printer;
6497 if ( lp_security() != SEC_ADS ) {
6498 return WERR_UNKNOWN_LEVEL;
6501 Printer = find_printer_index_by_hnd(p, handle);
6503 DEBUG(5,("publish_or_unpublish_printer, action = %d\n",info7->action));
6505 if (!Printer)
6506 return WERR_BADFID;
6508 if (!get_printer_snum(p, handle, &snum, NULL))
6509 return WERR_BADFID;
6511 nt_printer_publish(Printer, snum, info7->action);
6513 return WERR_OK;
6514 #else
6515 return WERR_UNKNOWN_LEVEL;
6516 #endif
6518 /****************************************************************************
6519 ****************************************************************************/
6521 WERROR _spoolss_setprinter(pipes_struct *p, SPOOL_Q_SETPRINTER *q_u, SPOOL_R_SETPRINTER *r_u)
6523 POLICY_HND *handle = &q_u->handle;
6524 uint32 level = q_u->level;
6525 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
6526 DEVMODE_CTR devmode_ctr = q_u->devmode_ctr;
6527 SEC_DESC_BUF *secdesc_ctr = q_u->secdesc_ctr;
6528 uint32 command = q_u->command;
6529 WERROR result;
6531 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
6533 if (!Printer) {
6534 DEBUG(2,("_spoolss_setprinter: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6535 return WERR_BADFID;
6538 /* check the level */
6539 switch (level) {
6540 case 0:
6541 return control_printer(handle, command, p);
6542 case 2:
6543 result = update_printer(p, handle, level, info, devmode_ctr.devmode);
6544 if (!W_ERROR_IS_OK(result))
6545 return result;
6546 if (secdesc_ctr)
6547 result = update_printer_sec(handle, level, info, p, secdesc_ctr);
6548 return result;
6549 case 3:
6550 return update_printer_sec(handle, level, info, p,
6551 secdesc_ctr);
6552 case 7:
6553 return publish_or_unpublish_printer(p, handle, info);
6554 default:
6555 return WERR_UNKNOWN_LEVEL;
6559 /****************************************************************************
6560 ****************************************************************************/
6562 WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
6564 POLICY_HND *handle = &q_u->handle;
6565 Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
6567 if (!Printer) {
6568 DEBUG(2,("_spoolss_fcpn: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
6569 return WERR_BADFID;
6572 if (Printer->notify.client_connected==True) {
6573 int snum = -1;
6575 if ( Printer->printer_type == SPLHND_SERVER)
6576 snum = -1;
6577 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
6578 !get_printer_snum(p, handle, &snum, NULL) )
6579 return WERR_BADFID;
6581 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
6584 Printer->notify.flags=0;
6585 Printer->notify.options=0;
6586 Printer->notify.localmachine[0]='\0';
6587 Printer->notify.printerlocal=0;
6588 if (Printer->notify.option)
6589 free_spool_notify_option(&Printer->notify.option);
6590 Printer->notify.client_connected=False;
6592 return WERR_OK;
6595 /****************************************************************************
6596 ****************************************************************************/
6598 WERROR _spoolss_addjob(pipes_struct *p, SPOOL_Q_ADDJOB *q_u, SPOOL_R_ADDJOB *r_u)
6600 /* that's an [in out] buffer */
6602 if (!q_u->buffer && (q_u->offered!=0)) {
6603 return WERR_INVALID_PARAM;
6606 rpcbuf_move(q_u->buffer, &r_u->buffer);
6608 r_u->needed = 0;
6609 return WERR_INVALID_PARAM; /* this is what a NT server
6610 returns for AddJob. AddJob
6611 must fail on non-local
6612 printers */
6615 /****************************************************************************
6616 ****************************************************************************/
6618 static void fill_job_info_1(JOB_INFO_1 *job_info, const print_queue_struct *queue,
6619 int position, int snum,
6620 const NT_PRINTER_INFO_LEVEL *ntprinter)
6622 struct tm *t;
6624 t=gmtime(&queue->time);
6626 job_info->jobid=queue->job;
6627 init_unistr(&job_info->printername, lp_servicename(snum));
6628 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6629 init_unistr(&job_info->username, queue->fs_user);
6630 init_unistr(&job_info->document, queue->fs_file);
6631 init_unistr(&job_info->datatype, "RAW");
6632 init_unistr(&job_info->text_status, "");
6633 job_info->status=nt_printj_status(queue->status);
6634 job_info->priority=queue->priority;
6635 job_info->position=position;
6636 job_info->totalpages=queue->page_count;
6637 job_info->pagesprinted=0;
6639 make_systemtime(&job_info->submitted, t);
6642 /****************************************************************************
6643 ****************************************************************************/
6645 static bool fill_job_info_2(JOB_INFO_2 *job_info, const print_queue_struct *queue,
6646 int position, int snum,
6647 const NT_PRINTER_INFO_LEVEL *ntprinter,
6648 DEVICEMODE *devmode)
6650 struct tm *t;
6652 t=gmtime(&queue->time);
6654 job_info->jobid=queue->job;
6656 init_unistr(&job_info->printername, ntprinter->info_2->printername);
6658 init_unistr(&job_info->machinename, ntprinter->info_2->servername);
6659 init_unistr(&job_info->username, queue->fs_user);
6660 init_unistr(&job_info->document, queue->fs_file);
6661 init_unistr(&job_info->notifyname, queue->fs_user);
6662 init_unistr(&job_info->datatype, "RAW");
6663 init_unistr(&job_info->printprocessor, "winprint");
6664 init_unistr(&job_info->parameters, "");
6665 init_unistr(&job_info->drivername, ntprinter->info_2->drivername);
6666 init_unistr(&job_info->text_status, "");
6668 /* and here the security descriptor */
6670 job_info->status=nt_printj_status(queue->status);
6671 job_info->priority=queue->priority;
6672 job_info->position=position;
6673 job_info->starttime=0;
6674 job_info->untiltime=0;
6675 job_info->totalpages=queue->page_count;
6676 job_info->size=queue->size;
6677 make_systemtime(&(job_info->submitted), t);
6678 job_info->timeelapsed=0;
6679 job_info->pagesprinted=0;
6681 job_info->devmode = devmode;
6683 return (True);
6686 /****************************************************************************
6687 Enumjobs at level 1.
6688 ****************************************************************************/
6690 static WERROR enumjobs_level1(const print_queue_struct *queue, int snum,
6691 const NT_PRINTER_INFO_LEVEL *ntprinter,
6692 RPC_BUFFER *buffer, uint32 offered,
6693 uint32 *needed, uint32 *returned)
6695 JOB_INFO_1 *info;
6696 int i;
6697 WERROR result = WERR_OK;
6699 info=SMB_MALLOC_ARRAY(JOB_INFO_1,*returned);
6700 if (info==NULL) {
6701 *returned=0;
6702 return WERR_NOMEM;
6705 for (i=0; i<*returned; i++)
6706 fill_job_info_1( &info[i], &queue[i], i, snum, ntprinter );
6708 /* check the required size. */
6709 for (i=0; i<*returned; i++)
6710 (*needed) += spoolss_size_job_info_1(&info[i]);
6712 if (*needed > offered) {
6713 result = WERR_INSUFFICIENT_BUFFER;
6714 goto out;
6717 if (!rpcbuf_alloc_size(buffer, *needed)) {
6718 result = WERR_NOMEM;
6719 goto out;
6722 /* fill the buffer with the structures */
6723 for (i=0; i<*returned; i++)
6724 smb_io_job_info_1("", buffer, &info[i], 0);
6726 out:
6727 /* clear memory */
6728 SAFE_FREE(info);
6730 if ( !W_ERROR_IS_OK(result) )
6731 *returned = 0;
6733 return result;
6736 /****************************************************************************
6737 Enumjobs at level 2.
6738 ****************************************************************************/
6740 static WERROR enumjobs_level2(const print_queue_struct *queue, int snum,
6741 const NT_PRINTER_INFO_LEVEL *ntprinter,
6742 RPC_BUFFER *buffer, uint32 offered,
6743 uint32 *needed, uint32 *returned)
6745 JOB_INFO_2 *info = NULL;
6746 int i;
6747 WERROR result = WERR_OK;
6748 DEVICEMODE *devmode = NULL;
6750 if ( !(info = SMB_MALLOC_ARRAY(JOB_INFO_2,*returned)) ) {
6751 *returned=0;
6752 return WERR_NOMEM;
6755 /* this should not be a failure condition if the devmode is NULL */
6757 devmode = construct_dev_mode(lp_const_servicename(snum));
6759 for (i=0; i<*returned; i++)
6760 fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter, devmode);
6762 /* check the required size. */
6763 for (i=0; i<*returned; i++)
6764 (*needed) += spoolss_size_job_info_2(&info[i]);
6766 if (*needed > offered) {
6767 result = WERR_INSUFFICIENT_BUFFER;
6768 goto out;
6771 if (!rpcbuf_alloc_size(buffer, *needed)) {
6772 result = WERR_NOMEM;
6773 goto out;
6776 /* fill the buffer with the structures */
6777 for (i=0; i<*returned; i++)
6778 smb_io_job_info_2("", buffer, &info[i], 0);
6780 out:
6781 free_devmode(devmode);
6782 SAFE_FREE(info);
6784 if ( !W_ERROR_IS_OK(result) )
6785 *returned = 0;
6787 return result;
6791 /****************************************************************************
6792 Enumjobs.
6793 ****************************************************************************/
6795 WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
6797 POLICY_HND *handle = &q_u->handle;
6798 uint32 level = q_u->level;
6799 RPC_BUFFER *buffer = NULL;
6800 uint32 offered = q_u->offered;
6801 uint32 *needed = &r_u->needed;
6802 uint32 *returned = &r_u->returned;
6803 WERROR wret;
6804 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
6805 int snum;
6806 print_status_struct prt_status;
6807 print_queue_struct *queue=NULL;
6809 /* that's an [in out] buffer */
6811 if (!q_u->buffer && (offered!=0)) {
6812 return WERR_INVALID_PARAM;
6815 rpcbuf_move(q_u->buffer, &r_u->buffer);
6816 buffer = r_u->buffer;
6818 DEBUG(4,("_spoolss_enumjobs\n"));
6820 *needed=0;
6821 *returned=0;
6823 /* lookup the printer snum and tdb entry */
6825 if (!get_printer_snum(p, handle, &snum, NULL))
6826 return WERR_BADFID;
6828 wret = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
6829 if ( !W_ERROR_IS_OK(wret) )
6830 return wret;
6832 *returned = print_queue_status(snum, &queue, &prt_status);
6833 DEBUGADD(4,("count:[%d], status:[%d], [%s]\n", *returned, prt_status.status, prt_status.message));
6835 if (*returned == 0) {
6836 SAFE_FREE(queue);
6837 free_a_printer(&ntprinter, 2);
6838 return WERR_OK;
6841 switch (level) {
6842 case 1:
6843 wret = enumjobs_level1(queue, snum, ntprinter, buffer, offered, needed, returned);
6844 break;
6845 case 2:
6846 wret = enumjobs_level2(queue, snum, ntprinter, buffer, offered, needed, returned);
6847 break;
6848 default:
6849 *returned=0;
6850 wret = WERR_UNKNOWN_LEVEL;
6851 break;
6854 SAFE_FREE(queue);
6855 free_a_printer( &ntprinter, 2 );
6856 return wret;
6859 /****************************************************************************
6860 ****************************************************************************/
6862 WERROR _spoolss_schedulejob( pipes_struct *p, SPOOL_Q_SCHEDULEJOB *q_u, SPOOL_R_SCHEDULEJOB *r_u)
6864 return WERR_OK;
6867 /****************************************************************************
6868 ****************************************************************************/
6870 WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u)
6872 POLICY_HND *handle = &q_u->handle;
6873 uint32 jobid = q_u->jobid;
6874 uint32 command = q_u->command;
6876 int snum;
6877 WERROR errcode = WERR_BADFUNC;
6879 if (!get_printer_snum(p, handle, &snum, NULL)) {
6880 return WERR_BADFID;
6883 if (!print_job_exists(lp_const_servicename(snum), jobid)) {
6884 return WERR_INVALID_PRINTER_NAME;
6887 switch (command) {
6888 case JOB_CONTROL_CANCEL:
6889 case JOB_CONTROL_DELETE:
6890 if (print_job_delete(&p->pipe_user, snum, jobid, &errcode)) {
6891 errcode = WERR_OK;
6893 break;
6894 case JOB_CONTROL_PAUSE:
6895 if (print_job_pause(&p->pipe_user, snum, jobid, &errcode)) {
6896 errcode = WERR_OK;
6898 break;
6899 case JOB_CONTROL_RESTART:
6900 case JOB_CONTROL_RESUME:
6901 if (print_job_resume(&p->pipe_user, snum, jobid, &errcode)) {
6902 errcode = WERR_OK;
6904 break;
6905 default:
6906 return WERR_UNKNOWN_LEVEL;
6909 return errcode;
6912 /****************************************************************************
6913 Enumerates all printer drivers at level 1.
6914 ****************************************************************************/
6916 static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
6918 int i;
6919 int ndrivers;
6920 uint32 version;
6921 fstring *list = NULL;
6922 NT_PRINTER_DRIVER_INFO_LEVEL driver;
6923 DRIVER_INFO_1 *driver_info_1=NULL;
6924 WERROR result = WERR_OK;
6926 *returned=0;
6928 for (version=0; version<DRIVER_MAX_VERSION; version++) {
6929 list=NULL;
6930 ndrivers=get_ntdrivers(&list, architecture, version);
6931 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
6933 if(ndrivers == -1) {
6934 SAFE_FREE(driver_info_1);
6935 return WERR_NOMEM;
6938 if(ndrivers != 0) {
6939 if((driver_info_1=SMB_REALLOC_ARRAY(driver_info_1, DRIVER_INFO_1, *returned+ndrivers )) == NULL) {
6940 DEBUG(0,("enumprinterdrivers_level1: failed to enlarge driver info buffer!\n"));
6941 SAFE_FREE(list);
6942 return WERR_NOMEM;
6946 for (i=0; i<ndrivers; i++) {
6947 WERROR status;
6948 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
6949 ZERO_STRUCT(driver);
6950 status = get_a_printer_driver(&driver, 3, list[i],
6951 architecture, version);
6952 if (!W_ERROR_IS_OK(status)) {
6953 SAFE_FREE(list);
6954 SAFE_FREE(driver_info_1);
6955 return status;
6957 fill_printer_driver_info_1(&driver_info_1[*returned+i], driver, servername, architecture );
6958 free_a_printer_driver(driver, 3);
6961 *returned+=ndrivers;
6962 SAFE_FREE(list);
6965 /* check the required size. */
6966 for (i=0; i<*returned; i++) {
6967 DEBUGADD(6,("adding driver [%d]'s size\n",i));
6968 *needed += spoolss_size_printer_driver_info_1(&driver_info_1[i]);
6971 if (*needed > offered) {
6972 result = WERR_INSUFFICIENT_BUFFER;
6973 goto out;
6976 if (!rpcbuf_alloc_size(buffer, *needed)) {
6977 result = WERR_NOMEM;
6978 goto out;
6981 /* fill the buffer with the driver structures */
6982 for (i=0; i<*returned; i++) {
6983 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
6984 smb_io_printer_driver_info_1("", buffer, &driver_info_1[i], 0);
6987 out:
6988 SAFE_FREE(driver_info_1);
6990 if ( !W_ERROR_IS_OK(result) )
6991 *returned = 0;
6993 return result;
6996 /****************************************************************************
6997 Enumerates all printer drivers at level 2.
6998 ****************************************************************************/
7000 static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7002 int i;
7003 int ndrivers;
7004 uint32 version;
7005 fstring *list = NULL;
7006 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7007 DRIVER_INFO_2 *driver_info_2=NULL;
7008 WERROR result = WERR_OK;
7010 *returned=0;
7012 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7013 list=NULL;
7014 ndrivers=get_ntdrivers(&list, architecture, version);
7015 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7017 if(ndrivers == -1) {
7018 SAFE_FREE(driver_info_2);
7019 return WERR_NOMEM;
7022 if(ndrivers != 0) {
7023 if((driver_info_2=SMB_REALLOC_ARRAY(driver_info_2, DRIVER_INFO_2, *returned+ndrivers )) == NULL) {
7024 DEBUG(0,("enumprinterdrivers_level2: failed to enlarge driver info buffer!\n"));
7025 SAFE_FREE(list);
7026 return WERR_NOMEM;
7030 for (i=0; i<ndrivers; i++) {
7031 WERROR status;
7033 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7034 ZERO_STRUCT(driver);
7035 status = get_a_printer_driver(&driver, 3, list[i],
7036 architecture, version);
7037 if (!W_ERROR_IS_OK(status)) {
7038 SAFE_FREE(list);
7039 SAFE_FREE(driver_info_2);
7040 return status;
7042 fill_printer_driver_info_2(&driver_info_2[*returned+i], driver, servername);
7043 free_a_printer_driver(driver, 3);
7046 *returned+=ndrivers;
7047 SAFE_FREE(list);
7050 /* check the required size. */
7051 for (i=0; i<*returned; i++) {
7052 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7053 *needed += spoolss_size_printer_driver_info_2(&(driver_info_2[i]));
7056 if (*needed > offered) {
7057 result = WERR_INSUFFICIENT_BUFFER;
7058 goto out;
7061 if (!rpcbuf_alloc_size(buffer, *needed)) {
7062 result = WERR_NOMEM;
7063 goto out;
7066 /* fill the buffer with the form structures */
7067 for (i=0; i<*returned; i++) {
7068 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7069 smb_io_printer_driver_info_2("", buffer, &(driver_info_2[i]), 0);
7072 out:
7073 SAFE_FREE(driver_info_2);
7075 if ( !W_ERROR_IS_OK(result) )
7076 *returned = 0;
7078 return result;
7081 /****************************************************************************
7082 Enumerates all printer drivers at level 3.
7083 ****************************************************************************/
7085 static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture, RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7087 int i;
7088 int ndrivers;
7089 uint32 version;
7090 fstring *list = NULL;
7091 DRIVER_INFO_3 *driver_info_3=NULL;
7092 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7093 WERROR result = WERR_OK;
7095 *returned=0;
7097 for (version=0; version<DRIVER_MAX_VERSION; version++) {
7098 list=NULL;
7099 ndrivers=get_ntdrivers(&list, architecture, version);
7100 DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
7102 if(ndrivers == -1) {
7103 SAFE_FREE(driver_info_3);
7104 return WERR_NOMEM;
7107 if(ndrivers != 0) {
7108 if((driver_info_3=SMB_REALLOC_ARRAY(driver_info_3, DRIVER_INFO_3, *returned+ndrivers )) == NULL) {
7109 DEBUG(0,("enumprinterdrivers_level3: failed to enlarge driver info buffer!\n"));
7110 SAFE_FREE(list);
7111 return WERR_NOMEM;
7115 for (i=0; i<ndrivers; i++) {
7116 WERROR status;
7118 DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
7119 ZERO_STRUCT(driver);
7120 status = get_a_printer_driver(&driver, 3, list[i],
7121 architecture, version);
7122 if (!W_ERROR_IS_OK(status)) {
7123 SAFE_FREE(list);
7124 SAFE_FREE(driver_info_3);
7125 return status;
7127 fill_printer_driver_info_3(&driver_info_3[*returned+i], driver, servername);
7128 free_a_printer_driver(driver, 3);
7131 *returned+=ndrivers;
7132 SAFE_FREE(list);
7135 /* check the required size. */
7136 for (i=0; i<*returned; i++) {
7137 DEBUGADD(6,("adding driver [%d]'s size\n",i));
7138 *needed += spoolss_size_printer_driver_info_3(&driver_info_3[i]);
7141 if (*needed > offered) {
7142 result = WERR_INSUFFICIENT_BUFFER;
7143 goto out;
7146 if (!rpcbuf_alloc_size(buffer, *needed)) {
7147 result = WERR_NOMEM;
7148 goto out;
7151 /* fill the buffer with the driver structures */
7152 for (i=0; i<*returned; i++) {
7153 DEBUGADD(6,("adding driver [%d] to buffer\n",i));
7154 smb_io_printer_driver_info_3("", buffer, &driver_info_3[i], 0);
7157 out:
7158 for (i=0; i<*returned; i++) {
7159 SAFE_FREE(driver_info_3[i].dependentfiles);
7162 SAFE_FREE(driver_info_3);
7164 if ( !W_ERROR_IS_OK(result) )
7165 *returned = 0;
7167 return result;
7170 /****************************************************************************
7171 Enumerates all printer drivers.
7172 ****************************************************************************/
7174 WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
7176 uint32 level = q_u->level;
7177 RPC_BUFFER *buffer = NULL;
7178 uint32 offered = q_u->offered;
7179 uint32 *needed = &r_u->needed;
7180 uint32 *returned = &r_u->returned;
7182 fstring servername;
7183 fstring architecture;
7185 /* that's an [in out] buffer */
7187 if (!q_u->buffer && (offered!=0)) {
7188 return WERR_INVALID_PARAM;
7191 rpcbuf_move(q_u->buffer, &r_u->buffer);
7192 buffer = r_u->buffer;
7194 DEBUG(4,("_spoolss_enumprinterdrivers\n"));
7196 *needed = 0;
7197 *returned = 0;
7199 unistr2_to_ascii(architecture, &q_u->environment, sizeof(architecture));
7200 unistr2_to_ascii(servername, &q_u->name, sizeof(servername));
7202 if ( !is_myname_or_ipaddr( servername ) )
7203 return WERR_UNKNOWN_PRINTER_DRIVER;
7205 switch (level) {
7206 case 1:
7207 return enumprinterdrivers_level1(servername, architecture, buffer, offered, needed, returned);
7208 case 2:
7209 return enumprinterdrivers_level2(servername, architecture, buffer, offered, needed, returned);
7210 case 3:
7211 return enumprinterdrivers_level3(servername, architecture, buffer, offered, needed, returned);
7212 default:
7213 return WERR_UNKNOWN_LEVEL;
7217 /****************************************************************************
7218 ****************************************************************************/
7220 static void fill_form_1(FORM_1 *form, nt_forms_struct *list)
7222 form->flag=list->flag;
7223 init_unistr(&form->name, list->name);
7224 form->width=list->width;
7225 form->length=list->length;
7226 form->left=list->left;
7227 form->top=list->top;
7228 form->right=list->right;
7229 form->bottom=list->bottom;
7232 /****************************************************************************
7233 ****************************************************************************/
7235 WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
7237 uint32 level = q_u->level;
7238 RPC_BUFFER *buffer = NULL;
7239 uint32 offered = q_u->offered;
7240 uint32 *needed = &r_u->needed;
7241 uint32 *numofforms = &r_u->numofforms;
7242 uint32 numbuiltinforms;
7244 nt_forms_struct *list=NULL;
7245 nt_forms_struct *builtinlist=NULL;
7246 FORM_1 *forms_1;
7247 int buffer_size=0;
7248 int i;
7250 /* that's an [in out] buffer */
7252 if (!q_u->buffer && (offered!=0) ) {
7253 return WERR_INVALID_PARAM;
7256 rpcbuf_move(q_u->buffer, &r_u->buffer);
7257 buffer = r_u->buffer;
7259 DEBUG(4,("_spoolss_enumforms\n"));
7260 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7261 DEBUGADD(5,("Info level [%d]\n", level));
7263 numbuiltinforms = get_builtin_ntforms(&builtinlist);
7264 DEBUGADD(5,("Number of builtin forms [%d]\n", numbuiltinforms));
7265 *numofforms = get_ntforms(&list);
7266 DEBUGADD(5,("Number of user forms [%d]\n", *numofforms));
7267 *numofforms += numbuiltinforms;
7269 if (*numofforms == 0) {
7270 SAFE_FREE(builtinlist);
7271 SAFE_FREE(list);
7272 return WERR_NO_MORE_ITEMS;
7275 switch (level) {
7276 case 1:
7277 if ((forms_1=SMB_MALLOC_ARRAY(FORM_1, *numofforms)) == NULL) {
7278 SAFE_FREE(builtinlist);
7279 SAFE_FREE(list);
7280 *numofforms=0;
7281 return WERR_NOMEM;
7284 /* construct the list of form structures */
7285 for (i=0; i<numbuiltinforms; i++) {
7286 DEBUGADD(6,("Filling form number [%d]\n",i));
7287 fill_form_1(&forms_1[i], &builtinlist[i]);
7290 SAFE_FREE(builtinlist);
7292 for (; i<*numofforms; i++) {
7293 DEBUGADD(6,("Filling form number [%d]\n",i));
7294 fill_form_1(&forms_1[i], &list[i-numbuiltinforms]);
7297 SAFE_FREE(list);
7299 /* check the required size. */
7300 for (i=0; i<numbuiltinforms; i++) {
7301 DEBUGADD(6,("adding form [%d]'s size\n",i));
7302 buffer_size += spoolss_size_form_1(&forms_1[i]);
7304 for (; i<*numofforms; i++) {
7305 DEBUGADD(6,("adding form [%d]'s size\n",i));
7306 buffer_size += spoolss_size_form_1(&forms_1[i]);
7309 *needed=buffer_size;
7311 if (*needed > offered) {
7312 SAFE_FREE(forms_1);
7313 *numofforms=0;
7314 return WERR_INSUFFICIENT_BUFFER;
7317 if (!rpcbuf_alloc_size(buffer, buffer_size)){
7318 SAFE_FREE(forms_1);
7319 *numofforms=0;
7320 return WERR_NOMEM;
7323 /* fill the buffer with the form structures */
7324 for (i=0; i<numbuiltinforms; i++) {
7325 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7326 smb_io_form_1("", buffer, &forms_1[i], 0);
7328 for (; i<*numofforms; i++) {
7329 DEBUGADD(6,("adding form [%d] to buffer\n",i));
7330 smb_io_form_1("", buffer, &forms_1[i], 0);
7333 SAFE_FREE(forms_1);
7335 return WERR_OK;
7337 default:
7338 SAFE_FREE(list);
7339 SAFE_FREE(builtinlist);
7340 return WERR_UNKNOWN_LEVEL;
7344 /****************************************************************************
7345 ****************************************************************************/
7347 WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
7349 uint32 level = q_u->level;
7350 UNISTR2 *uni_formname = &q_u->formname;
7351 RPC_BUFFER *buffer = NULL;
7352 uint32 offered = q_u->offered;
7353 uint32 *needed = &r_u->needed;
7355 nt_forms_struct *list=NULL;
7356 nt_forms_struct builtin_form;
7357 bool foundBuiltin;
7358 FORM_1 form_1;
7359 fstring form_name;
7360 int buffer_size=0;
7361 int numofforms=0, i=0;
7363 /* that's an [in out] buffer */
7365 if (!q_u->buffer && (offered!=0)) {
7366 return WERR_INVALID_PARAM;
7369 rpcbuf_move(q_u->buffer, &r_u->buffer);
7370 buffer = r_u->buffer;
7372 unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
7374 DEBUG(4,("_spoolss_getform\n"));
7375 DEBUGADD(5,("Offered buffer size [%d]\n", offered));
7376 DEBUGADD(5,("Info level [%d]\n", level));
7378 foundBuiltin = get_a_builtin_ntform(uni_formname,&builtin_form);
7379 if (!foundBuiltin) {
7380 numofforms = get_ntforms(&list);
7381 DEBUGADD(5,("Number of forms [%d]\n", numofforms));
7383 if (numofforms == 0)
7384 return WERR_BADFID;
7387 switch (level) {
7388 case 1:
7389 if (foundBuiltin) {
7390 fill_form_1(&form_1, &builtin_form);
7391 } else {
7393 /* Check if the requested name is in the list of form structures */
7394 for (i=0; i<numofforms; i++) {
7396 DEBUG(4,("_spoolss_getform: checking form %s (want %s)\n", list[i].name, form_name));
7398 if (strequal(form_name, list[i].name)) {
7399 DEBUGADD(6,("Found form %s number [%d]\n", form_name, i));
7400 fill_form_1(&form_1, &list[i]);
7401 break;
7405 SAFE_FREE(list);
7406 if (i == numofforms) {
7407 return WERR_BADFID;
7410 /* check the required size. */
7412 *needed=spoolss_size_form_1(&form_1);
7414 if (*needed > offered)
7415 return WERR_INSUFFICIENT_BUFFER;
7417 if (!rpcbuf_alloc_size(buffer, buffer_size))
7418 return WERR_NOMEM;
7420 /* fill the buffer with the form structures */
7421 DEBUGADD(6,("adding form %s [%d] to buffer\n", form_name, i));
7422 smb_io_form_1("", buffer, &form_1, 0);
7424 return WERR_OK;
7426 default:
7427 SAFE_FREE(list);
7428 return WERR_UNKNOWN_LEVEL;
7432 /****************************************************************************
7433 ****************************************************************************/
7435 static void fill_port_1(PORT_INFO_1 *port, const char *name)
7437 init_unistr(&port->port_name, name);
7440 /****************************************************************************
7441 TODO: This probably needs distinguish between TCP/IP and Local ports
7442 somehow.
7443 ****************************************************************************/
7445 static void fill_port_2(PORT_INFO_2 *port, const char *name)
7447 init_unistr(&port->port_name, name);
7448 init_unistr(&port->monitor_name, "Local Monitor");
7449 init_unistr(&port->description, SPL_LOCAL_PORT );
7450 port->port_type=PORT_TYPE_WRITE;
7451 port->reserved=0x0;
7455 /****************************************************************************
7456 wrapper around the enumer ports command
7457 ****************************************************************************/
7459 WERROR enumports_hook(TALLOC_CTX *ctx, int *count, char ***lines )
7461 char *cmd = lp_enumports_cmd();
7462 char **qlines = NULL;
7463 char *command = NULL;
7464 int numlines;
7465 int ret;
7466 int fd;
7468 *count = 0;
7469 *lines = NULL;
7471 /* if no hook then just fill in the default port */
7473 if ( !*cmd ) {
7474 if (!(qlines = SMB_MALLOC_ARRAY( char*, 2 ))) {
7475 return WERR_NOMEM;
7477 if (!(qlines[0] = SMB_STRDUP( SAMBA_PRINTER_PORT_NAME ))) {
7478 SAFE_FREE(qlines);
7479 return WERR_NOMEM;
7481 qlines[1] = NULL;
7482 numlines = 1;
7484 else {
7485 /* we have a valid enumport command */
7487 command = talloc_asprintf(ctx, "%s \"%d\"", cmd, 1);
7488 if (!command) {
7489 return WERR_NOMEM;
7492 DEBUG(10,("Running [%s]\n", command));
7493 ret = smbrun(command, &fd);
7494 DEBUG(10,("Returned [%d]\n", ret));
7495 TALLOC_FREE(command);
7496 if (ret != 0) {
7497 if (fd != -1) {
7498 close(fd);
7500 return WERR_ACCESS_DENIED;
7503 numlines = 0;
7504 qlines = fd_lines_load(fd, &numlines, 0);
7505 DEBUGADD(10,("Lines returned = [%d]\n", numlines));
7506 close(fd);
7509 *count = numlines;
7510 *lines = qlines;
7512 return WERR_OK;
7515 /****************************************************************************
7516 enumports level 1.
7517 ****************************************************************************/
7519 static WERROR enumports_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7521 PORT_INFO_1 *ports=NULL;
7522 int i=0;
7523 WERROR result = WERR_OK;
7524 char **qlines = NULL;
7525 int numlines = 0;
7527 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7528 if (!W_ERROR_IS_OK(result)) {
7529 file_lines_free(qlines);
7530 return result;
7533 if(numlines) {
7534 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_1, numlines )) == NULL) {
7535 DEBUG(10,("Returning WERR_NOMEM [%s]\n",
7536 dos_errstr(WERR_NOMEM)));
7537 file_lines_free(qlines);
7538 return WERR_NOMEM;
7541 for (i=0; i<numlines; i++) {
7542 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7543 fill_port_1(&ports[i], qlines[i]);
7546 file_lines_free(qlines);
7548 *returned = numlines;
7550 /* check the required size. */
7551 for (i=0; i<*returned; i++) {
7552 DEBUGADD(6,("adding port [%d]'s size\n", i));
7553 *needed += spoolss_size_port_info_1(&ports[i]);
7556 if (*needed > offered) {
7557 result = WERR_INSUFFICIENT_BUFFER;
7558 goto out;
7561 if (!rpcbuf_alloc_size(buffer, *needed)) {
7562 result = WERR_NOMEM;
7563 goto out;
7566 /* fill the buffer with the ports structures */
7567 for (i=0; i<*returned; i++) {
7568 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7569 smb_io_port_1("", buffer, &ports[i], 0);
7572 out:
7573 SAFE_FREE(ports);
7575 if ( !W_ERROR_IS_OK(result) )
7576 *returned = 0;
7578 return result;
7581 /****************************************************************************
7582 enumports level 2.
7583 ****************************************************************************/
7585 static WERROR enumports_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
7587 PORT_INFO_2 *ports=NULL;
7588 int i=0;
7589 WERROR result = WERR_OK;
7590 char **qlines = NULL;
7591 int numlines = 0;
7593 result = enumports_hook(talloc_tos(), &numlines, &qlines );
7594 if ( !W_ERROR_IS_OK(result)) {
7595 file_lines_free(qlines);
7596 return result;
7599 if(numlines) {
7600 if((ports=SMB_MALLOC_ARRAY( PORT_INFO_2, numlines)) == NULL) {
7601 file_lines_free(qlines);
7602 return WERR_NOMEM;
7605 for (i=0; i<numlines; i++) {
7606 DEBUG(6,("Filling port number [%d] with port [%s]\n", i, qlines[i]));
7607 fill_port_2(&(ports[i]), qlines[i]);
7611 file_lines_free(qlines);
7613 *returned = numlines;
7615 /* check the required size. */
7616 for (i=0; i<*returned; i++) {
7617 DEBUGADD(6,("adding port [%d]'s size\n", i));
7618 *needed += spoolss_size_port_info_2(&ports[i]);
7621 if (*needed > offered) {
7622 result = WERR_INSUFFICIENT_BUFFER;
7623 goto out;
7626 if (!rpcbuf_alloc_size(buffer, *needed)) {
7627 result = WERR_NOMEM;
7628 goto out;
7631 /* fill the buffer with the ports structures */
7632 for (i=0; i<*returned; i++) {
7633 DEBUGADD(6,("adding port [%d] to buffer\n", i));
7634 smb_io_port_2("", buffer, &ports[i], 0);
7637 out:
7638 SAFE_FREE(ports);
7640 if ( !W_ERROR_IS_OK(result) )
7641 *returned = 0;
7643 return result;
7646 /****************************************************************************
7647 enumports.
7648 ****************************************************************************/
7650 WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
7652 uint32 level = q_u->level;
7653 RPC_BUFFER *buffer = NULL;
7654 uint32 offered = q_u->offered;
7655 uint32 *needed = &r_u->needed;
7656 uint32 *returned = &r_u->returned;
7658 /* that's an [in out] buffer */
7660 if (!q_u->buffer && (offered!=0)) {
7661 return WERR_INVALID_PARAM;
7664 rpcbuf_move(q_u->buffer, &r_u->buffer);
7665 buffer = r_u->buffer;
7667 DEBUG(4,("_spoolss_enumports\n"));
7669 *returned=0;
7670 *needed=0;
7672 switch (level) {
7673 case 1:
7674 return enumports_level_1(buffer, offered, needed, returned);
7675 case 2:
7676 return enumports_level_2(buffer, offered, needed, returned);
7677 default:
7678 return WERR_UNKNOWN_LEVEL;
7682 /****************************************************************************
7683 ****************************************************************************/
7685 static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_srv_name,
7686 const SPOOL_PRINTER_INFO_LEVEL *info,
7687 DEVICEMODE *devmode, SEC_DESC_BUF *sec_desc_buf,
7688 uint32 user_switch, const SPOOL_USER_CTR *user,
7689 POLICY_HND *handle)
7691 NT_PRINTER_INFO_LEVEL *printer = NULL;
7692 fstring name;
7693 int snum;
7694 WERROR err = WERR_OK;
7696 if ( !(printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
7697 DEBUG(0,("spoolss_addprinterex_level_2: malloc fail.\n"));
7698 return WERR_NOMEM;
7701 /* convert from UNICODE to ASCII - this allocates the info_2 struct inside *printer.*/
7702 if (!convert_printer_info(info, printer, 2)) {
7703 free_a_printer(&printer, 2);
7704 return WERR_NOMEM;
7707 /* check to see if the printer already exists */
7709 if ((snum = print_queue_snum(printer->info_2->sharename)) != -1) {
7710 DEBUG(5, ("spoolss_addprinterex_level_2: Attempted to add a printer named [%s] when one already existed!\n",
7711 printer->info_2->sharename));
7712 free_a_printer(&printer, 2);
7713 return WERR_PRINTER_ALREADY_EXISTS;
7716 /* FIXME!!! smbd should check to see if the driver is installed before
7717 trying to add a printer like this --jerry */
7719 if (*lp_addprinter_cmd() ) {
7720 if ( !add_printer_hook(p->mem_ctx, p->pipe_user.nt_user_token, printer) ) {
7721 free_a_printer(&printer,2);
7722 return WERR_ACCESS_DENIED;
7724 } else {
7725 DEBUG(0,("spoolss_addprinterex_level_2: add printer for printer %s called and no"
7726 "smb.conf parameter \"addprinter command\" is defined. This"
7727 "parameter must exist for this call to succeed\n",
7728 printer->info_2->sharename ));
7731 /* use our primary netbios name since get_a_printer() will convert
7732 it to what the client expects on a case by case basis */
7734 slprintf(name, sizeof(name)-1, "\\\\%s\\%s", global_myname(),
7735 printer->info_2->sharename);
7738 if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
7739 free_a_printer(&printer,2);
7740 return WERR_ACCESS_DENIED;
7743 /* you must be a printer admin to add a new printer */
7744 if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
7745 free_a_printer(&printer,2);
7746 return WERR_ACCESS_DENIED;
7750 * Do sanity check on the requested changes for Samba.
7753 if (!check_printer_ok(printer->info_2, snum)) {
7754 free_a_printer(&printer,2);
7755 return WERR_INVALID_PARAM;
7759 * When a printer is created, the drivername bound to the printer is used
7760 * to lookup previously saved driver initialization info, which is then
7761 * bound to the new printer, simulating what happens in the Windows arch.
7764 if (!devmode)
7766 set_driver_init(printer, 2);
7768 else
7770 /* A valid devmode was included, convert and link it
7772 DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
7774 if (!convert_devicemode(printer->info_2->printername, devmode,
7775 &printer->info_2->devmode))
7776 return WERR_NOMEM;
7779 /* write the ASCII on disk */
7780 err = mod_a_printer(printer, 2);
7781 if (!W_ERROR_IS_OK(err)) {
7782 free_a_printer(&printer,2);
7783 return err;
7786 if (!open_printer_hnd(p, handle, name, PRINTER_ACCESS_ADMINISTER)) {
7787 /* Handle open failed - remove addition. */
7788 del_a_printer(printer->info_2->sharename);
7789 free_a_printer(&printer,2);
7790 return WERR_ACCESS_DENIED;
7793 update_c_setprinter(False);
7794 free_a_printer(&printer,2);
7796 return WERR_OK;
7799 /****************************************************************************
7800 ****************************************************************************/
7802 WERROR _spoolss_addprinterex( pipes_struct *p, SPOOL_Q_ADDPRINTEREX *q_u, SPOOL_R_ADDPRINTEREX *r_u)
7804 UNISTR2 *uni_srv_name = q_u->server_name;
7805 uint32 level = q_u->level;
7806 SPOOL_PRINTER_INFO_LEVEL *info = &q_u->info;
7807 DEVICEMODE *devmode = q_u->devmode_ctr.devmode;
7808 SEC_DESC_BUF *sdb = q_u->secdesc_ctr;
7809 uint32 user_switch = q_u->user_switch;
7810 SPOOL_USER_CTR *user = &q_u->user_ctr;
7811 POLICY_HND *handle = &r_u->handle;
7813 switch (level) {
7814 case 1:
7815 /* we don't handle yet */
7816 /* but I know what to do ... */
7817 return WERR_UNKNOWN_LEVEL;
7818 case 2:
7819 return spoolss_addprinterex_level_2(p, uni_srv_name, info,
7820 devmode, sdb,
7821 user_switch, user, handle);
7822 default:
7823 return WERR_UNKNOWN_LEVEL;
7827 /****************************************************************************
7828 ****************************************************************************/
7830 WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
7832 uint32 level = q_u->level;
7833 SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
7834 WERROR err = WERR_OK;
7835 NT_PRINTER_DRIVER_INFO_LEVEL driver;
7836 fstring driver_name;
7837 uint32 version;
7839 ZERO_STRUCT(driver);
7841 if (!convert_printer_driver_info(info, &driver, level)) {
7842 err = WERR_NOMEM;
7843 goto done;
7846 DEBUG(5,("Cleaning driver's information\n"));
7847 err = clean_up_driver_struct(driver, level, &p->pipe_user);
7848 if (!W_ERROR_IS_OK(err))
7849 goto done;
7851 DEBUG(5,("Moving driver to final destination\n"));
7852 if( !W_ERROR_IS_OK(err = move_driver_to_download_area(driver, level, &p->pipe_user, &err)) ) {
7853 goto done;
7856 if (add_a_printer_driver(driver, level)!=0) {
7857 err = WERR_ACCESS_DENIED;
7858 goto done;
7862 * I think this is where he DrvUpgradePrinter() hook would be
7863 * be called in a driver's interface DLL on a Windows NT 4.0/2k
7864 * server. Right now, we just need to send ourselves a message
7865 * to update each printer bound to this driver. --jerry
7868 if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
7869 DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
7870 driver_name));
7874 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp),
7875 * decide if the driver init data should be deleted. The rules are:
7876 * 1) never delete init data if it is a 9x driver, they don't use it anyway
7877 * 2) delete init data only if there is no 2k/Xp driver
7878 * 3) always delete init data
7879 * The generalized rule is always use init data from the highest order driver.
7880 * It is necessary to follow the driver install by an initialization step to
7881 * finish off this process.
7883 if (level == 3)
7884 version = driver.info_3->cversion;
7885 else if (level == 6)
7886 version = driver.info_6->version;
7887 else
7888 version = -1;
7889 switch (version) {
7891 * 9x printer driver - never delete init data
7893 case 0:
7894 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n",
7895 driver_name));
7896 break;
7899 * Nt or 2k (compatiblity mode) printer driver - only delete init data if
7900 * there is no 2k/Xp driver init data for this driver name.
7902 case 2:
7904 NT_PRINTER_DRIVER_INFO_LEVEL driver1;
7906 if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) {
7908 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
7910 if (!del_driver_init(driver_name))
7911 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
7912 } else {
7914 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
7916 free_a_printer_driver(driver1,3);
7917 DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",
7918 driver_name));
7921 break;
7924 * 2k or Xp printer driver - always delete init data
7926 case 3:
7927 if (!del_driver_init(driver_name))
7928 DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name));
7929 break;
7931 default:
7932 DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
7933 break;
7937 done:
7938 free_a_printer_driver(driver, level);
7939 return err;
7942 /********************************************************************
7943 * spoolss_addprinterdriverex
7944 ********************************************************************/
7946 WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
7948 SPOOL_Q_ADDPRINTERDRIVER q_u_local;
7949 SPOOL_R_ADDPRINTERDRIVER r_u_local;
7952 * we only support the semantics of AddPrinterDriver()
7953 * i.e. only copy files that are newer than existing ones
7956 if ( q_u->copy_flags != APD_COPY_NEW_FILES )
7957 return WERR_ACCESS_DENIED;
7959 ZERO_STRUCT(q_u_local);
7960 ZERO_STRUCT(r_u_local);
7962 /* just pass the information off to _spoolss_addprinterdriver() */
7963 q_u_local.server_name_ptr = q_u->server_name_ptr;
7964 copy_unistr2(&q_u_local.server_name, &q_u->server_name);
7965 q_u_local.level = q_u->level;
7966 memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
7968 return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
7971 /****************************************************************************
7972 ****************************************************************************/
7974 static void fill_driverdir_1(DRIVER_DIRECTORY_1 *info, char *name)
7976 init_unistr(&info->name, name);
7979 /****************************************************************************
7980 ****************************************************************************/
7982 static WERROR getprinterdriverdir_level_1(UNISTR2 *name, UNISTR2 *uni_environment, RPC_BUFFER *buffer, uint32 offered, uint32 *needed)
7984 char *path = NULL;
7985 char *long_archi = NULL;
7986 char *servername = NULL;
7987 char *pservername = NULL;
7988 const char *short_archi;
7989 DRIVER_DIRECTORY_1 *info=NULL;
7990 WERROR result = WERR_OK;
7991 TALLOC_CTX *ctx = talloc_tos();
7993 servername = unistr2_to_ascii_talloc(ctx, name);
7994 if (!servername) {
7995 return WERR_NOMEM;
7997 long_archi = unistr2_to_ascii_talloc(ctx, uni_environment);
7998 if (!long_archi) {
7999 return WERR_NOMEM;
8002 /* check for beginning double '\'s and that the server
8003 long enough */
8005 pservername = servername;
8006 if ( *pservername == '\\' && strlen(servername)>2 ) {
8007 pservername += 2;
8010 if ( !is_myname_or_ipaddr( pservername ) )
8011 return WERR_INVALID_PARAM;
8013 if (!(short_archi = get_short_archi(long_archi)))
8014 return WERR_INVALID_ENVIRONMENT;
8016 if((info=SMB_MALLOC_P(DRIVER_DIRECTORY_1)) == NULL)
8017 return WERR_NOMEM;
8019 path = talloc_asprintf(ctx,
8020 "\\\\%s\\print$\\%s", pservername, short_archi);
8021 if (!path) {
8022 result = WERR_NOMEM;
8023 goto out;
8026 DEBUG(4,("printer driver directory: [%s]\n", path));
8028 fill_driverdir_1(info, path);
8030 *needed += spoolss_size_driverdir_info_1(info);
8032 if (*needed > offered) {
8033 result = WERR_INSUFFICIENT_BUFFER;
8034 goto out;
8037 if (!rpcbuf_alloc_size(buffer, *needed)) {
8038 result = WERR_NOMEM;
8039 goto out;
8042 smb_io_driverdir_1("", buffer, info, 0);
8044 out:
8045 SAFE_FREE(info);
8047 return result;
8050 /****************************************************************************
8051 ****************************************************************************/
8053 WERROR _spoolss_getprinterdriverdirectory(pipes_struct *p, SPOOL_Q_GETPRINTERDRIVERDIR *q_u, SPOOL_R_GETPRINTERDRIVERDIR *r_u)
8055 UNISTR2 *name = &q_u->name;
8056 UNISTR2 *uni_environment = &q_u->environment;
8057 uint32 level = q_u->level;
8058 RPC_BUFFER *buffer = NULL;
8059 uint32 offered = q_u->offered;
8060 uint32 *needed = &r_u->needed;
8062 /* that's an [in out] buffer */
8064 if (!q_u->buffer && (offered!=0)) {
8065 return WERR_INVALID_PARAM;
8068 rpcbuf_move(q_u->buffer, &r_u->buffer);
8069 buffer = r_u->buffer;
8071 DEBUG(4,("_spoolss_getprinterdriverdirectory\n"));
8073 *needed=0;
8075 switch(level) {
8076 case 1:
8077 return getprinterdriverdir_level_1(name, uni_environment, buffer, offered, needed);
8078 default:
8079 return WERR_UNKNOWN_LEVEL;
8083 /****************************************************************************
8084 ****************************************************************************/
8086 WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
8088 POLICY_HND *handle = &q_u->handle;
8089 uint32 idx = q_u->index;
8090 uint32 in_value_len = q_u->valuesize;
8091 uint32 in_data_len = q_u->datasize;
8092 uint32 *out_max_value_len = &r_u->valuesize;
8093 uint16 **out_value = &r_u->value;
8094 uint32 *out_value_len = &r_u->realvaluesize;
8095 uint32 *out_type = &r_u->type;
8096 uint32 *out_max_data_len = &r_u->datasize;
8097 uint8 **data_out = &r_u->data;
8098 uint32 *out_data_len = &r_u->realdatasize;
8100 NT_PRINTER_INFO_LEVEL *printer = NULL;
8102 uint32 biggest_valuesize;
8103 uint32 biggest_datasize;
8104 uint32 data_len;
8105 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8106 int snum;
8107 WERROR result;
8108 REGISTRY_VALUE *val = NULL;
8109 NT_PRINTER_DATA *p_data;
8110 int i, key_index, num_values;
8111 int name_length;
8113 *out_type = 0;
8115 *out_max_data_len = 0;
8116 *data_out = NULL;
8117 *out_data_len = 0;
8119 DEBUG(5,("spoolss_enumprinterdata\n"));
8121 if (!Printer) {
8122 DEBUG(2,("_spoolss_enumprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8123 return WERR_BADFID;
8126 if (!get_printer_snum(p,handle, &snum, NULL))
8127 return WERR_BADFID;
8129 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8130 if (!W_ERROR_IS_OK(result))
8131 return result;
8133 p_data = printer->info_2->data;
8134 key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
8136 result = WERR_OK;
8139 * The NT machine wants to know the biggest size of value and data
8141 * cf: MSDN EnumPrinterData remark section
8144 if ( !in_value_len && !in_data_len && (key_index != -1) )
8146 DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
8148 biggest_valuesize = 0;
8149 biggest_datasize = 0;
8151 num_values = regval_ctr_numvals( p_data->keys[key_index].values );
8153 for ( i=0; i<num_values; i++ )
8155 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
8157 name_length = strlen(val->valuename);
8158 if ( strlen(val->valuename) > biggest_valuesize )
8159 biggest_valuesize = name_length;
8161 if ( val->size > biggest_datasize )
8162 biggest_datasize = val->size;
8164 DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
8165 biggest_datasize));
8168 /* the value is an UNICODE string but real_value_size is the length
8169 in bytes including the trailing 0 */
8171 *out_value_len = 2 * (1+biggest_valuesize);
8172 *out_data_len = biggest_datasize;
8174 DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
8176 goto done;
8180 * the value len is wrong in NT sp3
8181 * that's the number of bytes not the number of unicode chars
8184 if ( key_index != -1 )
8185 val = regval_ctr_specific_value( p_data->keys[key_index].values, idx );
8187 if ( !val )
8190 /* out_value should default to "" or else NT4 has
8191 problems unmarshalling the response */
8193 *out_max_value_len=(in_value_len/sizeof(uint16));
8195 if (in_value_len) {
8196 if((*out_value=(uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
8198 result = WERR_NOMEM;
8199 goto done;
8201 *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
8202 } else {
8203 *out_value=NULL;
8204 *out_value_len = 0;
8207 /* the data is counted in bytes */
8209 *out_max_data_len = in_data_len;
8210 *out_data_len = in_data_len;
8212 /* only allocate when given a non-zero data_len */
8214 if ( in_data_len && ((*data_out=(uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
8216 result = WERR_NOMEM;
8217 goto done;
8220 result = WERR_NO_MORE_ITEMS;
8222 else
8225 * the value is:
8226 * - counted in bytes in the request
8227 * - counted in UNICODE chars in the max reply
8228 * - counted in bytes in the real size
8230 * take a pause *before* coding not *during* coding
8233 /* name */
8234 *out_max_value_len=(in_value_len/sizeof(uint16));
8235 if (in_value_len) {
8236 if ( (*out_value = (uint16 *)TALLOC_ZERO(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
8238 result = WERR_NOMEM;
8239 goto done;
8242 *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), (size_t)in_value_len, 0);
8243 } else {
8244 *out_value = NULL;
8245 *out_value_len = 0;
8248 /* type */
8250 *out_type = regval_type( val );
8252 /* data - counted in bytes */
8254 *out_max_data_len = in_data_len;
8255 if ( in_data_len && (*data_out = (uint8 *)TALLOC_ZERO(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
8257 result = WERR_NOMEM;
8258 goto done;
8260 data_len = regval_size(val);
8261 if ( *data_out && data_len )
8262 memcpy( *data_out, regval_data_p(val), data_len );
8263 *out_data_len = data_len;
8266 done:
8267 free_a_printer(&printer, 2);
8268 return result;
8271 /****************************************************************************
8272 ****************************************************************************/
8274 WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
8276 POLICY_HND *handle = &q_u->handle;
8277 UNISTR2 *value = &q_u->value;
8278 uint32 type = q_u->type;
8279 uint8 *data = q_u->data;
8280 uint32 real_len = q_u->real_len;
8282 NT_PRINTER_INFO_LEVEL *printer = NULL;
8283 int snum=0;
8284 WERROR status = WERR_OK;
8285 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8286 fstring valuename;
8288 DEBUG(5,("spoolss_setprinterdata\n"));
8290 if (!Printer) {
8291 DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8292 return WERR_BADFID;
8295 if ( Printer->printer_type == SPLHND_SERVER ) {
8296 DEBUG(10,("_spoolss_setprinterdata: Not implemented for server handles yet\n"));
8297 return WERR_INVALID_PARAM;
8300 if (!get_printer_snum(p,handle, &snum, NULL))
8301 return WERR_BADFID;
8304 * Access check : NT returns "access denied" if you make a
8305 * SetPrinterData call without the necessary privildge.
8306 * we were originally returning OK if nothing changed
8307 * which made Win2k issue **a lot** of SetPrinterData
8308 * when connecting to a printer --jerry
8311 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
8313 DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
8314 status = WERR_ACCESS_DENIED;
8315 goto done;
8318 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8319 if (!W_ERROR_IS_OK(status))
8320 return status;
8322 unistr2_to_ascii(valuename, value, sizeof(valuename));
8325 * When client side code sets a magic printer data key, detect it and save
8326 * the current printer data and the magic key's data (its the DEVMODE) for
8327 * future printer/driver initializations.
8329 if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
8331 /* Set devmode and printer initialization info */
8332 status = save_driver_init( printer, 2, data, real_len );
8334 srv_spoolss_reset_printerdata( printer->info_2->drivername );
8336 else
8338 status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
8339 type, data, real_len );
8340 if ( W_ERROR_IS_OK(status) )
8341 status = mod_a_printer(printer, 2);
8344 done:
8345 free_a_printer(&printer, 2);
8347 return status;
8350 /****************************************************************************
8351 ****************************************************************************/
8353 WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
8355 POLICY_HND *handle = &q_u->handle;
8356 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8357 int snum;
8359 DEBUG(5,("_spoolss_resetprinter\n"));
8362 * All we do is to check to see if the handle and queue is valid.
8363 * This call really doesn't mean anything to us because we only
8364 * support RAW printing. --jerry
8367 if (!Printer) {
8368 DEBUG(2,("_spoolss_resetprinter: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8369 return WERR_BADFID;
8372 if (!get_printer_snum(p,handle, &snum, NULL))
8373 return WERR_BADFID;
8376 /* blindly return success */
8377 return WERR_OK;
8381 /****************************************************************************
8382 ****************************************************************************/
8384 WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
8386 POLICY_HND *handle = &q_u->handle;
8387 UNISTR2 *value = &q_u->valuename;
8389 NT_PRINTER_INFO_LEVEL *printer = NULL;
8390 int snum=0;
8391 WERROR status = WERR_OK;
8392 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
8393 char *valuename = NULL;
8394 TALLOC_CTX *ctx = p->mem_ctx;
8396 DEBUG(5,("spoolss_deleteprinterdata\n"));
8398 if (!Printer) {
8399 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8400 return WERR_BADFID;
8403 if (!get_printer_snum(p, handle, &snum, NULL))
8404 return WERR_BADFID;
8406 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
8407 DEBUG(3, ("_spoolss_deleteprinterdata: printer properties change denied by handle\n"));
8408 return WERR_ACCESS_DENIED;
8411 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8412 if (!W_ERROR_IS_OK(status))
8413 return status;
8415 valuename = unistr2_to_ascii_talloc(ctx, value);
8416 if (!valuename) {
8417 free_a_printer(&printer, 2);
8418 return WERR_NOMEM;
8421 status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
8423 if ( W_ERROR_IS_OK(status) )
8424 mod_a_printer( printer, 2 );
8426 free_a_printer(&printer, 2);
8427 TALLOC_FREE(valuename);
8429 return status;
8432 /****************************************************************************
8433 ****************************************************************************/
8435 WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
8437 POLICY_HND *handle = &q_u->handle;
8438 FORM *form = &q_u->form;
8439 nt_forms_struct tmpForm;
8440 int snum;
8441 WERROR status = WERR_OK;
8442 NT_PRINTER_INFO_LEVEL *printer = NULL;
8444 int count=0;
8445 nt_forms_struct *list=NULL;
8446 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8448 DEBUG(5,("spoolss_addform\n"));
8450 if (!Printer) {
8451 DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8452 return WERR_BADFID;
8456 /* forms can be added on printer of on the print server handle */
8458 if ( Printer->printer_type == SPLHND_PRINTER )
8460 if (!get_printer_snum(p,handle, &snum, NULL))
8461 return WERR_BADFID;
8463 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8464 if (!W_ERROR_IS_OK(status))
8465 goto done;
8468 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8469 DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
8470 status = WERR_ACCESS_DENIED;
8471 goto done;
8474 /* can't add if builtin */
8476 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8477 status = WERR_ALREADY_EXISTS;
8478 goto done;
8481 count = get_ntforms(&list);
8483 if(!add_a_form(&list, form, &count)) {
8484 status = WERR_NOMEM;
8485 goto done;
8488 write_ntforms(&list, count);
8491 * ChangeID must always be set if this is a printer
8494 if ( Printer->printer_type == SPLHND_PRINTER )
8495 status = mod_a_printer(printer, 2);
8497 done:
8498 if ( printer )
8499 free_a_printer(&printer, 2);
8500 SAFE_FREE(list);
8502 return status;
8505 /****************************************************************************
8506 ****************************************************************************/
8508 WERROR _spoolss_deleteform( pipes_struct *p, SPOOL_Q_DELETEFORM *q_u, SPOOL_R_DELETEFORM *r_u)
8510 POLICY_HND *handle = &q_u->handle;
8511 UNISTR2 *form_name = &q_u->name;
8512 nt_forms_struct tmpForm;
8513 int count=0;
8514 nt_forms_struct *list=NULL;
8515 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8516 int snum;
8517 WERROR status = WERR_OK;
8518 NT_PRINTER_INFO_LEVEL *printer = NULL;
8520 DEBUG(5,("spoolss_deleteform\n"));
8522 if (!Printer) {
8523 DEBUG(2,("_spoolss_deleteform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8524 return WERR_BADFID;
8527 /* forms can be deleted on printer of on the print server handle */
8529 if ( Printer->printer_type == SPLHND_PRINTER )
8531 if (!get_printer_snum(p,handle, &snum, NULL))
8532 return WERR_BADFID;
8534 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8535 if (!W_ERROR_IS_OK(status))
8536 goto done;
8539 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8540 DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
8541 status = WERR_ACCESS_DENIED;
8542 goto done;
8545 /* can't delete if builtin */
8547 if (get_a_builtin_ntform(form_name,&tmpForm)) {
8548 status = WERR_INVALID_PARAM;
8549 goto done;
8552 count = get_ntforms(&list);
8554 if ( !delete_a_form(&list, form_name, &count, &status ))
8555 goto done;
8558 * ChangeID must always be set if this is a printer
8561 if ( Printer->printer_type == SPLHND_PRINTER )
8562 status = mod_a_printer(printer, 2);
8564 done:
8565 if ( printer )
8566 free_a_printer(&printer, 2);
8567 SAFE_FREE(list);
8569 return status;
8572 /****************************************************************************
8573 ****************************************************************************/
8575 WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
8577 POLICY_HND *handle = &q_u->handle;
8578 FORM *form = &q_u->form;
8579 nt_forms_struct tmpForm;
8580 int snum;
8581 WERROR status = WERR_OK;
8582 NT_PRINTER_INFO_LEVEL *printer = NULL;
8584 int count=0;
8585 nt_forms_struct *list=NULL;
8586 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
8588 DEBUG(5,("spoolss_setform\n"));
8590 if (!Printer) {
8591 DEBUG(2,("_spoolss_setform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
8592 return WERR_BADFID;
8595 /* forms can be modified on printer of on the print server handle */
8597 if ( Printer->printer_type == SPLHND_PRINTER )
8599 if (!get_printer_snum(p,handle, &snum, NULL))
8600 return WERR_BADFID;
8602 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
8603 if (!W_ERROR_IS_OK(status))
8604 goto done;
8607 if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
8608 DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
8609 status = WERR_ACCESS_DENIED;
8610 goto done;
8613 /* can't set if builtin */
8614 if (get_a_builtin_ntform(&form->name,&tmpForm)) {
8615 status = WERR_INVALID_PARAM;
8616 goto done;
8619 count = get_ntforms(&list);
8620 update_a_form(&list, form, count);
8621 write_ntforms(&list, count);
8624 * ChangeID must always be set if this is a printer
8627 if ( Printer->printer_type == SPLHND_PRINTER )
8628 status = mod_a_printer(printer, 2);
8631 done:
8632 if ( printer )
8633 free_a_printer(&printer, 2);
8634 SAFE_FREE(list);
8636 return status;
8639 /****************************************************************************
8640 enumprintprocessors level 1.
8641 ****************************************************************************/
8643 static WERROR enumprintprocessors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8645 PRINTPROCESSOR_1 *info_1=NULL;
8646 WERROR result = WERR_OK;
8648 if((info_1 = SMB_MALLOC_P(PRINTPROCESSOR_1)) == NULL)
8649 return WERR_NOMEM;
8651 (*returned) = 0x1;
8653 init_unistr(&info_1->name, "winprint");
8655 *needed += spoolss_size_printprocessor_info_1(info_1);
8657 if (*needed > offered) {
8658 result = WERR_INSUFFICIENT_BUFFER;
8659 goto out;
8662 if (!rpcbuf_alloc_size(buffer, *needed)) {
8663 result = WERR_NOMEM;
8664 goto out;
8667 smb_io_printprocessor_info_1("", buffer, info_1, 0);
8669 out:
8670 SAFE_FREE(info_1);
8672 if ( !W_ERROR_IS_OK(result) )
8673 *returned = 0;
8675 return result;
8678 /****************************************************************************
8679 ****************************************************************************/
8681 WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
8683 uint32 level = q_u->level;
8684 RPC_BUFFER *buffer = NULL;
8685 uint32 offered = q_u->offered;
8686 uint32 *needed = &r_u->needed;
8687 uint32 *returned = &r_u->returned;
8689 /* that's an [in out] buffer */
8691 if (!q_u->buffer && (offered!=0)) {
8692 return WERR_INVALID_PARAM;
8695 rpcbuf_move(q_u->buffer, &r_u->buffer);
8696 buffer = r_u->buffer;
8698 DEBUG(5,("spoolss_enumprintprocessors\n"));
8701 * Enumerate the print processors ...
8703 * Just reply with "winprint", to keep NT happy
8704 * and I can use my nice printer checker.
8707 *returned=0;
8708 *needed=0;
8710 switch (level) {
8711 case 1:
8712 return enumprintprocessors_level_1(buffer, offered, needed, returned);
8713 default:
8714 return WERR_UNKNOWN_LEVEL;
8718 /****************************************************************************
8719 enumprintprocdatatypes level 1.
8720 ****************************************************************************/
8722 static WERROR enumprintprocdatatypes_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8724 PRINTPROCDATATYPE_1 *info_1=NULL;
8725 WERROR result = WERR_OK;
8727 if((info_1 = SMB_MALLOC_P(PRINTPROCDATATYPE_1)) == NULL)
8728 return WERR_NOMEM;
8730 (*returned) = 0x1;
8732 init_unistr(&info_1->name, "RAW");
8734 *needed += spoolss_size_printprocdatatype_info_1(info_1);
8736 if (*needed > offered) {
8737 result = WERR_INSUFFICIENT_BUFFER;
8738 goto out;
8741 if (!rpcbuf_alloc_size(buffer, *needed)) {
8742 result = WERR_NOMEM;
8743 goto out;
8746 smb_io_printprocdatatype_info_1("", buffer, info_1, 0);
8748 out:
8749 SAFE_FREE(info_1);
8751 if ( !W_ERROR_IS_OK(result) )
8752 *returned = 0;
8754 return result;
8757 /****************************************************************************
8758 ****************************************************************************/
8760 WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
8762 uint32 level = q_u->level;
8763 RPC_BUFFER *buffer = NULL;
8764 uint32 offered = q_u->offered;
8765 uint32 *needed = &r_u->needed;
8766 uint32 *returned = &r_u->returned;
8768 /* that's an [in out] buffer */
8770 if (!q_u->buffer && (offered!=0)) {
8771 return WERR_INVALID_PARAM;
8774 rpcbuf_move(q_u->buffer, &r_u->buffer);
8775 buffer = r_u->buffer;
8777 DEBUG(5,("_spoolss_enumprintprocdatatypes\n"));
8779 *returned=0;
8780 *needed=0;
8782 switch (level) {
8783 case 1:
8784 return enumprintprocdatatypes_level_1(buffer, offered, needed, returned);
8785 default:
8786 return WERR_UNKNOWN_LEVEL;
8790 /****************************************************************************
8791 enumprintmonitors level 1.
8792 ****************************************************************************/
8794 static WERROR enumprintmonitors_level_1(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8796 PRINTMONITOR_1 *info_1;
8797 WERROR result = WERR_OK;
8798 int i;
8800 if((info_1 = SMB_MALLOC_ARRAY(PRINTMONITOR_1, 2)) == NULL)
8801 return WERR_NOMEM;
8803 *returned = 2;
8805 init_unistr(&(info_1[0].name), SPL_LOCAL_PORT );
8806 init_unistr(&(info_1[1].name), SPL_TCPIP_PORT );
8808 for ( i=0; i<*returned; i++ ) {
8809 *needed += spoolss_size_printmonitor_info_1(&info_1[i]);
8812 if (*needed > offered) {
8813 result = WERR_INSUFFICIENT_BUFFER;
8814 goto out;
8817 if (!rpcbuf_alloc_size(buffer, *needed)) {
8818 result = WERR_NOMEM;
8819 goto out;
8822 for ( i=0; i<*returned; i++ ) {
8823 smb_io_printmonitor_info_1("", buffer, &info_1[i], 0);
8826 out:
8827 SAFE_FREE(info_1);
8829 if ( !W_ERROR_IS_OK(result) )
8830 *returned = 0;
8832 return result;
8835 /****************************************************************************
8836 enumprintmonitors level 2.
8837 ****************************************************************************/
8839 static WERROR enumprintmonitors_level_2(RPC_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)
8841 PRINTMONITOR_2 *info_2;
8842 WERROR result = WERR_OK;
8843 int i;
8845 if((info_2 = SMB_MALLOC_ARRAY(PRINTMONITOR_2, 2)) == NULL)
8846 return WERR_NOMEM;
8848 *returned = 2;
8850 init_unistr( &(info_2[0].name), SPL_LOCAL_PORT );
8851 init_unistr( &(info_2[0].environment), "Windows NT X86" );
8852 init_unistr( &(info_2[0].dll_name), "localmon.dll" );
8854 init_unistr( &(info_2[1].name), SPL_TCPIP_PORT );
8855 init_unistr( &(info_2[1].environment), "Windows NT X86" );
8856 init_unistr( &(info_2[1].dll_name), "tcpmon.dll" );
8858 for ( i=0; i<*returned; i++ ) {
8859 *needed += spoolss_size_printmonitor_info_2(&info_2[i]);
8862 if (*needed > offered) {
8863 result = WERR_INSUFFICIENT_BUFFER;
8864 goto out;
8867 if (!rpcbuf_alloc_size(buffer, *needed)) {
8868 result = WERR_NOMEM;
8869 goto out;
8872 for ( i=0; i<*returned; i++ ) {
8873 smb_io_printmonitor_info_2("", buffer, &info_2[i], 0);
8876 out:
8877 SAFE_FREE(info_2);
8879 if ( !W_ERROR_IS_OK(result) )
8880 *returned = 0;
8882 return result;
8885 /****************************************************************************
8886 ****************************************************************************/
8888 WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
8890 uint32 level = q_u->level;
8891 RPC_BUFFER *buffer = NULL;
8892 uint32 offered = q_u->offered;
8893 uint32 *needed = &r_u->needed;
8894 uint32 *returned = &r_u->returned;
8896 /* that's an [in out] buffer */
8898 if (!q_u->buffer && (offered!=0)) {
8899 return WERR_INVALID_PARAM;
8902 rpcbuf_move(q_u->buffer, &r_u->buffer);
8903 buffer = r_u->buffer;
8905 DEBUG(5,("spoolss_enumprintmonitors\n"));
8908 * Enumerate the print monitors ...
8910 * Just reply with "Local Port", to keep NT happy
8911 * and I can use my nice printer checker.
8914 *returned=0;
8915 *needed=0;
8917 switch (level) {
8918 case 1:
8919 return enumprintmonitors_level_1(buffer, offered, needed, returned);
8920 case 2:
8921 return enumprintmonitors_level_2(buffer, offered, needed, returned);
8922 default:
8923 return WERR_UNKNOWN_LEVEL;
8927 /****************************************************************************
8928 ****************************************************************************/
8930 static WERROR getjob_level_1(print_queue_struct **queue, int count, int snum,
8931 NT_PRINTER_INFO_LEVEL *ntprinter,
8932 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8933 uint32 *needed)
8935 int i=0;
8936 bool found=False;
8937 JOB_INFO_1 *info_1=NULL;
8938 WERROR result = WERR_OK;
8940 info_1=SMB_MALLOC_P(JOB_INFO_1);
8942 if (info_1 == NULL) {
8943 return WERR_NOMEM;
8946 for (i=0; i<count && found==False; i++) {
8947 if ((*queue)[i].job==(int)jobid)
8948 found=True;
8951 if (found==False) {
8952 SAFE_FREE(info_1);
8953 /* NT treats not found as bad param... yet another bad choice */
8954 return WERR_INVALID_PARAM;
8957 fill_job_info_1( info_1, &((*queue)[i-1]), i, snum, ntprinter );
8959 *needed += spoolss_size_job_info_1(info_1);
8961 if (*needed > offered) {
8962 result = WERR_INSUFFICIENT_BUFFER;
8963 goto out;
8966 if (!rpcbuf_alloc_size(buffer, *needed)) {
8967 result = WERR_NOMEM;
8968 goto out;
8971 smb_io_job_info_1("", buffer, info_1, 0);
8973 out:
8974 SAFE_FREE(info_1);
8976 return result;
8979 /****************************************************************************
8980 ****************************************************************************/
8982 static WERROR getjob_level_2(print_queue_struct **queue, int count, int snum,
8983 NT_PRINTER_INFO_LEVEL *ntprinter,
8984 uint32 jobid, RPC_BUFFER *buffer, uint32 offered,
8985 uint32 *needed)
8987 int i = 0;
8988 bool found = False;
8989 JOB_INFO_2 *info_2;
8990 WERROR result;
8991 DEVICEMODE *devmode = NULL;
8992 NT_DEVICEMODE *nt_devmode = NULL;
8994 if ( !(info_2=SMB_MALLOC_P(JOB_INFO_2)) )
8995 return WERR_NOMEM;
8997 ZERO_STRUCTP(info_2);
8999 for ( i=0; i<count && found==False; i++ )
9001 if ((*queue)[i].job == (int)jobid)
9002 found = True;
9005 if ( !found ) {
9006 /* NT treats not found as bad param... yet another bad
9007 choice */
9008 result = WERR_INVALID_PARAM;
9009 goto done;
9013 * if the print job does not have a DEVMODE associated with it,
9014 * just use the one for the printer. A NULL devicemode is not
9015 * a failure condition
9018 if ( !(nt_devmode=print_job_devmode( lp_const_servicename(snum), jobid )) )
9019 devmode = construct_dev_mode(lp_const_servicename(snum));
9020 else {
9021 if ((devmode = SMB_MALLOC_P(DEVICEMODE)) != NULL) {
9022 ZERO_STRUCTP( devmode );
9023 convert_nt_devicemode( devmode, nt_devmode );
9027 fill_job_info_2(info_2, &((*queue)[i-1]), i, snum, ntprinter, devmode);
9029 *needed += spoolss_size_job_info_2(info_2);
9031 if (*needed > offered) {
9032 result = WERR_INSUFFICIENT_BUFFER;
9033 goto done;
9036 if (!rpcbuf_alloc_size(buffer, *needed)) {
9037 result = WERR_NOMEM;
9038 goto done;
9041 smb_io_job_info_2("", buffer, info_2, 0);
9043 result = WERR_OK;
9045 done:
9046 /* Cleanup allocated memory */
9048 free_job_info_2(info_2); /* Also frees devmode */
9049 SAFE_FREE(info_2);
9051 return result;
9054 /****************************************************************************
9055 ****************************************************************************/
9057 WERROR _spoolss_getjob( pipes_struct *p, SPOOL_Q_GETJOB *q_u, SPOOL_R_GETJOB *r_u)
9059 POLICY_HND *handle = &q_u->handle;
9060 uint32 jobid = q_u->jobid;
9061 uint32 level = q_u->level;
9062 RPC_BUFFER *buffer = NULL;
9063 uint32 offered = q_u->offered;
9064 uint32 *needed = &r_u->needed;
9065 WERROR wstatus = WERR_OK;
9066 NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
9067 int snum;
9068 int count;
9069 print_queue_struct *queue = NULL;
9070 print_status_struct prt_status;
9072 /* that's an [in out] buffer */
9074 if (!q_u->buffer && (offered!=0)) {
9075 return WERR_INVALID_PARAM;
9078 rpcbuf_move(q_u->buffer, &r_u->buffer);
9079 buffer = r_u->buffer;
9081 DEBUG(5,("spoolss_getjob\n"));
9083 *needed = 0;
9085 if (!get_printer_snum(p, handle, &snum, NULL))
9086 return WERR_BADFID;
9088 wstatus = get_a_printer(NULL, &ntprinter, 2, lp_servicename(snum));
9089 if ( !W_ERROR_IS_OK(wstatus) )
9090 return wstatus;
9092 count = print_queue_status(snum, &queue, &prt_status);
9094 DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
9095 count, prt_status.status, prt_status.message));
9097 switch ( level ) {
9098 case 1:
9099 wstatus = getjob_level_1(&queue, count, snum, ntprinter, jobid,
9100 buffer, offered, needed);
9101 break;
9102 case 2:
9103 wstatus = getjob_level_2(&queue, count, snum, ntprinter, jobid,
9104 buffer, offered, needed);
9105 break;
9106 default:
9107 wstatus = WERR_UNKNOWN_LEVEL;
9108 break;
9111 SAFE_FREE(queue);
9112 free_a_printer( &ntprinter, 2 );
9114 return wstatus;
9117 /********************************************************************
9118 spoolss_getprinterdataex
9120 From MSDN documentation of GetPrinterDataEx: pass request
9121 to GetPrinterData if key is "PrinterDriverData".
9122 ********************************************************************/
9124 WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
9126 POLICY_HND *handle = &q_u->handle;
9127 uint32 in_size = q_u->size;
9128 uint32 *type = &r_u->type;
9129 uint32 *out_size = &r_u->size;
9130 uint8 **data = &r_u->data;
9131 uint32 *needed = &r_u->needed;
9132 fstring keyname, valuename;
9134 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9136 NT_PRINTER_INFO_LEVEL *printer = NULL;
9137 int snum = 0;
9138 WERROR status = WERR_OK;
9140 DEBUG(4,("_spoolss_getprinterdataex\n"));
9142 unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname));
9143 unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename));
9145 DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
9146 keyname, valuename));
9148 /* in case of problem, return some default values */
9150 *needed = 0;
9151 *type = 0;
9152 *out_size = in_size;
9154 if (!Printer) {
9155 DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9156 status = WERR_BADFID;
9157 goto done;
9160 /* Is the handle to a printer or to the server? */
9162 if (Printer->printer_type == SPLHND_SERVER) {
9163 DEBUG(10,("_spoolss_getprinterdataex: Not implemented for server handles yet\n"));
9164 status = WERR_INVALID_PARAM;
9165 goto done;
9168 if ( !get_printer_snum(p,handle, &snum, NULL) )
9169 return WERR_BADFID;
9171 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9172 if ( !W_ERROR_IS_OK(status) )
9173 goto done;
9175 /* check to see if the keyname is valid */
9176 if ( !strlen(keyname) ) {
9177 status = WERR_INVALID_PARAM;
9178 goto done;
9181 if ( lookup_printerkey( printer->info_2->data, keyname ) == -1 ) {
9182 DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
9183 free_a_printer( &printer, 2 );
9184 status = WERR_BADFILE;
9185 goto done;
9188 /* When given a new keyname, we should just create it */
9190 status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
9192 if (*needed > *out_size)
9193 status = WERR_MORE_DATA;
9195 done:
9196 if ( !W_ERROR_IS_OK(status) )
9198 DEBUG(5, ("error: allocating %d\n", *out_size));
9200 /* reply this param doesn't exist */
9202 if ( *out_size )
9204 if( (*data=(uint8 *)TALLOC_ZERO(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
9205 status = WERR_NOMEM;
9206 goto done;
9208 } else {
9209 *data = NULL;
9213 if ( printer )
9214 free_a_printer( &printer, 2 );
9216 return status;
9219 /********************************************************************
9220 * spoolss_setprinterdataex
9221 ********************************************************************/
9223 WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
9225 POLICY_HND *handle = &q_u->handle;
9226 uint32 type = q_u->type;
9227 uint8 *data = q_u->data;
9228 uint32 real_len = q_u->real_len;
9230 NT_PRINTER_INFO_LEVEL *printer = NULL;
9231 int snum = 0;
9232 WERROR status = WERR_OK;
9233 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9234 fstring valuename;
9235 fstring keyname;
9236 char *oid_string;
9238 DEBUG(4,("_spoolss_setprinterdataex\n"));
9240 /* From MSDN documentation of SetPrinterDataEx: pass request to
9241 SetPrinterData if key is "PrinterDriverData" */
9243 if (!Printer) {
9244 DEBUG(2,("_spoolss_setprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9245 return WERR_BADFID;
9248 if ( Printer->printer_type == SPLHND_SERVER ) {
9249 DEBUG(10,("_spoolss_setprinterdataex: Not implemented for server handles yet\n"));
9250 return WERR_INVALID_PARAM;
9253 if ( !get_printer_snum(p,handle, &snum, NULL) )
9254 return WERR_BADFID;
9257 * Access check : NT returns "access denied" if you make a
9258 * SetPrinterData call without the necessary privildge.
9259 * we were originally returning OK if nothing changed
9260 * which made Win2k issue **a lot** of SetPrinterData
9261 * when connecting to a printer --jerry
9264 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
9266 DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
9267 return WERR_ACCESS_DENIED;
9270 status = get_a_printer(Printer, &printer, 2, lp_servicename(snum));
9271 if (!W_ERROR_IS_OK(status))
9272 return status;
9274 unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename));
9275 unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname));
9277 /* check for OID in valuename */
9279 if ( (oid_string = strchr( valuename, ',' )) != NULL )
9281 *oid_string = '\0';
9282 oid_string++;
9285 /* save the registry data */
9287 status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
9289 if ( W_ERROR_IS_OK(status) )
9291 /* save the OID if one was specified */
9292 if ( oid_string ) {
9293 fstrcat( keyname, "\\" );
9294 fstrcat( keyname, SPOOL_OID_KEY );
9297 * I'm not checking the status here on purpose. Don't know
9298 * if this is right, but I'm returning the status from the
9299 * previous set_printer_dataex() call. I have no idea if
9300 * this is right. --jerry
9303 set_printer_dataex( printer, keyname, valuename,
9304 REG_SZ, (uint8 *)oid_string,
9305 strlen(oid_string)+1 );
9308 status = mod_a_printer(printer, 2);
9311 free_a_printer(&printer, 2);
9313 return status;
9317 /********************************************************************
9318 * spoolss_deleteprinterdataex
9319 ********************************************************************/
9321 WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
9323 POLICY_HND *handle = &q_u->handle;
9324 UNISTR2 *value = &q_u->valuename;
9325 UNISTR2 *key = &q_u->keyname;
9327 NT_PRINTER_INFO_LEVEL *printer = NULL;
9328 int snum=0;
9329 WERROR status = WERR_OK;
9330 Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
9331 char *valuename = NULL;
9332 char *keyname = NULL;
9333 TALLOC_CTX *ctx = p->mem_ctx;
9335 DEBUG(5,("spoolss_deleteprinterdataex\n"));
9337 if (!Printer) {
9338 DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9339 return WERR_BADFID;
9342 if (!get_printer_snum(p, handle, &snum, NULL))
9343 return WERR_BADFID;
9345 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9346 DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
9347 return WERR_ACCESS_DENIED;
9350 valuename = unistr2_to_ascii_talloc(ctx, value);
9351 keyname = unistr2_to_ascii_talloc(ctx, key);
9352 if (!valuename || !keyname) {
9353 return WERR_NOMEM;
9356 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9357 if (!W_ERROR_IS_OK(status))
9358 return status;
9360 status = delete_printer_dataex( printer, keyname, valuename );
9362 if ( W_ERROR_IS_OK(status) )
9363 mod_a_printer( printer, 2 );
9365 free_a_printer(&printer, 2);
9367 return status;
9370 /********************************************************************
9371 * spoolss_enumprinterkey
9372 ********************************************************************/
9375 WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
9377 fstring key;
9378 fstring *keynames = NULL;
9379 uint16 *enumkeys = NULL;
9380 int num_keys;
9381 int printerkey_len;
9382 POLICY_HND *handle = &q_u->handle;
9383 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9384 NT_PRINTER_DATA *data;
9385 NT_PRINTER_INFO_LEVEL *printer = NULL;
9386 int snum = 0;
9387 WERROR status = WERR_BADFILE;
9390 DEBUG(4,("_spoolss_enumprinterkey\n"));
9392 if (!Printer) {
9393 DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9394 return WERR_BADFID;
9397 if ( !get_printer_snum(p,handle, &snum, NULL) )
9398 return WERR_BADFID;
9400 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9401 if (!W_ERROR_IS_OK(status))
9402 return status;
9404 /* get the list of subkey names */
9406 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9407 data = printer->info_2->data;
9409 num_keys = get_printer_subkeys( data, key, &keynames );
9411 if ( num_keys == -1 ) {
9412 status = WERR_BADFILE;
9413 goto done;
9416 printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
9418 r_u->needed = printerkey_len*2;
9420 if ( q_u->size < r_u->needed ) {
9421 status = WERR_MORE_DATA;
9422 goto done;
9425 if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
9426 status = WERR_NOMEM;
9427 goto done;
9430 status = WERR_OK;
9432 if ( q_u->size < r_u->needed )
9433 status = WERR_MORE_DATA;
9435 done:
9436 free_a_printer( &printer, 2 );
9437 SAFE_FREE( keynames );
9439 return status;
9442 /********************************************************************
9443 * spoolss_deleteprinterkey
9444 ********************************************************************/
9446 WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
9448 POLICY_HND *handle = &q_u->handle;
9449 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9450 fstring key;
9451 NT_PRINTER_INFO_LEVEL *printer = NULL;
9452 int snum=0;
9453 WERROR status;
9455 DEBUG(5,("spoolss_deleteprinterkey\n"));
9457 if (!Printer) {
9458 DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
9459 return WERR_BADFID;
9462 /* if keyname == NULL, return error */
9464 if ( !q_u->keyname.buffer )
9465 return WERR_INVALID_PARAM;
9467 if (!get_printer_snum(p, handle, &snum, NULL))
9468 return WERR_BADFID;
9470 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
9471 DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
9472 return WERR_ACCESS_DENIED;
9475 status = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9476 if (!W_ERROR_IS_OK(status))
9477 return status;
9479 /* delete the key and all subneys */
9481 unistr2_to_ascii(key, &q_u->keyname, sizeof(key));
9483 status = delete_all_printer_data( printer->info_2, key );
9485 if ( W_ERROR_IS_OK(status) )
9486 status = mod_a_printer(printer, 2);
9488 free_a_printer( &printer, 2 );
9490 return status;
9494 /********************************************************************
9495 * spoolss_enumprinterdataex
9496 ********************************************************************/
9498 WERROR _spoolss_enumprinterdataex(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATAEX *q_u, SPOOL_R_ENUMPRINTERDATAEX *r_u)
9500 POLICY_HND *handle = &q_u->handle;
9501 uint32 in_size = q_u->size;
9502 uint32 num_entries,
9503 needed;
9504 NT_PRINTER_INFO_LEVEL *printer = NULL;
9505 PRINTER_ENUM_VALUES *enum_values = NULL;
9506 NT_PRINTER_DATA *p_data;
9507 fstring key;
9508 Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
9509 int snum;
9510 WERROR result;
9511 int key_index;
9512 int i;
9513 REGISTRY_VALUE *val;
9514 char *value_name;
9515 uint32 data_len;
9518 DEBUG(4,("_spoolss_enumprinterdataex\n"));
9520 if (!Printer) {
9521 DEBUG(2,("_spoolss_enumprinterdataex: Invalid handle (%s:%u:%u1<).\n", OUR_HANDLE(handle)));
9522 return WERR_BADFID;
9526 * first check for a keyname of NULL or "". Win2k seems to send
9527 * this a lot and we should send back WERR_INVALID_PARAM
9528 * no need to spend time looking up the printer in this case.
9529 * --jerry
9532 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9533 if ( !strlen(key) ) {
9534 result = WERR_INVALID_PARAM;
9535 goto done;
9538 /* get the printer off of disk */
9540 if (!get_printer_snum(p,handle, &snum, NULL))
9541 return WERR_BADFID;
9543 ZERO_STRUCT(printer);
9544 result = get_a_printer(Printer, &printer, 2, lp_const_servicename(snum));
9545 if (!W_ERROR_IS_OK(result))
9546 return result;
9548 /* now look for a match on the key name */
9550 p_data = printer->info_2->data;
9552 unistr2_to_ascii(key, &q_u->key, sizeof(key));
9553 if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
9555 DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
9556 result = WERR_INVALID_PARAM;
9557 goto done;
9560 result = WERR_OK;
9561 needed = 0;
9563 /* allocate the memory for the array of pointers -- if necessary */
9565 num_entries = regval_ctr_numvals( p_data->keys[key_index].values );
9566 if ( num_entries )
9568 if ( (enum_values=TALLOC_ARRAY(p->mem_ctx, PRINTER_ENUM_VALUES, num_entries)) == NULL )
9570 DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%lu] bytes!\n",
9571 (unsigned long)num_entries*sizeof(PRINTER_ENUM_VALUES)));
9572 result = WERR_NOMEM;
9573 goto done;
9576 memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
9580 * loop through all params and build the array to pass
9581 * back to the client
9584 for ( i=0; i<num_entries; i++ )
9586 /* lookup the registry value */
9588 val = regval_ctr_specific_value( p_data->keys[key_index].values, i );
9589 DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
9591 /* copy the data */
9593 value_name = regval_name( val );
9594 init_unistr( &enum_values[i].valuename, value_name );
9595 enum_values[i].value_len = (strlen(value_name)+1) * 2;
9596 enum_values[i].type = regval_type( val );
9598 data_len = regval_size( val );
9599 if ( data_len ) {
9600 if ( !(enum_values[i].data = (uint8 *)TALLOC_MEMDUP(p->mem_ctx, regval_data_p(val), data_len)) )
9602 DEBUG(0,("TALLOC_MEMDUP failed to allocate memory [data_len=%d] for data!\n",
9603 data_len ));
9604 result = WERR_NOMEM;
9605 goto done;
9608 enum_values[i].data_len = data_len;
9610 /* keep track of the size of the array in bytes */
9612 needed += spoolss_size_printer_enum_values(&enum_values[i]);
9615 /* housekeeping information in the reply */
9617 /* Fix from Martin Zielinski <mz@seh.de> - ensure
9618 * the hand marshalled container size is a multiple
9619 * of 4 bytes for RPC alignment.
9622 if (needed % 4) {
9623 needed += 4-(needed % 4);
9626 r_u->needed = needed;
9627 r_u->returned = num_entries;
9629 if (needed > in_size) {
9630 result = WERR_MORE_DATA;
9631 goto done;
9634 /* copy data into the reply */
9636 /* mz: Vista x64 returns 0x6f7 (The stub received bad data), if the
9637 response buffer size is != the offered buffer size
9639 r_u->ctr.size = r_u->needed;
9641 r_u->ctr.size = in_size;
9643 r_u->ctr.size_of_array = r_u->returned;
9644 r_u->ctr.values = enum_values;
9646 done:
9647 if ( printer )
9648 free_a_printer(&printer, 2);
9650 return result;
9653 /****************************************************************************
9654 ****************************************************************************/
9656 static void fill_printprocessordirectory_1(PRINTPROCESSOR_DIRECTORY_1 *info, const char *name)
9658 init_unistr(&info->name, name);
9661 static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,
9662 UNISTR2 *environment,
9663 RPC_BUFFER *buffer,
9664 uint32 offered,
9665 uint32 *needed)
9667 char *long_archi = NULL;
9668 PRINTPROCESSOR_DIRECTORY_1 *info=NULL;
9669 WERROR result = WERR_OK;
9670 TALLOC_CTX *ctx = talloc_tos();
9672 long_archi = unistr2_to_ascii_talloc(ctx, environment);
9673 if (!long_archi) {
9674 return WERR_NOMEM;
9677 if (!get_short_archi(long_archi))
9678 return WERR_INVALID_ENVIRONMENT;
9680 if((info=SMB_MALLOC_P(PRINTPROCESSOR_DIRECTORY_1)) == NULL)
9681 return WERR_NOMEM;
9683 fill_printprocessordirectory_1(info, "C:\\WINNT\\System32\\spool\\PRTPROCS\\W32X86");
9685 *needed += spoolss_size_printprocessordirectory_info_1(info);
9687 if (*needed > offered) {
9688 result = WERR_INSUFFICIENT_BUFFER;
9689 goto out;
9692 if (!rpcbuf_alloc_size(buffer, *needed)) {
9693 result = WERR_INSUFFICIENT_BUFFER;
9694 goto out;
9697 smb_io_printprocessordirectory_1("", buffer, info, 0);
9699 out:
9700 SAFE_FREE(info);
9702 return result;
9705 WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROCESSORDIRECTORY *q_u, SPOOL_R_GETPRINTPROCESSORDIRECTORY *r_u)
9707 uint32 level = q_u->level;
9708 RPC_BUFFER *buffer = NULL;
9709 uint32 offered = q_u->offered;
9710 uint32 *needed = &r_u->needed;
9711 WERROR result;
9713 /* that's an [in out] buffer */
9715 if (!q_u->buffer && (offered!=0)) {
9716 return WERR_INVALID_PARAM;
9719 rpcbuf_move(q_u->buffer, &r_u->buffer);
9720 buffer = r_u->buffer;
9722 DEBUG(5,("_spoolss_getprintprocessordirectory\n"));
9724 *needed=0;
9726 switch(level) {
9727 case 1:
9728 result = getprintprocessordirectory_level_1
9729 (&q_u->name, &q_u->environment, buffer, offered, needed);
9730 break;
9731 default:
9732 result = WERR_UNKNOWN_LEVEL;
9735 return result;
9738 /*******************************************************************
9739 Streams the monitor UI DLL name in UNICODE
9740 *******************************************************************/
9742 static WERROR xcvtcp_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9743 RPC_BUFFER *out, uint32 *needed )
9745 const char *dllname = "tcpmonui.dll";
9747 *needed = (strlen(dllname)+1) * 2;
9749 if ( rpcbuf_get_size(out) < *needed ) {
9750 return WERR_INSUFFICIENT_BUFFER;
9753 if ( !make_monitorui_buf( out, dllname ) ) {
9754 return WERR_NOMEM;
9757 return WERR_OK;
9760 /*******************************************************************
9761 Create a new TCP/IP port
9762 *******************************************************************/
9764 static WERROR xcvtcp_addport( NT_USER_TOKEN *token, RPC_BUFFER *in,
9765 RPC_BUFFER *out, uint32 *needed )
9767 NT_PORT_DATA_1 port1;
9768 TALLOC_CTX *ctx = talloc_tos();
9769 char *device_uri = NULL;
9771 ZERO_STRUCT( port1 );
9773 /* convert to our internal port data structure */
9775 if ( !convert_port_data_1( &port1, in ) ) {
9776 return WERR_NOMEM;
9779 /* create the device URI and call the add_port_hook() */
9781 switch ( port1.protocol ) {
9782 case PORT_PROTOCOL_DIRECT:
9783 device_uri = talloc_asprintf(ctx,
9784 "socket://%s:%d/", port1.hostaddr, port1.port );
9785 break;
9787 case PORT_PROTOCOL_LPR:
9788 device_uri = talloc_asprintf(ctx,
9789 "lpr://%s/%s", port1.hostaddr, port1.queue );
9790 break;
9792 default:
9793 return WERR_UNKNOWN_PORT;
9796 if (!device_uri) {
9797 return WERR_NOMEM;
9800 return add_port_hook(ctx, token, port1.name, device_uri );
9803 /*******************************************************************
9804 *******************************************************************/
9806 struct xcv_api_table xcvtcp_cmds[] = {
9807 { "MonitorUI", xcvtcp_monitorui },
9808 { "AddPort", xcvtcp_addport},
9809 { NULL, NULL }
9812 static WERROR process_xcvtcp_command( NT_USER_TOKEN *token, const char *command,
9813 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9814 uint32 *needed )
9816 int i;
9818 DEBUG(10,("process_xcvtcp_command: Received command \"%s\"\n", command));
9820 for ( i=0; xcvtcp_cmds[i].name; i++ ) {
9821 if ( strcmp( command, xcvtcp_cmds[i].name ) == 0 )
9822 return xcvtcp_cmds[i].fn( token, inbuf, outbuf, needed );
9825 return WERR_BADFUNC;
9828 /*******************************************************************
9829 *******************************************************************/
9830 #if 0 /* don't support management using the "Local Port" monitor */
9832 static WERROR xcvlocal_monitorui( NT_USER_TOKEN *token, RPC_BUFFER *in,
9833 RPC_BUFFER *out, uint32 *needed )
9835 const char *dllname = "localui.dll";
9837 *needed = (strlen(dllname)+1) * 2;
9839 if ( rpcbuf_get_size(out) < *needed ) {
9840 return WERR_INSUFFICIENT_BUFFER;
9843 if ( !make_monitorui_buf( out, dllname )) {
9844 return WERR_NOMEM;
9847 return WERR_OK;
9850 /*******************************************************************
9851 *******************************************************************/
9853 struct xcv_api_table xcvlocal_cmds[] = {
9854 { "MonitorUI", xcvlocal_monitorui },
9855 { NULL, NULL }
9857 #else
9858 struct xcv_api_table xcvlocal_cmds[] = {
9859 { NULL, NULL }
9861 #endif
9865 /*******************************************************************
9866 *******************************************************************/
9868 static WERROR process_xcvlocal_command( NT_USER_TOKEN *token, const char *command,
9869 RPC_BUFFER *inbuf, RPC_BUFFER *outbuf,
9870 uint32 *needed )
9872 int i;
9874 DEBUG(10,("process_xcvlocal_command: Received command \"%s\"\n", command));
9876 for ( i=0; xcvlocal_cmds[i].name; i++ ) {
9877 if ( strcmp( command, xcvlocal_cmds[i].name ) == 0 )
9878 return xcvlocal_cmds[i].fn( token, inbuf, outbuf , needed );
9880 return WERR_BADFUNC;
9883 /*******************************************************************
9884 *******************************************************************/
9886 WERROR _spoolss_xcvdataport(pipes_struct *p, SPOOL_Q_XCVDATAPORT *q_u, SPOOL_R_XCVDATAPORT *r_u)
9888 Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
9889 fstring command;
9891 if (!Printer) {
9892 DEBUG(2,("_spoolss_xcvdataport: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle)));
9893 return WERR_BADFID;
9896 /* Has to be a handle to the TCP/IP port monitor */
9898 if ( !(Printer->printer_type & (SPLHND_PORTMON_LOCAL|SPLHND_PORTMON_TCP)) ) {
9899 DEBUG(2,("_spoolss_xcvdataport: Call only valid for Port Monitors\n"));
9900 return WERR_BADFID;
9903 /* requires administrative access to the server */
9905 if ( !(Printer->access_granted & SERVER_ACCESS_ADMINISTER) ) {
9906 DEBUG(2,("_spoolss_xcvdataport: denied by handle permissions.\n"));
9907 return WERR_ACCESS_DENIED;
9910 /* Get the command name. There's numerous commands supported by the
9911 TCPMON interface. */
9913 rpcstr_pull(command, q_u->dataname.buffer, sizeof(command),
9914 q_u->dataname.uni_str_len*2, 0);
9916 /* Allocate the outgoing buffer */
9918 rpcbuf_init( &r_u->outdata, q_u->offered, p->mem_ctx );
9920 switch ( Printer->printer_type ) {
9921 case SPLHND_PORTMON_TCP:
9922 return process_xcvtcp_command( p->pipe_user.nt_user_token, command,
9923 &q_u->indata, &r_u->outdata, &r_u->needed );
9924 case SPLHND_PORTMON_LOCAL:
9925 return process_xcvlocal_command( p->pipe_user.nt_user_token, command,
9926 &q_u->indata, &r_u->outdata, &r_u->needed );
9929 return WERR_INVALID_PRINT_MONITOR;