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.
10 * Copyright (C) Guenther Deschner 2009.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 3 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <http://www.gnu.org/licenses/>.
26 /* Since the SPOOLSS rpc routines are basically DOS 16-bit calls wrapped
27 up, all the errors returned are DOS errors, not NT status codes. */
30 #include "../librpc/gen_ndr/srv_spoolss.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
33 /* macros stolen from s4 spoolss server */
34 #define SPOOLSS_BUFFER_UNION(fn,ic,info,level) \
35 ((info)?ndr_size_##fn(info, level, ic, 0):0)
37 #define SPOOLSS_BUFFER_UNION_ARRAY(mem_ctx,fn,ic,info,level,count) \
38 ((info)?ndr_size_##fn##_info(mem_ctx, ic, level, count, info):0)
40 #define SPOOLSS_BUFFER_ARRAY(mem_ctx,fn,ic,info,count) \
41 ((info)?ndr_size_##fn##_info(mem_ctx, ic, count, info):0)
43 #define SPOOLSS_BUFFER_OK(val_true,val_false) ((r->in.offered >= *r->out.needed)?val_true:val_false)
46 extern userdom_struct current_user_info;
49 #define DBGC_CLASS DBGC_RPC_SRV
51 #ifndef MAX_OPEN_PRINTER_EXS
52 #define MAX_OPEN_PRINTER_EXS 50
55 #define MAGIC_DISPLAY_FREQUENCY 0xfade2bad
56 #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_"
58 static Printer_entry *printers_list;
60 typedef struct _counter_printer_0 {
61 struct _counter_printer_0 *next;
62 struct _counter_printer_0 *prev;
68 static counter_printer_0 *counter_list;
70 static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/
71 static uint32_t smb_connections = 0;
74 /* in printing/nt_printing.c */
76 extern struct standard_mapping printer_std_mapping, printserver_std_mapping;
78 /* API table for Xcv Monitor functions */
80 struct xcv_api_table {
82 WERROR(*fn) (TALLOC_CTX *mem_ctx, NT_USER_TOKEN *token, DATA_BLOB *in, DATA_BLOB *out, uint32_t *needed);
85 /********************************************************************
86 * Canonicalize servername.
87 ********************************************************************/
89 static const char *canon_servername(const char *servername)
91 const char *pservername = servername;
92 while (*pservername == '\\') {
98 /* translate between internal status numbers and NT status numbers */
99 static int nt_printj_status(int v)
105 return JOB_STATUS_PAUSED;
107 return JOB_STATUS_SPOOLING;
109 return JOB_STATUS_PRINTING;
111 return JOB_STATUS_ERROR;
113 return JOB_STATUS_DELETING;
115 return JOB_STATUS_OFFLINE;
117 return JOB_STATUS_PAPEROUT;
119 return JOB_STATUS_PRINTED;
121 return JOB_STATUS_DELETED;
123 return JOB_STATUS_BLOCKED_DEVQ;
124 case LPQ_USER_INTERVENTION:
125 return JOB_STATUS_USER_INTERVENTION;
130 static int nt_printq_status(int v)
134 return PRINTER_STATUS_PAUSED;
143 /***************************************************************************
144 Disconnect from the client
145 ****************************************************************************/
147 static void srv_spoolss_replycloseprinter(int snum, struct policy_handle *handle)
153 * Tell the specific printing tdb we no longer want messages for this printer
154 * by deregistering our PID.
157 if (!print_notify_deregister_pid(snum))
158 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
160 /* weird if the test succeds !!! */
161 if (smb_connections==0) {
162 DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
166 status = rpccli_spoolss_ReplyClosePrinter(notify_cli_pipe, talloc_tos(),
169 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
170 DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
171 win_errstr(result)));
173 /* if it's the last connection, deconnect the IPC$ share */
174 if (smb_connections==1) {
176 cli_shutdown( rpc_pipe_np_smb_conn(notify_cli_pipe) );
177 notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */
179 messaging_deregister(smbd_messaging_context(),
180 MSG_PRINTER_NOTIFY2, NULL);
182 /* Tell the connections db we're no longer interested in
183 * printer notify messages. */
185 register_message_flags(false, FLAG_MSG_PRINT_NOTIFY);
191 /****************************************************************************
192 Functions to free a printer entry datastruct.
193 ****************************************************************************/
195 static int printer_entry_destructor(Printer_entry *Printer)
197 if (Printer->notify.client_connected == true) {
200 if ( Printer->printer_type == SPLHND_SERVER) {
202 srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
203 } else if (Printer->printer_type == SPLHND_PRINTER) {
204 snum = print_queue_snum(Printer->sharename);
206 srv_spoolss_replycloseprinter(snum,
207 &Printer->notify.client_hnd);
211 Printer->notify.flags=0;
212 Printer->notify.options=0;
213 Printer->notify.localmachine[0]='\0';
214 Printer->notify.printerlocal=0;
215 TALLOC_FREE(Printer->notify.option);
216 Printer->notify.client_connected = false;
218 free_nt_devicemode( &Printer->nt_devmode );
219 free_a_printer( &Printer->printer_info, 2 );
221 /* Remove from the internal list. */
222 DLIST_REMOVE(printers_list, Printer);
226 /****************************************************************************
227 find printer index by handle
228 ****************************************************************************/
230 static Printer_entry *find_printer_index_by_hnd(pipes_struct *p,
231 struct policy_handle *hnd)
233 Printer_entry *find_printer = NULL;
235 if(!find_policy_by_hnd(p,hnd,(void **)(void *)&find_printer)) {
236 DEBUG(2,("find_printer_index_by_hnd: Printer handle not found: "));
243 /****************************************************************************
244 Close printer index by handle.
245 ****************************************************************************/
247 static bool close_printer_handle(pipes_struct *p, struct policy_handle *hnd)
249 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
252 DEBUG(2,("close_printer_handle: Invalid handle (%s:%u:%u)\n",
257 close_policy_hnd(p, hnd);
262 /****************************************************************************
263 Delete a printer given a handle.
264 ****************************************************************************/
266 static WERROR delete_printer_hook(TALLOC_CTX *ctx, NT_USER_TOKEN *token, const char *sharename)
268 char *cmd = lp_deleteprinter_cmd();
269 char *command = NULL;
271 SE_PRIV se_printop = SE_PRINT_OPERATOR;
272 bool is_print_op = false;
274 /* can't fail if we don't try */
279 command = talloc_asprintf(ctx,
286 is_print_op = user_has_privileges( token, &se_printop );
288 DEBUG(10,("Running [%s]\n", command));
290 /********** BEGIN SePrintOperatorPrivlege BLOCK **********/
295 if ( (ret = smbrun(command, NULL)) == 0 ) {
296 /* Tell everyone we updated smb.conf. */
297 message_send_all(smbd_messaging_context(),
298 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
304 /********** END SePrintOperatorPrivlege BLOCK **********/
306 DEBUGADD(10,("returned [%d]\n", ret));
308 TALLOC_FREE(command);
311 return WERR_BADFID; /* What to return here? */
313 /* go ahead and re-read the services immediately */
315 reload_services(false);
318 if ( lp_servicenumber( sharename ) < 0 )
319 return WERR_ACCESS_DENIED;
324 /****************************************************************************
325 Delete a printer given a handle.
326 ****************************************************************************/
328 static WERROR delete_printer_handle(pipes_struct *p, struct policy_handle *hnd)
330 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
333 DEBUG(2,("delete_printer_handle: Invalid handle (%s:%u:%u)\n",
339 * It turns out that Windows allows delete printer on a handle
340 * opened by an admin user, then used on a pipe handle created
341 * by an anonymous user..... but they're working on security.... riiight !
345 if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
346 DEBUG(3, ("delete_printer_handle: denied by handle\n"));
347 return WERR_ACCESS_DENIED;
350 /* this does not need a become root since the access check has been
351 done on the handle already */
353 if (del_a_printer( Printer->sharename ) != 0) {
354 DEBUG(3,("Error deleting printer %s\n", Printer->sharename));
358 return delete_printer_hook(p->mem_ctx, p->server_info->ptok,
359 Printer->sharename );
362 /****************************************************************************
363 Return the snum of a printer corresponding to an handle.
364 ****************************************************************************/
366 static bool get_printer_snum(pipes_struct *p, struct policy_handle *hnd,
367 int *number, struct share_params **params)
369 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
372 DEBUG(2,("get_printer_snum: Invalid handle (%s:%u:%u)\n",
377 switch (Printer->printer_type) {
379 DEBUG(4,("short name:%s\n", Printer->sharename));
380 *number = print_queue_snum(Printer->sharename);
381 return (*number != -1);
389 /****************************************************************************
390 Set printer handle type.
391 Check if it's \\server or \\server\printer
392 ****************************************************************************/
394 static bool set_printer_hnd_printertype(Printer_entry *Printer, const char *handlename)
396 DEBUG(3,("Setting printer type=%s\n", handlename));
398 if ( strlen(handlename) < 3 ) {
399 DEBUGADD(4,("A print server must have at least 1 char ! %s\n", handlename));
403 /* it's a print server */
404 if (*handlename=='\\' && *(handlename+1)=='\\' && !strchr_m(handlename+2, '\\')) {
405 DEBUGADD(4,("Printer is a print server\n"));
406 Printer->printer_type = SPLHND_SERVER;
408 /* it's a printer (set_printer_hnd_name() will handle port monitors */
410 DEBUGADD(4,("Printer is a printer\n"));
411 Printer->printer_type = SPLHND_PRINTER;
417 /****************************************************************************
418 Set printer handle name.. Accept names like \\server, \\server\printer,
419 \\server\SHARE, & "\\server\,XcvMonitor Standard TCP/IP Port" See
420 the MSDN docs regarding OpenPrinter() for details on the XcvData() and
421 XcvDataPort() interface.
422 ****************************************************************************/
424 static bool set_printer_hnd_name(Printer_entry *Printer, const char *handlename)
427 int n_services=lp_numservices();
428 char *aprinter, *printername;
429 const char *servername;
432 NT_PRINTER_INFO_LEVEL *printer = NULL;
435 DEBUG(4,("Setting printer name=%s (len=%lu)\n", handlename,
436 (unsigned long)strlen(handlename)));
438 aprinter = CONST_DISCARD(char *, handlename);
439 if ( *handlename == '\\' ) {
440 servername = canon_servername(handlename);
441 if ( (aprinter = strchr_m( servername, '\\' )) != NULL ) {
446 servername = global_myname();
449 /* save the servername to fill in replies on this handle */
451 if ( !is_myname_or_ipaddr( servername ) )
454 fstrcpy( Printer->servername, servername );
456 if ( Printer->printer_type == SPLHND_SERVER )
459 if ( Printer->printer_type != SPLHND_PRINTER )
462 DEBUGADD(5, ("searching for [%s]\n", aprinter ));
464 /* check for the Port Monitor Interface */
466 if ( strequal( aprinter, SPL_XCV_MONITOR_TCPMON ) ) {
467 Printer->printer_type = SPLHND_PORTMON_TCP;
468 fstrcpy(sname, SPL_XCV_MONITOR_TCPMON);
471 else if ( strequal( aprinter, SPL_XCV_MONITOR_LOCALMON ) ) {
472 Printer->printer_type = SPLHND_PORTMON_LOCAL;
473 fstrcpy(sname, SPL_XCV_MONITOR_LOCALMON);
477 /* Search all sharenames first as this is easier than pulling
478 the printer_info_2 off of disk. Don't use find_service() since
479 that calls out to map_username() */
481 /* do another loop to look for printernames */
483 for (snum=0; !found && snum<n_services; snum++) {
485 /* no point going on if this is not a printer */
487 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
490 fstrcpy(sname, lp_servicename(snum));
491 if ( strequal( aprinter, sname ) ) {
496 /* no point looking up the printer object if
497 we aren't allowing printername != sharename */
499 if ( lp_force_printername(snum) )
502 fstrcpy(sname, lp_servicename(snum));
506 /* This call doesn't fill in the location or comment from
507 * a CUPS server for efficiency with large numbers of printers.
511 result = get_a_printer_search( NULL, &printer, 2, sname );
512 if ( !W_ERROR_IS_OK(result) ) {
513 DEBUG(0,("set_printer_hnd_name: failed to lookup printer [%s] -- result [%s]\n",
514 sname, win_errstr(result)));
518 /* printername is always returned as \\server\printername */
519 if ( !(printername = strchr_m(&printer->info_2->printername[2], '\\')) ) {
520 DEBUG(0,("set_printer_hnd_name: info2->printername in wrong format! [%s]\n",
521 printer->info_2->printername));
522 free_a_printer( &printer, 2);
528 if ( strequal(printername, aprinter) ) {
529 free_a_printer( &printer, 2);
534 DEBUGADD(10, ("printername: %s\n", printername));
536 free_a_printer( &printer, 2);
539 free_a_printer( &printer, 2);
542 DEBUGADD(4,("Printer not found\n"));
546 DEBUGADD(4,("set_printer_hnd_name: Printer found: %s -> %s\n", aprinter, sname));
548 fstrcpy(Printer->sharename, sname);
553 /****************************************************************************
554 Find first available printer slot. creates a printer handle for you.
555 ****************************************************************************/
557 static bool open_printer_hnd(pipes_struct *p, struct policy_handle *hnd,
558 const char *name, uint32_t access_granted)
560 Printer_entry *new_printer;
562 DEBUG(10,("open_printer_hnd: name [%s]\n", name));
564 new_printer = TALLOC_ZERO_P(NULL, Printer_entry);
565 if (new_printer == NULL) {
568 talloc_set_destructor(new_printer, printer_entry_destructor);
570 if (!create_policy_hnd(p, hnd, new_printer)) {
571 TALLOC_FREE(new_printer);
575 /* Add to the internal list. */
576 DLIST_ADD(printers_list, new_printer);
578 new_printer->notify.option=NULL;
580 if (!set_printer_hnd_printertype(new_printer, name)) {
581 close_printer_handle(p, hnd);
585 if (!set_printer_hnd_name(new_printer, name)) {
586 close_printer_handle(p, hnd);
590 new_printer->access_granted = access_granted;
592 DEBUG(5, ("%d printer handles active\n",
593 (int)num_pipe_handles(p->pipe_handles)));
598 /***************************************************************************
599 check to see if the client motify handle is monitoring the notification
600 given by (notify_type, notify_field).
601 **************************************************************************/
603 static bool is_monitoring_event_flags(uint32_t flags, uint16_t notify_type,
604 uint16_t notify_field)
609 static bool is_monitoring_event(Printer_entry *p, uint16_t notify_type,
610 uint16_t notify_field)
612 struct spoolss_NotifyOption *option = p->notify.option;
616 * Flags should always be zero when the change notify
617 * is registered by the client's spooler. A user Win32 app
618 * might use the flags though instead of the NOTIFY_OPTION_INFO
627 return is_monitoring_event_flags(
628 p->notify.flags, notify_type, notify_field);
630 for (i = 0; i < option->count; i++) {
632 /* Check match for notify_type */
634 if (option->types[i].type != notify_type)
637 /* Check match for field */
639 for (j = 0; j < option->types[i].count; j++) {
640 if (option->types[i].fields[j].field == notify_field) {
646 DEBUG(10, ("Open handle for \\\\%s\\%s is not monitoring 0x%02x/0x%02x\n",
647 p->servername, p->sharename, notify_type, notify_field));
652 #define SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(_data, _integer) \
653 _data->data.integer[0] = _integer; \
654 _data->data.integer[1] = 0;
657 #define SETUP_SPOOLSS_NOTIFY_DATA_STRING(_data, _p) \
658 _data->data.string.string = talloc_strdup(mem_ctx, _p); \
659 if (!_data->data.string.string) {\
660 _data->data.string.size = 0; \
662 _data->data.string.size = strlen_m_term(_p) * 2;
664 #define SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(_data, _devmode) \
665 _data->data.devmode.devmode = _devmode;
667 #define SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(_data, _size, _sd) \
668 _data->data.sd.sd = dup_sec_desc(mem_ctx, _sd); \
669 if (!_data->data.sd.sd) { \
670 _data->data.sd.sd_size = 0; \
672 _data->data.sd.sd_size = _size;
674 static void init_systemtime_buffer(TALLOC_CTX *mem_ctx,
679 struct spoolss_Time st;
683 if (!init_systemtime(&st, t)) {
687 p = talloc_array(mem_ctx, char, len);
693 * Systemtime must be linearized as a set of UINT16's.
694 * Fix from Benjamin (Bj) Kuit bj@it.uts.edu.au
697 SSVAL(p, 0, st.year);
698 SSVAL(p, 2, st.month);
699 SSVAL(p, 4, st.day_of_week);
701 SSVAL(p, 8, st.hour);
702 SSVAL(p, 10, st.minute);
703 SSVAL(p, 12, st.second);
704 SSVAL(p, 14, st.millisecond);
710 /* Convert a notification message to a struct spoolss_Notify */
712 static void notify_one_value(struct spoolss_notify_msg *msg,
713 struct spoolss_Notify *data,
716 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, msg->notify.value[0]);
719 static void notify_string(struct spoolss_notify_msg *msg,
720 struct spoolss_Notify *data,
723 /* The length of the message includes the trailing \0 */
725 data->data.string.size = msg->len * 2;
726 data->data.string.string = talloc_strdup(mem_ctx, msg->notify.data);
727 if (!data->data.string.string) {
728 data->data.string.size = 0;
733 static void notify_system_time(struct spoolss_notify_msg *msg,
734 struct spoolss_Notify *data,
737 data->data.string.string = NULL;
738 data->data.string.size = 0;
740 if (msg->len != sizeof(time_t)) {
741 DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
746 init_systemtime_buffer(mem_ctx, gmtime((time_t *)msg->notify.data),
747 &data->data.string.string,
748 &data->data.string.size);
751 struct notify2_message_table {
753 void (*fn)(struct spoolss_notify_msg *msg,
754 struct spoolss_Notify *data, TALLOC_CTX *mem_ctx);
757 static struct notify2_message_table printer_notify_table[] = {
758 /* 0x00 */ { "PRINTER_NOTIFY_FIELD_SERVER_NAME", notify_string },
759 /* 0x01 */ { "PRINTER_NOTIFY_FIELD_PRINTER_NAME", notify_string },
760 /* 0x02 */ { "PRINTER_NOTIFY_FIELD_SHARE_NAME", notify_string },
761 /* 0x03 */ { "PRINTER_NOTIFY_FIELD_PORT_NAME", notify_string },
762 /* 0x04 */ { "PRINTER_NOTIFY_FIELD_DRIVER_NAME", notify_string },
763 /* 0x05 */ { "PRINTER_NOTIFY_FIELD_COMMENT", notify_string },
764 /* 0x06 */ { "PRINTER_NOTIFY_FIELD_LOCATION", notify_string },
765 /* 0x07 */ { "PRINTER_NOTIFY_FIELD_DEVMODE", NULL },
766 /* 0x08 */ { "PRINTER_NOTIFY_FIELD_SEPFILE", notify_string },
767 /* 0x09 */ { "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", notify_string },
768 /* 0x0a */ { "PRINTER_NOTIFY_FIELD_PARAMETERS", NULL },
769 /* 0x0b */ { "PRINTER_NOTIFY_FIELD_DATATYPE", notify_string },
770 /* 0x0c */ { "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
771 /* 0x0d */ { "PRINTER_NOTIFY_FIELD_ATTRIBUTES", notify_one_value },
772 /* 0x0e */ { "PRINTER_NOTIFY_FIELD_PRIORITY", notify_one_value },
773 /* 0x0f */ { "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NULL },
774 /* 0x10 */ { "PRINTER_NOTIFY_FIELD_START_TIME", NULL },
775 /* 0x11 */ { "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NULL },
776 /* 0x12 */ { "PRINTER_NOTIFY_FIELD_STATUS", notify_one_value },
779 static struct notify2_message_table job_notify_table[] = {
780 /* 0x00 */ { "JOB_NOTIFY_FIELD_PRINTER_NAME", NULL },
781 /* 0x01 */ { "JOB_NOTIFY_FIELD_MACHINE_NAME", NULL },
782 /* 0x02 */ { "JOB_NOTIFY_FIELD_PORT_NAME", NULL },
783 /* 0x03 */ { "JOB_NOTIFY_FIELD_USER_NAME", notify_string },
784 /* 0x04 */ { "JOB_NOTIFY_FIELD_NOTIFY_NAME", NULL },
785 /* 0x05 */ { "JOB_NOTIFY_FIELD_DATATYPE", NULL },
786 /* 0x06 */ { "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NULL },
787 /* 0x07 */ { "JOB_NOTIFY_FIELD_PARAMETERS", NULL },
788 /* 0x08 */ { "JOB_NOTIFY_FIELD_DRIVER_NAME", NULL },
789 /* 0x09 */ { "JOB_NOTIFY_FIELD_DEVMODE", NULL },
790 /* 0x0a */ { "JOB_NOTIFY_FIELD_STATUS", notify_one_value },
791 /* 0x0b */ { "JOB_NOTIFY_FIELD_STATUS_STRING", NULL },
792 /* 0x0c */ { "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NULL },
793 /* 0x0d */ { "JOB_NOTIFY_FIELD_DOCUMENT", notify_string },
794 /* 0x0e */ { "JOB_NOTIFY_FIELD_PRIORITY", NULL },
795 /* 0x0f */ { "JOB_NOTIFY_FIELD_POSITION", NULL },
796 /* 0x10 */ { "JOB_NOTIFY_FIELD_SUBMITTED", notify_system_time },
797 /* 0x11 */ { "JOB_NOTIFY_FIELD_START_TIME", NULL },
798 /* 0x12 */ { "JOB_NOTIFY_FIELD_UNTIL_TIME", NULL },
799 /* 0x13 */ { "JOB_NOTIFY_FIELD_TIME", NULL },
800 /* 0x14 */ { "JOB_NOTIFY_FIELD_TOTAL_PAGES", notify_one_value },
801 /* 0x15 */ { "JOB_NOTIFY_FIELD_PAGES_PRINTED", NULL },
802 /* 0x16 */ { "JOB_NOTIFY_FIELD_TOTAL_BYTES", notify_one_value },
803 /* 0x17 */ { "JOB_NOTIFY_FIELD_BYTES_PRINTED", NULL },
807 /***********************************************************************
808 Allocate talloc context for container object
809 **********************************************************************/
811 static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
816 ctr->ctx = talloc_init("notify_msg_ctr_init %p", ctr);
821 /***********************************************************************
822 release all allocated memory and zero out structure
823 **********************************************************************/
825 static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
831 talloc_destroy(ctr->ctx);
838 /***********************************************************************
839 **********************************************************************/
841 static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
849 /***********************************************************************
850 **********************************************************************/
852 static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
854 if ( !ctr || !ctr->msg_groups )
857 if ( idx >= ctr->num_groups )
860 return &ctr->msg_groups[idx];
864 /***********************************************************************
865 How many groups of change messages do we have ?
866 **********************************************************************/
868 static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
873 return ctr->num_groups;
876 /***********************************************************************
877 Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
878 **********************************************************************/
880 static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
882 SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
883 SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
884 SPOOLSS_NOTIFY_MSG *msg_list = NULL;
890 /* loop over all groups looking for a matching printer name */
892 for ( i=0; i<ctr->num_groups; i++ ) {
893 if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
897 /* add a new group? */
899 if ( i == ctr->num_groups ) {
902 if ( !(groups = TALLOC_REALLOC_ARRAY( ctr->ctx, ctr->msg_groups, SPOOLSS_NOTIFY_MSG_GROUP, ctr->num_groups)) ) {
903 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
906 ctr->msg_groups = groups;
908 /* clear the new entry and set the printer name */
910 ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
911 fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
914 /* add the change messages; 'i' is the correct index now regardless */
916 msg_grp = &ctr->msg_groups[i];
920 if ( !(msg_list = TALLOC_REALLOC_ARRAY( ctr->ctx, msg_grp->msgs, SPOOLSS_NOTIFY_MSG, msg_grp->num_msgs )) ) {
921 DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
924 msg_grp->msgs = msg_list;
926 new_slot = msg_grp->num_msgs-1;
927 memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
929 /* need to allocate own copy of data */
932 msg_grp->msgs[new_slot].notify.data = (char *)
933 TALLOC_MEMDUP( ctr->ctx, msg->notify.data, msg->len );
935 return ctr->num_groups;
938 /***********************************************************************
939 Send a change notication message on all handles which have a call
941 **********************************************************************/
943 static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx )
946 TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
947 SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx );
948 SPOOLSS_NOTIFY_MSG *messages;
949 int sending_msg_count;
952 DEBUG(5,("send_notify2_changes() called with no msg group!\n"));
956 messages = msg_group->msgs;
959 DEBUG(5,("send_notify2_changes() called with no messages!\n"));
963 DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername));
965 /* loop over all printers */
967 for (p = printers_list; p; p = p->next) {
968 struct spoolss_Notify *notifies;
973 /* Is there notification on this handle? */
975 if ( !p->notify.client_connected )
978 DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename));
980 /* For this printer? Print servers always receive
983 if ( ( p->printer_type == SPLHND_PRINTER ) &&
984 ( !strequal(msg_group->printername, p->sharename) ) )
987 DEBUG(10,("Our printer\n"));
989 /* allocate the max entries possible */
991 notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs);
996 /* build the array of change notifications */
998 sending_msg_count = 0;
1000 for ( i=0; i<msg_group->num_msgs; i++ ) {
1001 SPOOLSS_NOTIFY_MSG *msg = &messages[i];
1003 /* Are we monitoring this event? */
1005 if (!is_monitoring_event(p, msg->type, msg->field))
1008 sending_msg_count++;
1011 DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n",
1012 msg->type, msg->field, p->sharename));
1015 * if the is a printer notification handle and not a job notification
1016 * type, then set the id to 0. Other wise just use what was specified
1019 * When registering change notification on a print server handle
1020 * we always need to send back the id (snum) matching the printer
1021 * for which the change took place. For change notify registered
1022 * on a printer handle, this does not matter and the id should be 0.
1027 if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
1033 /* Convert unix jobid to smb jobid */
1035 if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
1036 id = sysjob_to_jobid(msg->id);
1039 DEBUG(3, ("no such unix jobid %d\n", msg->id));
1044 construct_info_data( ¬ifies[count], msg->type, msg->field, id );
1047 case PRINTER_NOTIFY_TYPE:
1048 if ( printer_notify_table[msg->field].fn )
1049 printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1052 case JOB_NOTIFY_TYPE:
1053 if ( job_notify_table[msg->field].fn )
1054 job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx);
1058 DEBUG(5, ("Unknown notification type %d\n", msg->type));
1065 if ( sending_msg_count ) {
1068 union spoolss_ReplyPrinterInfo info;
1069 struct spoolss_NotifyInfo info0;
1070 uint32_t reply_result;
1072 info0.version = 0x2;
1073 info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED;
1074 info0.count = count;
1075 info0.notifies = notifies;
1077 info.info0 = &info0;
1079 status = rpccli_spoolss_RouterReplyPrinterEx(notify_cli_pipe, mem_ctx,
1080 &p->notify.client_hnd,
1081 p->notify.change, /* color */
1084 0, /* reply_type, must be 0 */
1087 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
1088 DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n",
1089 notify_cli_pipe->srv_name_slash,
1092 switch (reply_result) {
1095 case PRINTER_NOTIFY_INFO_DISCARDED:
1096 case PRINTER_NOTIFY_INFO_DISCARDNOTED:
1097 case PRINTER_NOTIFY_INFO_COLOR_MISMATCH:
1106 DEBUG(8,("send_notify2_changes: Exit...\n"));
1110 /***********************************************************************
1111 **********************************************************************/
1113 static bool notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len )
1116 uint32_t tv_sec, tv_usec;
1119 /* Unpack message */
1121 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "f",
1124 offset += tdb_unpack((uint8_t *)buf + offset, len - offset, "ddddddd",
1126 &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
1129 tdb_unpack((uint8_t *)buf + offset, len - offset, "dd",
1130 &msg->notify.value[0], &msg->notify.value[1]);
1132 tdb_unpack((uint8_t *)buf + offset, len - offset, "B",
1133 &msg->len, &msg->notify.data);
1135 DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n",
1136 msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags));
1138 tv->tv_sec = tv_sec;
1139 tv->tv_usec = tv_usec;
1142 DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0],
1143 msg->notify.value[1]));
1145 dump_data(3, (uint8_t *)msg->notify.data, msg->len);
1150 /********************************************************************
1151 Receive a notify2 message list
1152 ********************************************************************/
1154 static void receive_notify2_message_list(struct messaging_context *msg,
1157 struct server_id server_id,
1160 size_t msg_count, i;
1161 char *buf = (char *)data->data;
1164 SPOOLSS_NOTIFY_MSG notify;
1165 SPOOLSS_NOTIFY_MSG_CTR messages;
1168 if (data->length < 4) {
1169 DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n"));
1173 msg_count = IVAL(buf, 0);
1176 DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count));
1178 if (msg_count == 0) {
1179 DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
1183 /* initialize the container */
1185 ZERO_STRUCT( messages );
1186 notify_msg_ctr_init( &messages );
1189 * build message groups for each printer identified
1190 * in a change_notify msg. Remember that a PCN message
1191 * includes the handle returned for the srv_spoolss_replyopenprinter()
1192 * call. Therefore messages are grouped according to printer handle.
1195 for ( i=0; i<msg_count; i++ ) {
1196 struct timeval msg_tv;
1198 if (msg_ptr + 4 - buf > data->length) {
1199 DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n"));
1203 msg_len = IVAL(msg_ptr,0);
1206 if (msg_ptr + msg_len - buf > data->length) {
1207 DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n"));
1211 /* unpack messages */
1213 ZERO_STRUCT( notify );
1214 notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len );
1217 /* add to correct list in container */
1219 notify_msg_ctr_addmsg( &messages, ¬ify );
1221 /* free memory that might have been allocated by notify2_unpack_msg() */
1223 if ( notify.len != 0 )
1224 SAFE_FREE( notify.notify.data );
1227 /* process each group of messages */
1229 num_groups = notify_msg_ctr_numgroups( &messages );
1230 for ( i=0; i<num_groups; i++ )
1231 send_notify2_changes( &messages, i );
1236 DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
1237 (uint32_t)msg_count ));
1239 notify_msg_ctr_destroy( &messages );
1244 /********************************************************************
1245 Send a message to ourself about new driver being installed
1246 so we can upgrade the information for each printer bound to this
1248 ********************************************************************/
1250 static bool srv_spoolss_drv_upgrade_printer(const char *drivername)
1252 int len = strlen(drivername);
1257 DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n",
1260 messaging_send_buf(smbd_messaging_context(), procid_self(),
1261 MSG_PRINTER_DRVUPGRADE,
1262 (uint8_t *)drivername, len+1);
1267 /**********************************************************************
1268 callback to receive a MSG_PRINTER_DRVUPGRADE message and interate
1269 over all printers, upgrading ones as necessary
1270 **********************************************************************/
1272 void do_drv_upgrade_printer(struct messaging_context *msg,
1275 struct server_id server_id,
1280 int n_services = lp_numservices();
1283 len = MIN(data->length,sizeof(drivername)-1);
1284 strncpy(drivername, (const char *)data->data, len);
1286 DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername ));
1288 /* Iterate the printer list */
1290 for (snum=0; snum<n_services; snum++)
1292 if (lp_snum_ok(snum) && lp_print_ok(snum) )
1295 NT_PRINTER_INFO_LEVEL *printer = NULL;
1297 result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum));
1298 if (!W_ERROR_IS_OK(result))
1301 if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))
1303 DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername));
1305 /* all we care about currently is the change_id */
1307 result = mod_a_printer(printer, 2);
1308 if (!W_ERROR_IS_OK(result)) {
1309 DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
1310 win_errstr(result)));
1314 free_a_printer(&printer, 2);
1321 /********************************************************************
1322 Update the cache for all printq's with a registered client
1324 ********************************************************************/
1326 void update_monitored_printq_cache( void )
1328 Printer_entry *printer = printers_list;
1331 /* loop through all printers and update the cache where
1332 client_connected == true */
1335 if ( (printer->printer_type == SPLHND_PRINTER)
1336 && printer->notify.client_connected )
1338 snum = print_queue_snum(printer->sharename);
1339 print_queue_status( snum, NULL, NULL );
1342 printer = printer->next;
1347 /********************************************************************
1348 Send a message to ourself about new driver being installed
1349 so we can upgrade the information for each printer bound to this
1351 ********************************************************************/
1353 static bool srv_spoolss_reset_printerdata(char* drivername)
1355 int len = strlen(drivername);
1360 DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n",
1363 messaging_send_buf(smbd_messaging_context(), procid_self(),
1364 MSG_PRINTERDATA_INIT_RESET,
1365 (uint8_t *)drivername, len+1);
1370 /**********************************************************************
1371 callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate
1372 over all printers, resetting printer data as neessary
1373 **********************************************************************/
1375 void reset_all_printerdata(struct messaging_context *msg,
1378 struct server_id server_id,
1383 int n_services = lp_numservices();
1386 len = MIN( data->length, sizeof(drivername)-1 );
1387 strncpy( drivername, (const char *)data->data, len );
1389 DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername ));
1391 /* Iterate the printer list */
1393 for ( snum=0; snum<n_services; snum++ )
1395 if ( lp_snum_ok(snum) && lp_print_ok(snum) )
1398 NT_PRINTER_INFO_LEVEL *printer = NULL;
1400 result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) );
1401 if ( !W_ERROR_IS_OK(result) )
1405 * if the printer is bound to the driver,
1406 * then reset to the new driver initdata
1409 if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) )
1411 DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername));
1413 if ( !set_driver_init(printer, 2) ) {
1414 DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n",
1415 printer->info_2->printername, printer->info_2->drivername));
1418 result = mod_a_printer( printer, 2 );
1419 if ( !W_ERROR_IS_OK(result) ) {
1420 DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n",
1421 get_dos_error_msg(result)));
1425 free_a_printer( &printer, 2 );
1434 /****************************************************************
1435 _spoolss_OpenPrinter
1436 ****************************************************************/
1438 WERROR _spoolss_OpenPrinter(pipes_struct *p,
1439 struct spoolss_OpenPrinter *r)
1441 struct spoolss_OpenPrinterEx e;
1444 ZERO_STRUCT(e.in.userlevel);
1446 e.in.printername = r->in.printername;
1447 e.in.datatype = r->in.datatype;
1448 e.in.devmode_ctr = r->in.devmode_ctr;
1449 e.in.access_mask = r->in.access_mask;
1452 e.out.handle = r->out.handle;
1454 werr = _spoolss_OpenPrinterEx(p, &e);
1456 if (W_ERROR_EQUAL(werr, WERR_INVALID_PARAM)) {
1457 /* OpenPrinterEx returns this for a bad
1458 * printer name. We must return WERR_INVALID_PRINTER_NAME
1461 werr = WERR_INVALID_PRINTER_NAME;
1467 /********************************************************************
1468 ********************************************************************/
1470 bool convert_devicemode(const char *printername,
1471 const struct spoolss_DeviceMode *devmode,
1472 NT_DEVICEMODE **pp_nt_devmode)
1474 NT_DEVICEMODE *nt_devmode = *pp_nt_devmode;
1477 * Ensure nt_devmode is a valid pointer
1478 * as we will be overwriting it.
1481 if (nt_devmode == NULL) {
1482 DEBUG(5, ("convert_devicemode: allocating a generic devmode\n"));
1483 if ((nt_devmode = construct_nt_devicemode(printername)) == NULL)
1487 fstrcpy(nt_devmode->devicename, devmode->devicename);
1488 fstrcpy(nt_devmode->formname, devmode->formname);
1490 nt_devmode->devicename[31] = '\0';
1491 nt_devmode->formname[31] = '\0';
1493 nt_devmode->specversion = devmode->specversion;
1494 nt_devmode->driverversion = devmode->driverversion;
1495 nt_devmode->size = devmode->size;
1496 nt_devmode->fields = devmode->fields;
1497 nt_devmode->orientation = devmode->orientation;
1498 nt_devmode->papersize = devmode->papersize;
1499 nt_devmode->paperlength = devmode->paperlength;
1500 nt_devmode->paperwidth = devmode->paperwidth;
1501 nt_devmode->scale = devmode->scale;
1502 nt_devmode->copies = devmode->copies;
1503 nt_devmode->defaultsource = devmode->defaultsource;
1504 nt_devmode->printquality = devmode->printquality;
1505 nt_devmode->color = devmode->color;
1506 nt_devmode->duplex = devmode->duplex;
1507 nt_devmode->yresolution = devmode->yresolution;
1508 nt_devmode->ttoption = devmode->ttoption;
1509 nt_devmode->collate = devmode->collate;
1511 nt_devmode->logpixels = devmode->logpixels;
1512 nt_devmode->bitsperpel = devmode->bitsperpel;
1513 nt_devmode->pelswidth = devmode->pelswidth;
1514 nt_devmode->pelsheight = devmode->pelsheight;
1515 nt_devmode->displayflags = devmode->displayflags;
1516 nt_devmode->displayfrequency = devmode->displayfrequency;
1517 nt_devmode->icmmethod = devmode->icmmethod;
1518 nt_devmode->icmintent = devmode->icmintent;
1519 nt_devmode->mediatype = devmode->mediatype;
1520 nt_devmode->dithertype = devmode->dithertype;
1521 nt_devmode->reserved1 = devmode->reserved1;
1522 nt_devmode->reserved2 = devmode->reserved2;
1523 nt_devmode->panningwidth = devmode->panningwidth;
1524 nt_devmode->panningheight = devmode->panningheight;
1527 * Only change private and driverextra if the incoming devmode
1528 * has a new one. JRA.
1531 if ((devmode->__driverextra_length != 0) && (devmode->driverextra_data.data != NULL)) {
1532 SAFE_FREE(nt_devmode->nt_dev_private);
1533 nt_devmode->driverextra = devmode->__driverextra_length;
1534 if((nt_devmode->nt_dev_private = SMB_MALLOC_ARRAY(uint8_t, nt_devmode->driverextra)) == NULL)
1536 memcpy(nt_devmode->nt_dev_private, devmode->driverextra_data.data, nt_devmode->driverextra);
1539 *pp_nt_devmode = nt_devmode;
1544 /****************************************************************
1545 _spoolss_OpenPrinterEx
1546 ****************************************************************/
1548 WERROR _spoolss_OpenPrinterEx(pipes_struct *p,
1549 struct spoolss_OpenPrinterEx *r)
1552 Printer_entry *Printer=NULL;
1554 if (!r->in.printername) {
1555 return WERR_INVALID_PARAM;
1558 /* some sanity check because you can open a printer or a print server */
1559 /* aka: \\server\printer or \\server */
1561 DEBUGADD(3,("checking name: %s\n", r->in.printername));
1563 if (!open_printer_hnd(p, r->out.handle, r->in.printername, 0)) {
1564 ZERO_STRUCTP(r->out.handle);
1565 return WERR_INVALID_PARAM;
1568 Printer = find_printer_index_by_hnd(p, r->out.handle);
1570 DEBUG(0,("_spoolss_OpenPrinterEx: logic error. Can't find printer "
1571 "handle we created for printer %s\n", r->in.printername));
1572 close_printer_handle(p, r->out.handle);
1573 ZERO_STRUCTP(r->out.handle);
1574 return WERR_INVALID_PARAM;
1578 * First case: the user is opening the print server:
1580 * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
1581 * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
1583 * Then both Win2k and WinNT clients try an OpenPrinterEx with
1584 * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
1585 * or if the user is listed in the smb.conf printer admin parameter.
1587 * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
1588 * client view printer folder, but does not show the MSAPW.
1590 * Note: this test needs code to check access rights here too. Jeremy
1591 * could you look at this?
1593 * Second case: the user is opening a printer:
1594 * NT doesn't let us connect to a printer if the connecting user
1595 * doesn't have print permission.
1597 * Third case: user is opening a Port Monitor
1598 * access checks same as opening a handle to the print server.
1601 switch (Printer->printer_type )
1604 case SPLHND_PORTMON_TCP:
1605 case SPLHND_PORTMON_LOCAL:
1606 /* Printserver handles use global struct... */
1610 /* Map standard access rights to object specific access rights */
1612 se_map_standard(&r->in.access_mask,
1613 &printserver_std_mapping);
1615 /* Deny any object specific bits that don't apply to print
1616 servers (i.e printer and job specific bits) */
1618 r->in.access_mask &= SPECIFIC_RIGHTS_MASK;
1620 if (r->in.access_mask &
1621 ~(SERVER_ACCESS_ADMINISTER | SERVER_ACCESS_ENUMERATE)) {
1622 DEBUG(3, ("access DENIED for non-printserver bits\n"));
1623 close_printer_handle(p, r->out.handle);
1624 ZERO_STRUCTP(r->out.handle);
1625 return WERR_ACCESS_DENIED;
1628 /* Allow admin access */
1630 if ( r->in.access_mask & SERVER_ACCESS_ADMINISTER )
1632 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1634 if (!lp_ms_add_printer_wizard()) {
1635 close_printer_handle(p, r->out.handle);
1636 ZERO_STRUCTP(r->out.handle);
1637 return WERR_ACCESS_DENIED;
1640 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1641 and not a printer admin, then fail */
1643 if ((p->server_info->utok.uid != sec_initial_uid()) &&
1644 !user_has_privileges(p->server_info->ptok,
1646 !token_contains_name_in_list(
1647 uidtoname(p->server_info->utok.uid),
1649 p->server_info->ptok,
1650 lp_printer_admin(snum))) {
1651 close_printer_handle(p, r->out.handle);
1652 ZERO_STRUCTP(r->out.handle);
1653 return WERR_ACCESS_DENIED;
1656 r->in.access_mask = SERVER_ACCESS_ADMINISTER;
1660 r->in.access_mask = SERVER_ACCESS_ENUMERATE;
1663 DEBUG(4,("Setting print server access = %s\n", (r->in.access_mask == SERVER_ACCESS_ADMINISTER)
1664 ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
1666 /* We fall through to return WERR_OK */
1669 case SPLHND_PRINTER:
1670 /* NT doesn't let us connect to a printer if the connecting user
1671 doesn't have print permission. */
1673 if (!get_printer_snum(p, r->out.handle, &snum, NULL)) {
1674 close_printer_handle(p, r->out.handle);
1675 ZERO_STRUCTP(r->out.handle);
1679 if (r->in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED) {
1680 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1683 se_map_standard(&r->in.access_mask, &printer_std_mapping);
1685 /* map an empty access mask to the minimum access mask */
1686 if (r->in.access_mask == 0x0)
1687 r->in.access_mask = PRINTER_ACCESS_USE;
1690 * If we are not serving the printer driver for this printer,
1691 * map PRINTER_ACCESS_ADMINISTER to PRINTER_ACCESS_USE. This
1692 * will keep NT clients happy --jerry
1695 if (lp_use_client_driver(snum)
1696 && (r->in.access_mask & PRINTER_ACCESS_ADMINISTER))
1698 r->in.access_mask = PRINTER_ACCESS_USE;
1701 /* check smb.conf parameters and the the sec_desc */
1703 if ( !check_access(get_client_fd(), lp_hostsallow(snum), lp_hostsdeny(snum)) ) {
1704 DEBUG(3, ("access DENIED (hosts allow/deny) for printer open\n"));
1705 ZERO_STRUCTP(r->out.handle);
1706 return WERR_ACCESS_DENIED;
1709 if (!user_ok_token(uidtoname(p->server_info->utok.uid), NULL,
1710 p->server_info->ptok, snum) ||
1711 !print_access_check(p->server_info, snum,
1712 r->in.access_mask)) {
1713 DEBUG(3, ("access DENIED for printer open\n"));
1714 close_printer_handle(p, r->out.handle);
1715 ZERO_STRUCTP(r->out.handle);
1716 return WERR_ACCESS_DENIED;
1719 if ((r->in.access_mask & SPECIFIC_RIGHTS_MASK)& ~(PRINTER_ACCESS_ADMINISTER|PRINTER_ACCESS_USE)) {
1720 DEBUG(3, ("access DENIED for printer open - unknown bits\n"));
1721 close_printer_handle(p, r->out.handle);
1722 ZERO_STRUCTP(r->out.handle);
1723 return WERR_ACCESS_DENIED;
1726 if (r->in.access_mask & PRINTER_ACCESS_ADMINISTER)
1727 r->in.access_mask = PRINTER_ACCESS_ADMINISTER;
1729 r->in.access_mask = PRINTER_ACCESS_USE;
1731 DEBUG(4,("Setting printer access = %s\n", (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1732 ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
1737 /* sanity check to prevent programmer error */
1738 ZERO_STRUCTP(r->out.handle);
1742 Printer->access_granted = r->in.access_mask;
1745 * If the client sent a devmode in the OpenPrinter() call, then
1746 * save it here in case we get a job submission on this handle
1749 if ((Printer->printer_type != SPLHND_SERVER) &&
1750 r->in.devmode_ctr.devmode) {
1751 convert_devicemode(Printer->sharename,
1752 r->in.devmode_ctr.devmode,
1753 &Printer->nt_devmode);
1756 #if 0 /* JERRY -- I'm doubtful this is really effective */
1757 /* HACK ALERT!!! Sleep for 1/3 of a second to try trigger a LAN/WAN
1758 optimization in Windows 2000 clients --jerry */
1760 if ( (r->in.access_mask == PRINTER_ACCESS_ADMINISTER)
1761 && (RA_WIN2K == get_remote_arch()) )
1763 DEBUG(10,("_spoolss_OpenPrinterEx: Enabling LAN/WAN hack for Win2k clients.\n"));
1764 sys_usleep( 500000 );
1771 /****************************************************************************
1772 ****************************************************************************/
1774 static bool printer_info2_to_nt_printer_info2(struct spoolss_SetPrinterInfo2 *r,
1775 NT_PRINTER_INFO_LEVEL_2 *d)
1777 DEBUG(7,("printer_info2_to_nt_printer_info2\n"));
1783 d->attributes = r->attributes;
1784 d->priority = r->priority;
1785 d->default_priority = r->defaultpriority;
1786 d->starttime = r->starttime;
1787 d->untiltime = r->untiltime;
1788 d->status = r->status;
1789 d->cjobs = r->cjobs;
1791 fstrcpy(d->servername, r->servername);
1792 fstrcpy(d->printername, r->printername);
1793 fstrcpy(d->sharename, r->sharename);
1794 fstrcpy(d->portname, r->portname);
1795 fstrcpy(d->drivername, r->drivername);
1796 slprintf(d->comment, sizeof(d->comment)-1, "%s", r->comment);
1797 fstrcpy(d->location, r->location);
1798 fstrcpy(d->sepfile, r->sepfile);
1799 fstrcpy(d->printprocessor, r->printprocessor);
1800 fstrcpy(d->datatype, r->datatype);
1801 fstrcpy(d->parameters, r->parameters);
1806 /****************************************************************************
1807 ****************************************************************************/
1809 static bool convert_printer_info(struct spoolss_SetPrinterInfoCtr *info_ctr,
1810 NT_PRINTER_INFO_LEVEL *printer)
1814 switch (info_ctr->level) {
1816 /* allocate memory if needed. Messy because
1817 convert_printer_info is used to update an existing
1818 printer or build a new one */
1820 if (!printer->info_2) {
1821 printer->info_2 = TALLOC_ZERO_P(printer, NT_PRINTER_INFO_LEVEL_2);
1822 if (!printer->info_2) {
1823 DEBUG(0,("convert_printer_info: "
1824 "talloc() failed!\n"));
1829 ret = printer_info2_to_nt_printer_info2(info_ctr->info.info2,
1831 printer->info_2->setuptime = time(NULL);
1838 /****************************************************************
1839 _spoolss_ClosePrinter
1840 ****************************************************************/
1842 WERROR _spoolss_ClosePrinter(pipes_struct *p,
1843 struct spoolss_ClosePrinter *r)
1845 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1847 if (Printer && Printer->document_started) {
1848 struct spoolss_EndDocPrinter e;
1850 e.in.handle = r->in.handle;
1852 _spoolss_EndDocPrinter(p, &e);
1855 if (!close_printer_handle(p, r->in.handle))
1858 /* clear the returned printer handle. Observed behavior
1859 from Win2k server. Don't think this really matters.
1860 Previous code just copied the value of the closed
1863 ZERO_STRUCTP(r->out.handle);
1868 /****************************************************************
1869 _spoolss_DeletePrinter
1870 ****************************************************************/
1872 WERROR _spoolss_DeletePrinter(pipes_struct *p,
1873 struct spoolss_DeletePrinter *r)
1875 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
1878 if (Printer && Printer->document_started) {
1879 struct spoolss_EndDocPrinter e;
1881 e.in.handle = r->in.handle;
1883 _spoolss_EndDocPrinter(p, &e);
1886 result = delete_printer_handle(p, r->in.handle);
1888 update_c_setprinter(false);
1893 /*******************************************************************
1894 * static function to lookup the version id corresponding to an
1895 * long architecture string
1896 ******************************************************************/
1898 static const struct print_architecture_table_node archi_table[]= {
1900 {"Windows 4.0", SPL_ARCH_WIN40, 0 },
1901 {"Windows NT x86", SPL_ARCH_W32X86, 2 },
1902 {"Windows NT R4000", SPL_ARCH_W32MIPS, 2 },
1903 {"Windows NT Alpha_AXP", SPL_ARCH_W32ALPHA, 2 },
1904 {"Windows NT PowerPC", SPL_ARCH_W32PPC, 2 },
1905 {"Windows IA64", SPL_ARCH_IA64, 3 },
1906 {"Windows x64", SPL_ARCH_X64, 3 },
1910 static int get_version_id(const char *arch)
1914 for (i=0; archi_table[i].long_archi != NULL; i++)
1916 if (strcmp(arch, archi_table[i].long_archi) == 0)
1917 return (archi_table[i].version);
1923 /****************************************************************
1924 _spoolss_DeletePrinterDriver
1925 ****************************************************************/
1927 WERROR _spoolss_DeletePrinterDriver(pipes_struct *p,
1928 struct spoolss_DeletePrinterDriver *r)
1931 struct spoolss_DriverInfo8 *info = NULL;
1932 struct spoolss_DriverInfo8 *info_win2k = NULL;
1935 WERROR status_win2k = WERR_ACCESS_DENIED;
1936 SE_PRIV se_printop = SE_PRINT_OPERATOR;
1938 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
1939 and not a printer admin, then fail */
1941 if ( (p->server_info->utok.uid != sec_initial_uid())
1942 && !user_has_privileges(p->server_info->ptok, &se_printop )
1943 && !token_contains_name_in_list(
1944 uidtoname(p->server_info->utok.uid), NULL,
1945 NULL, p->server_info->ptok,
1946 lp_printer_admin(-1)) )
1948 return WERR_ACCESS_DENIED;
1951 /* check that we have a valid driver name first */
1953 if ((version = get_version_id(r->in.architecture)) == -1)
1954 return WERR_INVALID_ENVIRONMENT;
1956 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
1960 /* try for Win2k driver if "Windows NT x86" */
1962 if ( version == 2 ) {
1964 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1969 status = WERR_UNKNOWN_PRINTER_DRIVER;
1973 /* otherwise it was a failure */
1975 status = WERR_UNKNOWN_PRINTER_DRIVER;
1981 if (printer_driver_in_use(info)) {
1982 status = WERR_PRINTER_DRIVER_IN_USE;
1988 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx,
1991 r->in.architecture, 3)))
1993 /* if we get to here, we now have 2 driver info structures to remove */
1994 /* remove the Win2k driver first*/
1996 status_win2k = delete_printer_driver(
1997 p, info_win2k, 3, false);
1998 free_a_printer_driver(info_win2k);
2000 /* this should not have failed---if it did, report to client */
2001 if ( !W_ERROR_IS_OK(status_win2k) )
2003 status = status_win2k;
2009 status = delete_printer_driver(p, info, version, false);
2011 /* if at least one of the deletes succeeded return OK */
2013 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2017 free_a_printer_driver(info);
2022 /****************************************************************
2023 _spoolss_DeletePrinterDriverEx
2024 ****************************************************************/
2026 WERROR _spoolss_DeletePrinterDriverEx(pipes_struct *p,
2027 struct spoolss_DeletePrinterDriverEx *r)
2029 struct spoolss_DriverInfo8 *info = NULL;
2030 struct spoolss_DriverInfo8 *info_win2k = NULL;
2034 WERROR status_win2k = WERR_ACCESS_DENIED;
2035 SE_PRIV se_printop = SE_PRINT_OPERATOR;
2037 /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
2038 and not a printer admin, then fail */
2040 if ( (p->server_info->utok.uid != sec_initial_uid())
2041 && !user_has_privileges(p->server_info->ptok, &se_printop )
2042 && !token_contains_name_in_list(
2043 uidtoname(p->server_info->utok.uid), NULL, NULL,
2044 p->server_info->ptok, lp_printer_admin(-1)) )
2046 return WERR_ACCESS_DENIED;
2049 /* check that we have a valid driver name first */
2050 if ((version = get_version_id(r->in.architecture)) == -1) {
2051 /* this is what NT returns */
2052 return WERR_INVALID_ENVIRONMENT;
2055 if (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION)
2056 version = r->in.version;
2058 status = get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2059 r->in.architecture, version);
2061 if ( !W_ERROR_IS_OK(status) )
2064 * if the client asked for a specific version,
2065 * or this is something other than Windows NT x86,
2069 if ( (r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
2072 /* try for Win2k driver if "Windows NT x86" */
2075 if (!W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info, r->in.driver,
2078 status = WERR_UNKNOWN_PRINTER_DRIVER;
2083 if (printer_driver_in_use(info)) {
2084 status = WERR_PRINTER_DRIVER_IN_USE;
2089 * we have a couple of cases to consider.
2090 * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
2091 * then the delete should fail if **any** files overlap with
2093 * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
2094 * non-overlapping files
2095 * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
2096 * is set, the do not delete any files
2097 * Refer to MSDN docs on DeletePrinterDriverEx() for details.
2100 delete_files = r->in.delete_flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
2102 /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
2104 if (delete_files && printer_driver_files_in_use(info, info) & (r->in.delete_flags & DPD_DELETE_ALL_FILES)) {
2105 /* no idea of the correct error here */
2106 status = WERR_ACCESS_DENIED;
2111 /* also check for W32X86/3 if necessary; maybe we already have? */
2113 if ( (version == 2) && ((r->in.delete_flags & DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
2114 if (W_ERROR_IS_OK(get_a_printer_driver(p->mem_ctx, &info_win2k,
2116 r->in.architecture, 3)))
2119 if (delete_files && printer_driver_files_in_use(info, info_win2k) & (r->in.delete_flags & DPD_DELETE_ALL_FILES) ) {
2120 /* no idea of the correct error here */
2121 free_a_printer_driver(info_win2k);
2122 status = WERR_ACCESS_DENIED;
2126 /* if we get to here, we now have 2 driver info structures to remove */
2127 /* remove the Win2k driver first*/
2129 status_win2k = delete_printer_driver(
2130 p, info_win2k, 3, delete_files);
2131 free_a_printer_driver(info_win2k);
2133 /* this should not have failed---if it did, report to client */
2135 if ( !W_ERROR_IS_OK(status_win2k) )
2140 status = delete_printer_driver(p, info, version, delete_files);
2142 if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
2145 free_a_printer_driver(info);
2151 /****************************************************************************
2152 Internal routine for removing printerdata
2153 ***************************************************************************/
2155 static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, const char *key, const char *value )
2157 return delete_printer_data( printer->info_2, key, value );
2160 /****************************************************************************
2161 Internal routine for storing printerdata
2162 ***************************************************************************/
2164 WERROR set_printer_dataex(NT_PRINTER_INFO_LEVEL *printer,
2165 const char *key, const char *value,
2166 uint32_t type, uint8_t *data, int real_len)
2168 /* the registry objects enforce uniqueness based on value name */
2170 return add_printer_data( printer->info_2, key, value, type, data, real_len );
2173 /********************************************************************
2174 GetPrinterData on a printer server Handle.
2175 ********************************************************************/
2177 static WERROR getprinterdata_printer_server(TALLOC_CTX *mem_ctx,
2179 enum winreg_Type *type,
2180 union spoolss_PrinterData *data)
2182 DEBUG(8,("getprinterdata_printer_server:%s\n", value));
2184 if (!StrCaseCmp(value, "W3SvcInstalled")) {
2190 if (!StrCaseCmp(value, "BeepEnabled")) {
2196 if (!StrCaseCmp(value, "EventLog")) {
2198 /* formally was 0x1b */
2203 if (!StrCaseCmp(value, "NetPopup")) {
2209 if (!StrCaseCmp(value, "MajorVersion")) {
2212 /* Windows NT 4.0 seems to not allow uploading of drivers
2213 to a server that reports 0x3 as the MajorVersion.
2214 need to investigate more how Win2k gets around this .
2217 if (RA_WINNT == get_remote_arch()) {
2226 if (!StrCaseCmp(value, "MinorVersion")) {
2233 * uint32_t size = 0x114
2234 * uint32_t major = 5
2235 * uint32_t minor = [0|1]
2236 * uint32_t build = [2195|2600]
2237 * extra unicode string = e.g. "Service Pack 3"
2239 if (!StrCaseCmp(value, "OSVersion")) {
2241 enum ndr_err_code ndr_err;
2242 struct spoolss_OSVersion os;
2244 os.major = 5; /* Windows 2000 == 5.0 */
2246 os.build = 2195; /* build */
2247 os.extra_string = ""; /* leave extra string empty */
2249 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &os,
2250 (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
2251 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2252 return WERR_GENERAL_FAILURE;
2256 data->binary = blob;
2262 if (!StrCaseCmp(value, "DefaultSpoolDirectory")) {
2265 data->string = talloc_strdup(mem_ctx, "C:\\PRINTERS");
2266 W_ERROR_HAVE_NO_MEMORY(data->string);
2271 if (!StrCaseCmp(value, "Architecture")) {
2274 data->string = talloc_strdup(mem_ctx, "Windows NT x86");
2275 W_ERROR_HAVE_NO_MEMORY(data->string);
2280 if (!StrCaseCmp(value, "DsPresent")) {
2283 /* only show the publish check box if we are a
2284 member of a AD domain */
2286 if (lp_security() == SEC_ADS) {
2294 if (!StrCaseCmp(value, "DNSMachineName")) {
2295 const char *hostname = get_mydnsfullname();
2298 return WERR_BADFILE;
2302 data->string = talloc_strdup(mem_ctx, hostname);
2303 W_ERROR_HAVE_NO_MEMORY(data->string);
2310 return WERR_INVALID_PARAM;
2313 /****************************************************************
2314 _spoolss_GetPrinterData
2315 ****************************************************************/
2317 WERROR _spoolss_GetPrinterData(pipes_struct *p,
2318 struct spoolss_GetPrinterData *r)
2320 struct spoolss_GetPrinterDataEx r2;
2322 r2.in.handle = r->in.handle;
2323 r2.in.key_name = "PrinterDriverData";
2324 r2.in.value_name = r->in.value_name;
2325 r2.in.offered = r->in.offered;
2326 r2.out.type = r->out.type;
2327 r2.out.data = r->out.data;
2328 r2.out.needed = r->out.needed;
2330 return _spoolss_GetPrinterDataEx(p, &r2);
2333 /*********************************************************
2334 Connect to the client machine.
2335 **********************************************************/
2337 static bool spoolss_connect_to_client(struct rpc_pipe_client **pp_pipe,
2338 struct sockaddr_storage *client_ss, const char *remote_machine)
2341 struct cli_state *the_cli;
2342 struct sockaddr_storage rm_addr;
2344 if ( is_zero_addr((struct sockaddr *)client_ss) ) {
2345 if ( !resolve_name( remote_machine, &rm_addr, 0x20, false) ) {
2346 DEBUG(2,("spoolss_connect_to_client: Can't resolve address for %s\n", remote_machine));
2350 if (ismyaddr((struct sockaddr *)&rm_addr)) {
2351 DEBUG(0,("spoolss_connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
2355 char addr[INET6_ADDRSTRLEN];
2356 rm_addr = *client_ss;
2357 print_sockaddr(addr, sizeof(addr), &rm_addr);
2358 DEBUG(5,("spoolss_connect_to_client: Using address %s (no name resolution necessary)\n",
2362 /* setup the connection */
2364 ret = cli_full_connection( &the_cli, global_myname(), remote_machine,
2365 &rm_addr, 0, "IPC$", "IPC",
2369 0, lp_client_signing(), NULL );
2371 if ( !NT_STATUS_IS_OK( ret ) ) {
2372 DEBUG(2,("spoolss_connect_to_client: connection to [%s] failed!\n",
2377 if ( the_cli->protocol != PROTOCOL_NT1 ) {
2378 DEBUG(0,("spoolss_connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
2379 cli_shutdown(the_cli);
2384 * Ok - we have an anonymous connection to the IPC$ share.
2385 * Now start the NT Domain stuff :-).
2388 ret = cli_rpc_pipe_open_noauth(the_cli, &ndr_table_spoolss.syntax_id, pp_pipe);
2389 if (!NT_STATUS_IS_OK(ret)) {
2390 DEBUG(2,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n",
2391 remote_machine, nt_errstr(ret)));
2392 cli_shutdown(the_cli);
2399 /***************************************************************************
2400 Connect to the client.
2401 ****************************************************************************/
2403 static bool srv_spoolss_replyopenprinter(int snum, const char *printer,
2404 uint32_t localprinter, uint32_t type,
2405 struct policy_handle *handle,
2406 struct sockaddr_storage *client_ss)
2412 * If it's the first connection, contact the client
2413 * and connect to the IPC$ share anonymously
2415 if (smb_connections==0) {
2416 fstring unix_printer;
2418 fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
2420 if ( !spoolss_connect_to_client( ¬ify_cli_pipe, client_ss, unix_printer ))
2423 messaging_register(smbd_messaging_context(), NULL,
2424 MSG_PRINTER_NOTIFY2,
2425 receive_notify2_message_list);
2426 /* Tell the connections db we're now interested in printer
2427 * notify messages. */
2428 register_message_flags(true, FLAG_MSG_PRINT_NOTIFY);
2432 * Tell the specific printing tdb we want messages for this printer
2433 * by registering our PID.
2436 if (!print_notify_register_pid(snum))
2437 DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
2441 status = rpccli_spoolss_ReplyOpenPrinter(notify_cli_pipe, talloc_tos(),
2449 if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(result))
2450 DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
2451 win_errstr(result)));
2453 return (W_ERROR_IS_OK(result));
2456 /****************************************************************
2457 ****************************************************************/
2459 static struct spoolss_NotifyOption *dup_spoolss_NotifyOption(TALLOC_CTX *mem_ctx,
2460 const struct spoolss_NotifyOption *r)
2462 struct spoolss_NotifyOption *option;
2469 option = talloc_zero(mem_ctx, struct spoolss_NotifyOption);
2476 if (!option->count) {
2480 option->types = talloc_zero_array(option,
2481 struct spoolss_NotifyOptionType, option->count);
2482 if (!option->types) {
2483 talloc_free(option);
2487 for (i=0; i < option->count; i++) {
2488 option->types[i] = r->types[i];
2490 if (option->types[i].count) {
2491 option->types[i].fields = talloc_zero_array(option,
2492 union spoolss_Field, option->types[i].count);
2493 if (!option->types[i].fields) {
2494 talloc_free(option);
2497 for (k=0; k<option->types[i].count; k++) {
2498 option->types[i].fields[k] =
2499 r->types[i].fields[k];
2507 /****************************************************************
2508 * _spoolss_RemoteFindFirstPrinterChangeNotifyEx
2510 * before replying OK: status=0 a rpc call is made to the workstation
2511 * asking ReplyOpenPrinter
2513 * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe
2514 * called from api_spoolss_rffpcnex
2515 ****************************************************************/
2517 WERROR _spoolss_RemoteFindFirstPrinterChangeNotifyEx(pipes_struct *p,
2518 struct spoolss_RemoteFindFirstPrinterChangeNotifyEx *r)
2521 struct spoolss_NotifyOption *option = r->in.notify_options;
2522 struct sockaddr_storage client_ss;
2524 /* store the notify value in the printer struct */
2526 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
2529 DEBUG(2,("_spoolss_RemoteFindFirstPrinterChangeNotifyEx: "
2530 "Invalid handle (%s:%u:%u).\n",
2531 OUR_HANDLE(r->in.handle)));
2535 Printer->notify.flags = r->in.flags;
2536 Printer->notify.options = r->in.options;
2537 Printer->notify.printerlocal = r->in.printer_local;
2539 TALLOC_FREE(Printer->notify.option);
2540 Printer->notify.option = dup_spoolss_NotifyOption(Printer, option);
2542 fstrcpy(Printer->notify.localmachine, r->in.local_machine);
2544 /* Connect to the client machine and send a ReplyOpenPrinter */
2546 if ( Printer->printer_type == SPLHND_SERVER)
2548 else if ( (Printer->printer_type == SPLHND_PRINTER) &&
2549 !get_printer_snum(p, r->in.handle, &snum, NULL) )
2552 if (!interpret_string_addr(&client_ss, p->client_address,
2554 return WERR_SERVER_UNAVAILABLE;
2557 if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
2558 Printer->notify.printerlocal, 1,
2559 &Printer->notify.client_hnd, &client_ss))
2560 return WERR_SERVER_UNAVAILABLE;
2562 Printer->notify.client_connected = true;
2567 /*******************************************************************
2568 * fill a notify_info_data with the servername
2569 ********************************************************************/
2571 void spoolss_notify_server_name(int snum,
2572 struct spoolss_Notify *data,
2573 print_queue_struct *queue,
2574 NT_PRINTER_INFO_LEVEL *printer,
2575 TALLOC_CTX *mem_ctx)
2577 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->servername);
2580 /*******************************************************************
2581 * fill a notify_info_data with the printername (not including the servername).
2582 ********************************************************************/
2584 void spoolss_notify_printer_name(int snum,
2585 struct spoolss_Notify *data,
2586 print_queue_struct *queue,
2587 NT_PRINTER_INFO_LEVEL *printer,
2588 TALLOC_CTX *mem_ctx)
2590 /* the notify name should not contain the \\server\ part */
2591 char *p = strrchr(printer->info_2->printername, '\\');
2594 p = printer->info_2->printername;
2599 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2602 /*******************************************************************
2603 * fill a notify_info_data with the servicename
2604 ********************************************************************/
2606 void spoolss_notify_share_name(int snum,
2607 struct spoolss_Notify *data,
2608 print_queue_struct *queue,
2609 NT_PRINTER_INFO_LEVEL *printer,
2610 TALLOC_CTX *mem_ctx)
2612 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, lp_servicename(snum));
2615 /*******************************************************************
2616 * fill a notify_info_data with the port name
2617 ********************************************************************/
2619 void spoolss_notify_port_name(int snum,
2620 struct spoolss_Notify *data,
2621 print_queue_struct *queue,
2622 NT_PRINTER_INFO_LEVEL *printer,
2623 TALLOC_CTX *mem_ctx)
2625 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->portname);
2628 /*******************************************************************
2629 * fill a notify_info_data with the printername
2630 * but it doesn't exist, have to see what to do
2631 ********************************************************************/
2633 void spoolss_notify_driver_name(int snum,
2634 struct spoolss_Notify *data,
2635 print_queue_struct *queue,
2636 NT_PRINTER_INFO_LEVEL *printer,
2637 TALLOC_CTX *mem_ctx)
2639 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->drivername);
2642 /*******************************************************************
2643 * fill a notify_info_data with the comment
2644 ********************************************************************/
2646 void spoolss_notify_comment(int snum,
2647 struct spoolss_Notify *data,
2648 print_queue_struct *queue,
2649 NT_PRINTER_INFO_LEVEL *printer,
2650 TALLOC_CTX *mem_ctx)
2654 if (*printer->info_2->comment == '\0') {
2655 p = lp_comment(snum);
2657 p = printer->info_2->comment;
2660 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->comment);
2663 /*******************************************************************
2664 * fill a notify_info_data with the comment
2665 * location = "Room 1, floor 2, building 3"
2666 ********************************************************************/
2668 void spoolss_notify_location(int snum,
2669 struct spoolss_Notify *data,
2670 print_queue_struct *queue,
2671 NT_PRINTER_INFO_LEVEL *printer,
2672 TALLOC_CTX *mem_ctx)
2674 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->location);
2677 /*******************************************************************
2678 * fill a notify_info_data with the device mode
2679 * jfm:xxxx don't to it for know but that's a real problem !!!
2680 ********************************************************************/
2682 static void spoolss_notify_devmode(int snum,
2683 struct spoolss_Notify *data,
2684 print_queue_struct *queue,
2685 NT_PRINTER_INFO_LEVEL *printer,
2686 TALLOC_CTX *mem_ctx)
2688 /* for a dummy implementation we have to zero the fields */
2689 SETUP_SPOOLSS_NOTIFY_DATA_DEVMODE(data, NULL);
2692 /*******************************************************************
2693 * fill a notify_info_data with the separator file name
2694 ********************************************************************/
2696 void spoolss_notify_sepfile(int snum,
2697 struct spoolss_Notify *data,
2698 print_queue_struct *queue,
2699 NT_PRINTER_INFO_LEVEL *printer,
2700 TALLOC_CTX *mem_ctx)
2702 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->sepfile);
2705 /*******************************************************************
2706 * fill a notify_info_data with the print processor
2707 * jfm:xxxx return always winprint to indicate we don't do anything to it
2708 ********************************************************************/
2710 void spoolss_notify_print_processor(int snum,
2711 struct spoolss_Notify *data,
2712 print_queue_struct *queue,
2713 NT_PRINTER_INFO_LEVEL *printer,
2714 TALLOC_CTX *mem_ctx)
2716 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->printprocessor);
2719 /*******************************************************************
2720 * fill a notify_info_data with the print processor options
2721 * jfm:xxxx send an empty string
2722 ********************************************************************/
2724 void spoolss_notify_parameters(int snum,
2725 struct spoolss_Notify *data,
2726 print_queue_struct *queue,
2727 NT_PRINTER_INFO_LEVEL *printer,
2728 TALLOC_CTX *mem_ctx)
2730 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->parameters);
2733 /*******************************************************************
2734 * fill a notify_info_data with the data type
2735 * jfm:xxxx always send RAW as data type
2736 ********************************************************************/
2738 void spoolss_notify_datatype(int snum,
2739 struct spoolss_Notify *data,
2740 print_queue_struct *queue,
2741 NT_PRINTER_INFO_LEVEL *printer,
2742 TALLOC_CTX *mem_ctx)
2744 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, printer->info_2->datatype);
2747 /*******************************************************************
2748 * fill a notify_info_data with the security descriptor
2749 * jfm:xxxx send an null pointer to say no security desc
2750 * have to implement security before !
2751 ********************************************************************/
2753 static void spoolss_notify_security_desc(int snum,
2754 struct spoolss_Notify *data,
2755 print_queue_struct *queue,
2756 NT_PRINTER_INFO_LEVEL *printer,
2757 TALLOC_CTX *mem_ctx)
2759 SETUP_SPOOLSS_NOTIFY_DATA_SECDESC(data,
2760 printer->info_2->secdesc_buf->sd_size,
2761 printer->info_2->secdesc_buf->sd);
2764 /*******************************************************************
2765 * fill a notify_info_data with the attributes
2766 * jfm:xxxx a samba printer is always shared
2767 ********************************************************************/
2769 void spoolss_notify_attributes(int snum,
2770 struct spoolss_Notify *data,
2771 print_queue_struct *queue,
2772 NT_PRINTER_INFO_LEVEL *printer,
2773 TALLOC_CTX *mem_ctx)
2775 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->attributes);
2778 /*******************************************************************
2779 * fill a notify_info_data with the priority
2780 ********************************************************************/
2782 static void spoolss_notify_priority(int snum,
2783 struct spoolss_Notify *data,
2784 print_queue_struct *queue,
2785 NT_PRINTER_INFO_LEVEL *printer,
2786 TALLOC_CTX *mem_ctx)
2788 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->priority);
2791 /*******************************************************************
2792 * fill a notify_info_data with the default priority
2793 ********************************************************************/
2795 static void spoolss_notify_default_priority(int snum,
2796 struct spoolss_Notify *data,
2797 print_queue_struct *queue,
2798 NT_PRINTER_INFO_LEVEL *printer,
2799 TALLOC_CTX *mem_ctx)
2801 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->default_priority);
2804 /*******************************************************************
2805 * fill a notify_info_data with the start time
2806 ********************************************************************/
2808 static void spoolss_notify_start_time(int snum,
2809 struct spoolss_Notify *data,
2810 print_queue_struct *queue,
2811 NT_PRINTER_INFO_LEVEL *printer,
2812 TALLOC_CTX *mem_ctx)
2814 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->starttime);
2817 /*******************************************************************
2818 * fill a notify_info_data with the until time
2819 ********************************************************************/
2821 static void spoolss_notify_until_time(int snum,
2822 struct spoolss_Notify *data,
2823 print_queue_struct *queue,
2824 NT_PRINTER_INFO_LEVEL *printer,
2825 TALLOC_CTX *mem_ctx)
2827 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->untiltime);
2830 /*******************************************************************
2831 * fill a notify_info_data with the status
2832 ********************************************************************/
2834 static void spoolss_notify_status(int snum,
2835 struct spoolss_Notify *data,
2836 print_queue_struct *queue,
2837 NT_PRINTER_INFO_LEVEL *printer,
2838 TALLOC_CTX *mem_ctx)
2840 print_status_struct status;
2842 print_queue_length(snum, &status);
2843 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, status.status);
2846 /*******************************************************************
2847 * fill a notify_info_data with the number of jobs queued
2848 ********************************************************************/
2850 void spoolss_notify_cjobs(int snum,
2851 struct spoolss_Notify *data,
2852 print_queue_struct *queue,
2853 NT_PRINTER_INFO_LEVEL *printer,
2854 TALLOC_CTX *mem_ctx)
2856 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, print_queue_length(snum, NULL));
2859 /*******************************************************************
2860 * fill a notify_info_data with the average ppm
2861 ********************************************************************/
2863 static void spoolss_notify_average_ppm(int snum,
2864 struct spoolss_Notify *data,
2865 print_queue_struct *queue,
2866 NT_PRINTER_INFO_LEVEL *printer,
2867 TALLOC_CTX *mem_ctx)
2869 /* always respond 8 pages per minutes */
2870 /* a little hard ! */
2871 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, printer->info_2->averageppm);
2874 /*******************************************************************
2875 * fill a notify_info_data with username
2876 ********************************************************************/
2878 static void spoolss_notify_username(int snum,
2879 struct spoolss_Notify *data,
2880 print_queue_struct *queue,
2881 NT_PRINTER_INFO_LEVEL *printer,
2882 TALLOC_CTX *mem_ctx)
2884 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_user);
2887 /*******************************************************************
2888 * fill a notify_info_data with job status
2889 ********************************************************************/
2891 static void spoolss_notify_job_status(int snum,
2892 struct spoolss_Notify *data,
2893 print_queue_struct *queue,
2894 NT_PRINTER_INFO_LEVEL *printer,
2895 TALLOC_CTX *mem_ctx)
2897 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, nt_printj_status(queue->status));
2900 /*******************************************************************
2901 * fill a notify_info_data with job name
2902 ********************************************************************/
2904 static void spoolss_notify_job_name(int snum,
2905 struct spoolss_Notify *data,
2906 print_queue_struct *queue,
2907 NT_PRINTER_INFO_LEVEL *printer,
2908 TALLOC_CTX *mem_ctx)
2910 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, queue->fs_file);
2913 /*******************************************************************
2914 * fill a notify_info_data with job status
2915 ********************************************************************/
2917 static void spoolss_notify_job_status_string(int snum,
2918 struct spoolss_Notify *data,
2919 print_queue_struct *queue,
2920 NT_PRINTER_INFO_LEVEL *printer,
2921 TALLOC_CTX *mem_ctx)
2924 * Now we're returning job status codes we just return a "" here. JRA.
2929 #if 0 /* NO LONGER NEEDED - JRA. 02/22/2001 */
2932 switch (queue->status) {
2937 p = ""; /* NT provides the paused string */
2946 #endif /* NO LONGER NEEDED. */
2948 SETUP_SPOOLSS_NOTIFY_DATA_STRING(data, p);
2951 /*******************************************************************
2952 * fill a notify_info_data with job time
2953 ********************************************************************/
2955 static void spoolss_notify_job_time(int snum,
2956 struct spoolss_Notify *data,
2957 print_queue_struct *queue,
2958 NT_PRINTER_INFO_LEVEL *printer,
2959 TALLOC_CTX *mem_ctx)
2961 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
2964 /*******************************************************************
2965 * fill a notify_info_data with job size
2966 ********************************************************************/
2968 static void spoolss_notify_job_size(int snum,
2969 struct spoolss_Notify *data,
2970 print_queue_struct *queue,
2971 NT_PRINTER_INFO_LEVEL *printer,
2972 TALLOC_CTX *mem_ctx)
2974 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->size);
2977 /*******************************************************************
2978 * fill a notify_info_data with page info
2979 ********************************************************************/
2980 static void spoolss_notify_total_pages(int snum,
2981 struct spoolss_Notify *data,
2982 print_queue_struct *queue,
2983 NT_PRINTER_INFO_LEVEL *printer,
2984 TALLOC_CTX *mem_ctx)
2986 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->page_count);
2989 /*******************************************************************
2990 * fill a notify_info_data with pages printed info.
2991 ********************************************************************/
2992 static void spoolss_notify_pages_printed(int snum,
2993 struct spoolss_Notify *data,
2994 print_queue_struct *queue,
2995 NT_PRINTER_INFO_LEVEL *printer,
2996 TALLOC_CTX *mem_ctx)
2998 /* Add code when back-end tracks this */
2999 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, 0);
3002 /*******************************************************************
3003 Fill a notify_info_data with job position.
3004 ********************************************************************/
3006 static void spoolss_notify_job_position(int snum,
3007 struct spoolss_Notify *data,
3008 print_queue_struct *queue,
3009 NT_PRINTER_INFO_LEVEL *printer,
3010 TALLOC_CTX *mem_ctx)
3012 SETUP_SPOOLSS_NOTIFY_DATA_INTEGER(data, queue->job);
3015 /*******************************************************************
3016 Fill a notify_info_data with submitted time.
3017 ********************************************************************/
3019 static void spoolss_notify_submitted_time(int snum,
3020 struct spoolss_Notify *data,
3021 print_queue_struct *queue,
3022 NT_PRINTER_INFO_LEVEL *printer,
3023 TALLOC_CTX *mem_ctx)
3025 data->data.string.string = NULL;
3026 data->data.string.size = 0;
3028 init_systemtime_buffer(mem_ctx, gmtime(&queue->time),
3029 &data->data.string.string,
3030 &data->data.string.size);
3034 struct s_notify_info_data_table
3036 enum spoolss_NotifyType type;
3039 enum spoolss_NotifyTable variable_type;
3040 void (*fn) (int snum, struct spoolss_Notify *data,
3041 print_queue_struct *queue,
3042 NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx);
3045 /* A table describing the various print notification constants and
3046 whether the notification data is a pointer to a variable sized
3047 buffer, a one value uint32_t or a two value uint32_t. */
3049 static const struct s_notify_info_data_table notify_info_data_table[] =
3051 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SERVER_NAME, "PRINTER_NOTIFY_FIELD_SERVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3052 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINTER_NAME, "PRINTER_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3053 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SHARE_NAME, "PRINTER_NOTIFY_FIELD_SHARE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_share_name },
3054 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PORT_NAME, "PRINTER_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3055 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DRIVER_NAME, "PRINTER_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3056 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_COMMENT, "PRINTER_NOTIFY_FIELD_COMMENT", NOTIFY_TABLE_STRING, spoolss_notify_comment },
3057 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_LOCATION, "PRINTER_NOTIFY_FIELD_LOCATION", NOTIFY_TABLE_STRING, spoolss_notify_location },
3058 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEVMODE, "PRINTER_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3059 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SEPFILE, "PRINTER_NOTIFY_FIELD_SEPFILE", NOTIFY_TABLE_STRING, spoolss_notify_sepfile },
3060 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR, "PRINTER_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3061 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PARAMETERS, "PRINTER_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3062 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DATATYPE, "PRINTER_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3063 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, spoolss_notify_security_desc },
3064 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_ATTRIBUTES, "PRINTER_NOTIFY_FIELD_ATTRIBUTES", NOTIFY_TABLE_DWORD, spoolss_notify_attributes },
3065 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PRIORITY, "PRINTER_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3066 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY, "PRINTER_NOTIFY_FIELD_DEFAULT_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_default_priority },
3067 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_START_TIME, "PRINTER_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3068 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_UNTIL_TIME, "PRINTER_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3069 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS, "PRINTER_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_status },
3070 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_STATUS_STRING, "PRINTER_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, NULL },
3071 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_CJOBS, "PRINTER_NOTIFY_FIELD_CJOBS", NOTIFY_TABLE_DWORD, spoolss_notify_cjobs },
3072 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_AVERAGE_PPM, "PRINTER_NOTIFY_FIELD_AVERAGE_PPM", NOTIFY_TABLE_DWORD, spoolss_notify_average_ppm },
3073 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_PAGES, "PRINTER_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, NULL },
3074 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_PAGES_PRINTED, "PRINTER_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3075 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_TOTAL_BYTES, "PRINTER_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, NULL },
3076 { PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_FIELD_BYTES_PRINTED, "PRINTER_NOTIFY_FIELD_BYTES_PRINTED", NOTIFY_TABLE_DWORD, NULL },
3077 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINTER_NAME, "JOB_NOTIFY_FIELD_PRINTER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_printer_name },
3078 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_MACHINE_NAME, "JOB_NOTIFY_FIELD_MACHINE_NAME", NOTIFY_TABLE_STRING, spoolss_notify_server_name },
3079 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PORT_NAME, "JOB_NOTIFY_FIELD_PORT_NAME", NOTIFY_TABLE_STRING, spoolss_notify_port_name },
3080 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_USER_NAME, "JOB_NOTIFY_FIELD_USER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3081 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_NOTIFY_NAME, "JOB_NOTIFY_FIELD_NOTIFY_NAME", NOTIFY_TABLE_STRING, spoolss_notify_username },
3082 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DATATYPE, "JOB_NOTIFY_FIELD_DATATYPE", NOTIFY_TABLE_STRING, spoolss_notify_datatype },
3083 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRINT_PROCESSOR, "JOB_NOTIFY_FIELD_PRINT_PROCESSOR", NOTIFY_TABLE_STRING, spoolss_notify_print_processor },
3084 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PARAMETERS, "JOB_NOTIFY_FIELD_PARAMETERS", NOTIFY_TABLE_STRING, spoolss_notify_parameters },
3085 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DRIVER_NAME, "JOB_NOTIFY_FIELD_DRIVER_NAME", NOTIFY_TABLE_STRING, spoolss_notify_driver_name },
3086 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DEVMODE, "JOB_NOTIFY_FIELD_DEVMODE", NOTIFY_TABLE_DEVMODE, spoolss_notify_devmode },
3087 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS, "JOB_NOTIFY_FIELD_STATUS", NOTIFY_TABLE_DWORD, spoolss_notify_job_status },
3088 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_STATUS_STRING, "JOB_NOTIFY_FIELD_STATUS_STRING", NOTIFY_TABLE_STRING, spoolss_notify_job_status_string },
3089 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR, "JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR", NOTIFY_TABLE_SECURITYDESCRIPTOR, NULL },
3090 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_DOCUMENT, "JOB_NOTIFY_FIELD_DOCUMENT", NOTIFY_TABLE_STRING, spoolss_notify_job_name },
3091 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PRIORITY, "JOB_NOTIFY_FIELD_PRIORITY", NOTIFY_TABLE_DWORD, spoolss_notify_priority },
3092 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_POSITION, "JOB_NOTIFY_FIELD_POSITION", NOTIFY_TABLE_DWORD, spoolss_notify_job_position },
3093 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_SUBMITTED, "JOB_NOTIFY_FIELD_SUBMITTED", NOTIFY_TABLE_TIME, spoolss_notify_submitted_time },
3094 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_START_TIME, "JOB_NOTIFY_FIELD_START_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_start_time },
3095 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_UNTIL_TIME, "JOB_NOTIFY_FIELD_UNTIL_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_until_time },
3096 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TIME, "JOB_NOTIFY_FIELD_TIME", NOTIFY_TABLE_DWORD, spoolss_notify_job_time },
3097 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_PAGES, "JOB_NOTIFY_FIELD_TOTAL_PAGES", NOTIFY_TABLE_DWORD, spoolss_notify_total_pages },
3098 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_PAGES_PRINTED, "JOB_NOTIFY_FIELD_PAGES_PRINTED", NOTIFY_TABLE_DWORD, spoolss_notify_pages_printed },
3099 { JOB_NOTIFY_TYPE, JOB_NOTIFY_FIELD_TOTAL_BYTES, "JOB_NOTIFY_FIELD_TOTAL_BYTES", NOTIFY_TABLE_DWORD, spoolss_notify_job_size },
3102 /*******************************************************************
3103 Return the variable_type of info_data structure.
3104 ********************************************************************/
3106 static uint32_t variable_type_of_notify_info_data(enum spoolss_NotifyType type,
3111 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3112 if ( (notify_info_data_table[i].type == type) &&
3113 (notify_info_data_table[i].field == field) ) {
3114 return notify_info_data_table[i].variable_type;
3118 DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
3123 /****************************************************************************
3124 ****************************************************************************/
3126 static bool search_notify(enum spoolss_NotifyType type,
3132 for (i = 0; i < ARRAY_SIZE(notify_info_data_table); i++) {
3133 if (notify_info_data_table[i].type == type &&
3134 notify_info_data_table[i].field == field &&
3135 notify_info_data_table[i].fn != NULL) {
3144 /****************************************************************************
3145 ****************************************************************************/
3147 void construct_info_data(struct spoolss_Notify *info_data,
3148 enum spoolss_NotifyType type,
3152 info_data->type = type;
3153 info_data->field.field = field;
3154 info_data->variable_type = variable_type_of_notify_info_data(type, field);
3155 info_data->job_id = id;
3158 /*******************************************************************
3160 * fill a notify_info struct with info asked
3162 ********************************************************************/
3164 static bool construct_notify_printer_info(Printer_entry *print_hnd,
3165 struct spoolss_NotifyInfo *info,
3167 const struct spoolss_NotifyOptionType *option_type,
3169 TALLOC_CTX *mem_ctx)
3172 enum spoolss_NotifyType type;
3175 struct spoolss_Notify *current_data;
3176 NT_PRINTER_INFO_LEVEL *printer = NULL;
3177 print_queue_struct *queue=NULL;
3179 type = option_type->type;
3181 DEBUG(4,("construct_notify_printer_info: Notify type: [%s], number of notify info: [%d] on printer: [%s]\n",
3182 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3183 option_type->count, lp_servicename(snum)));
3185 if (!W_ERROR_IS_OK(get_a_printer(print_hnd, &printer, 2, lp_const_servicename(snum))))
3188 for(field_num=0; field_num < option_type->count; field_num++) {
3189 field = option_type->fields[field_num].field;
3191 DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
3193 if (!search_notify(type, field, &j) )
3196 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3197 struct spoolss_Notify,
3199 if (info->notifies == NULL) {
3200 DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
3201 free_a_printer(&printer, 2);
3205 current_data = &info->notifies[info->count];
3207 construct_info_data(current_data, type, field, id);
3209 DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
3210 notify_info_data_table[j].name, snum, printer->info_2->printername ));
3212 notify_info_data_table[j].fn(snum, current_data, queue,
3218 free_a_printer(&printer, 2);
3222 /*******************************************************************
3224 * fill a notify_info struct with info asked
3226 ********************************************************************/
3228 static bool construct_notify_jobs_info(print_queue_struct *queue,
3229 struct spoolss_NotifyInfo *info,
3230 NT_PRINTER_INFO_LEVEL *printer,
3232 const struct spoolss_NotifyOptionType *option_type,
3234 TALLOC_CTX *mem_ctx)
3237 enum spoolss_NotifyType type;
3239 struct spoolss_Notify *current_data;
3241 DEBUG(4,("construct_notify_jobs_info\n"));
3243 type = option_type->type;
3245 DEBUGADD(4,("Notify type: [%s], number of notify info: [%d]\n",
3246 (type == PRINTER_NOTIFY_TYPE ? "PRINTER_NOTIFY_TYPE" : "JOB_NOTIFY_TYPE"),
3247 option_type->count));
3249 for(field_num=0; field_num<option_type->count; field_num++) {
3250 field = option_type->fields[field_num].field;
3252 if (!search_notify(type, field, &j) )
3255 info->notifies = TALLOC_REALLOC_ARRAY(info, info->notifies,
3256 struct spoolss_Notify,
3258 if (info->notifies == NULL) {
3259 DEBUG(2,("construct_notify_jobs_info: failed to enlarg buffer info->data!\n"));
3263 current_data=&(info->notifies[info->count]);
3265 construct_info_data(current_data, type, field, id);
3266 notify_info_data_table[j].fn(snum, current_data, queue,
3275 * JFM: The enumeration is not that simple, it's even non obvious.
3277 * let's take an example: I want to monitor the PRINTER SERVER for
3278 * the printer's name and the number of jobs currently queued.
3279 * So in the NOTIFY_OPTION, I have one NOTIFY_OPTION_TYPE structure.
3280 * Its type is PRINTER_NOTIFY_TYPE and it has 2 fields NAME and CJOBS.
3282 * I have 3 printers on the back of my server.
3284 * Now the response is a NOTIFY_INFO structure, with 6 NOTIFY_INFO_DATA
3287 * 1 printer 1 name 1
3288 * 2 printer 1 cjob 1
3289 * 3 printer 2 name 2
3290 * 4 printer 2 cjob 2
3291 * 5 printer 3 name 3
3292 * 6 printer 3 name 3
3294 * that's the print server case, the printer case is even worse.
3297 /*******************************************************************
3299 * enumerate all printers on the printserver
3300 * fill a notify_info struct with info asked
3302 ********************************************************************/
3304 static WERROR printserver_notify_info(pipes_struct *p,
3305 struct policy_handle *hnd,
3306 struct spoolss_NotifyInfo *info,
3307 TALLOC_CTX *mem_ctx)
3310 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3311 int n_services=lp_numservices();
3313 struct spoolss_NotifyOption *option;
3314 struct spoolss_NotifyOptionType option_type;
3316 DEBUG(4,("printserver_notify_info\n"));
3321 option = Printer->notify.option;
3324 info->notifies = NULL;
3327 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3328 sending a ffpcn() request first */
3333 for (i=0; i<option->count; i++) {
3334 option_type = option->types[i];
3336 if (option_type.type != PRINTER_NOTIFY_TYPE)
3339 for (snum=0; snum<n_services; snum++)
3341 if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
3342 construct_notify_printer_info ( Printer, info, snum, &option_type, snum, mem_ctx );
3348 * Debugging information, don't delete.
3351 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3352 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3353 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3355 for (i=0; i<info->count; i++) {
3356 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3357 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3358 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3365 /*******************************************************************
3367 * fill a notify_info struct with info asked
3369 ********************************************************************/
3371 static WERROR printer_notify_info(pipes_struct *p, struct policy_handle *hnd,
3372 struct spoolss_NotifyInfo *info,
3373 TALLOC_CTX *mem_ctx)
3376 Printer_entry *Printer = find_printer_index_by_hnd(p, hnd);
3379 struct spoolss_NotifyOption *option;
3380 struct spoolss_NotifyOptionType option_type;
3382 print_queue_struct *queue=NULL;
3383 print_status_struct status;
3385 DEBUG(4,("printer_notify_info\n"));
3390 option = Printer->notify.option;
3394 info->notifies = NULL;
3397 /* a bug in xp sp2 rc2 causes it to send a fnpcn request without
3398 sending a ffpcn() request first */
3403 get_printer_snum(p, hnd, &snum, NULL);
3405 for (i=0; i<option->count; i++) {
3406 option_type = option->types[i];
3408 switch (option_type.type) {
3409 case PRINTER_NOTIFY_TYPE:
3410 if(construct_notify_printer_info(Printer, info, snum,
3416 case JOB_NOTIFY_TYPE: {
3417 NT_PRINTER_INFO_LEVEL *printer = NULL;
3419 count = print_queue_status(snum, &queue, &status);
3421 if (!W_ERROR_IS_OK(get_a_printer(Printer, &printer, 2, lp_const_servicename(snum))))
3424 for (j=0; j<count; j++) {
3425 construct_notify_jobs_info(&queue[j], info,
3432 free_a_printer(&printer, 2);
3442 * Debugging information, don't delete.
3445 DEBUG(1,("dumping the NOTIFY_INFO\n"));
3446 DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
3447 DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
3449 for (i=0; i<info->count; i++) {
3450 DEBUGADD(1,("[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\t[%d]\n",
3451 i, info->data[i].type, info->data[i].field, info->data[i].reserved,
3452 info->data[i].id, info->data[i].size, info->data[i].enc_type));
3458 /****************************************************************
3459 _spoolss_RouterRefreshPrinterChangeNotify
3460 ****************************************************************/
3462 WERROR _spoolss_RouterRefreshPrinterChangeNotify(pipes_struct *p,
3463 struct spoolss_RouterRefreshPrinterChangeNotify *r)
3465 struct spoolss_NotifyInfo *info;
3467 Printer_entry *Printer = find_printer_index_by_hnd(p, r->in.handle);
3468 WERROR result = WERR_BADFID;
3470 /* we always have a spoolss_NotifyInfo struct */
3471 info = talloc_zero(p->mem_ctx, struct spoolss_NotifyInfo);
3473 result = WERR_NOMEM;
3477 *r->out.info = info;
3480 DEBUG(2,("_spoolss_RouterRefreshPrinterChangeNotify: "
3481 "Invalid handle (%s:%u:%u).\n",
3482 OUR_HANDLE(r->in.handle)));
3486 DEBUG(4,("Printer type %x\n",Printer->printer_type));
3489 * We are now using the change value, and
3490 * I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
3491 * I don't have a global notification system, I'm sending back all the
3492 * informations even when _NOTHING_ has changed.
3495 /* We need to keep track of the change value to send back in
3496 RRPCN replies otherwise our updates are ignored. */
3498 Printer->notify.fnpcn = true;
3500 if (Printer->notify.client_connected) {
3501 DEBUG(10,("_spoolss_RouterRefreshPrinterChangeNotify: "
3502 "Saving change value in request [%x]\n",
3504 Printer->notify.change = r->in.change_low;
3507 /* just ignore the spoolss_NotifyOption */
3509 switch (Printer->printer_type) {
3511 result = printserver_notify_info(p, r->in.handle,
3515 case SPLHND_PRINTER:
3516 result = printer_notify_info(p, r->in.handle,
3521 Printer->notify.fnpcn = false;
3527 /********************************************************************
3528 * construct_printer_info_0
3529 * fill a printer_info_0 struct
3530 ********************************************************************/
3532 static WERROR construct_printer_info0(TALLOC_CTX *mem_ctx,
3533 const NT_PRINTER_INFO_LEVEL *ntprinter,
3534 struct spoolss_PrinterInfo0 *r,
3538 counter_printer_0 *session_counter;
3540 print_status_struct status;
3542 r->printername = talloc_strdup(mem_ctx, ntprinter->info_2->printername);
3543 W_ERROR_HAVE_NO_MEMORY(r->printername);
3545 r->servername = talloc_strdup(mem_ctx, ntprinter->info_2->servername);
3546 W_ERROR_HAVE_NO_MEMORY(r->servername);
3548 count = print_queue_length(snum, &status);
3550 /* check if we already have a counter for this printer */
3551 for (session_counter = counter_list; session_counter; session_counter = session_counter->next) {
3552 if (session_counter->snum == snum)
3556 /* it's the first time, add it to the list */
3557 if (session_counter == NULL) {
3558 session_counter = SMB_MALLOC_P(counter_printer_0);
3559 W_ERROR_HAVE_NO_MEMORY(session_counter);
3560 ZERO_STRUCTP(session_counter);