diff options
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 289 |
1 files changed, 162 insertions, 127 deletions
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 75d7ac7164..6bbd26b0a8 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -1082,168 +1082,203 @@ static void construct_info_data(struct spoolss_Notify *info_data, back registered **********************************************************************/ -static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx ) -{ - struct printer_handle *p; - TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr ); - SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx ); - SPOOLSS_NOTIFY_MSG *messages; - int sending_msg_count; +static int build_notify2_messages(TALLOC_CTX *mem_ctx, + struct printer_handle *prn_hnd, + SPOOLSS_NOTIFY_MSG *messages, + uint32_t num_msgs, + struct spoolss_Notify **_notifies, + int *_count) +{ + struct spoolss_Notify *notifies; + SPOOLSS_NOTIFY_MSG *msg; + int count = 0; + uint32_t id; + int i; - if ( !msg_group ) { - DEBUG(5,("send_notify2_changes() called with no msg group!\n")); - return; + notifies = talloc_zero_array(mem_ctx, + struct spoolss_Notify, num_msgs); + if (!notifies) { + return ENOMEM; } - messages = msg_group->msgs; + for (i = 0; i < num_msgs; i++) { - if ( !messages ) { - DEBUG(5,("send_notify2_changes() called with no messages!\n")); - return; - } + msg = &messages[i]; - DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername)); + /* Are we monitoring this event? */ - /* loop over all printers */ + if (!is_monitoring_event(prn_hnd, msg->type, msg->field)) { + continue; + } - for (p = printers_list; p; p = p->next) { - struct spoolss_Notify *notifies; - uint32_t count = 0; - uint32_t id; - int i; + DEBUG(10, ("Sending message type [0x%x] field [0x%2x] " + "for printer [%s]\n", + msg->type, msg->field, prn_hnd->sharename)); - /* Is there notification on this handle? */ + /* + * if the is a printer notification handle and not a job + * notification type, then set the id to 0. + * Otherwise just use what was specified in the message. + * + * When registering change notification on a print server + * handle we always need to send back the id (snum) matching + * the printer for which the change took place. + * For change notify registered on a printer handle, + * this does not matter and the id should be 0. + * + * --jerry + */ - if ( !p->notify.client_connected ) - continue; + if ((msg->type == PRINTER_NOTIFY_TYPE) && + (prn_hnd->printer_type == SPLHND_PRINTER)) { + id = 0; + } else { + id = msg->id; + } - DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename)); + /* Convert unix jobid to smb jobid */ - /* For this printer? Print servers always receive - notifications. */ + if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) { + id = sysjob_to_jobid(msg->id); - if ( ( p->printer_type == SPLHND_PRINTER ) && - ( !strequal(msg_group->printername, p->sharename) ) ) - continue; + if (id == -1) { + DEBUG(3, ("no such unix jobid %d\n", + msg->id)); + continue; + } + } - DEBUG(10,("Our printer\n")); + construct_info_data(¬ifies[count], + msg->type, msg->field, id); - /* allocate the max entries possible */ + switch(msg->type) { + case PRINTER_NOTIFY_TYPE: + if (printer_notify_table[msg->field].fn) { + printer_notify_table[msg->field].fn(msg, + ¬ifies[count], mem_ctx); + } + break; - notifies = TALLOC_ZERO_ARRAY(mem_ctx, struct spoolss_Notify, msg_group->num_msgs); - if (!notifies) { - return; - } + case JOB_NOTIFY_TYPE: + if (job_notify_table[msg->field].fn) { + job_notify_table[msg->field].fn(msg, + ¬ifies[count], mem_ctx); + } + break; - /* build the array of change notifications */ + default: + DEBUG(5, ("Unknown notification type %d\n", + msg->type)); + continue; + } - sending_msg_count = 0; + count++; + } - for ( i=0; i<msg_group->num_msgs; i++ ) { - SPOOLSS_NOTIFY_MSG *msg = &messages[i]; + *_notifies = notifies; + *_count = count; - /* Are we monitoring this event? */ + return 0; +} - if (!is_monitoring_event(p, msg->type, msg->field)) - continue; +static int send_notify2_printer(TALLOC_CTX *mem_ctx, + struct printer_handle *prn_hnd, + SPOOLSS_NOTIFY_MSG_GROUP *msg_group) +{ + struct spoolss_Notify *notifies; + int count = 0; + union spoolss_ReplyPrinterInfo info; + struct spoolss_NotifyInfo info0; + uint32_t reply_result; + NTSTATUS status; + WERROR werr; + int ret; - sending_msg_count++; + /* Is there notification on this handle? */ + if (!prn_hnd->notify.client_connected) { + return 0; + } + DEBUG(10, ("Client connected! [\\\\%s\\%s]\n", + prn_hnd->servername, prn_hnd->sharename)); - DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n", - msg->type, msg->field, p->sharename)); + /* For this printer? Print servers always receive notifications. */ + if ((prn_hnd->printer_type == SPLHND_PRINTER) && + (!strequal(msg_group->printername, prn_hnd->sharename))) { + return 0; + } - /* - * if the is a printer notification handle and not a job notification - * type, then set the id to 0. Other wise just use what was specified - * in the message. - * - * When registering change notification on a print server handle - * we always need to send back the id (snum) matching the printer - * for which the change took place. For change notify registered - * on a printer handle, this does not matter and the id should be 0. - * - * --jerry - */ + DEBUG(10,("Our printer\n")); - if ( ( p->printer_type == SPLHND_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) ) - id = 0; - else - id = msg->id; + /* build the array of change notifications */ + ret = build_notify2_messages(mem_ctx, prn_hnd, + msg_group->msgs, + msg_group->num_msgs, + ¬ifies, &count); + if (ret) { + return ret; + } + info0.version = 0x2; + info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED; + info0.count = count; + info0.notifies = notifies; - /* Convert unix jobid to smb jobid */ + info.info0 = &info0; - if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) { - id = sysjob_to_jobid(msg->id); + status = rpccli_spoolss_RouterReplyPrinterEx( + back_channel.cli_pipe, mem_ctx, + &prn_hnd->notify.client_hnd, + prn_hnd->notify.change, /* color */ + prn_hnd->notify.flags, + &reply_result, + 0, /* reply_type, must be 0 */ + info, &werr); + if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) { + DEBUG(1, ("RouterReplyPrinterEx to client: %s " + "failed: %s\n", + back_channel.cli_pipe->srv_name_slash, + win_errstr(werr))); + } + switch (reply_result) { + case 0: + break; + case PRINTER_NOTIFY_INFO_DISCARDED: + case PRINTER_NOTIFY_INFO_DISCARDNOTED: + case PRINTER_NOTIFY_INFO_COLOR_MISMATCH: + break; + default: + break; + } - if (id == -1) { - DEBUG(3, ("no such unix jobid %d\n", msg->id)); - goto done; - } - } + return 0; +} - construct_info_data(¬ifies[count], - (enum spoolss_NotifyType) msg->type, - msg->field, - id); +static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32_t idx ) +{ + struct printer_handle *p; + TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr ); + SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, idx ); + int ret; - switch(msg->type) { - case PRINTER_NOTIFY_TYPE: - if ( printer_notify_table[msg->field].fn ) - printer_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx); - break; + if ( !msg_group ) { + DEBUG(5,("send_notify2_changes() called with no msg group!\n")); + return; + } - case JOB_NOTIFY_TYPE: - if ( job_notify_table[msg->field].fn ) - job_notify_table[msg->field].fn(msg, ¬ifies[count], mem_ctx); - break; + if (!msg_group->msgs) { + DEBUG(5, ("send_notify2_changes() called with no messages!\n")); + return; + } - default: - DEBUG(5, ("Unknown notification type %d\n", msg->type)); - goto done; - } + DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername)); - count++; - } + /* loop over all printers */ - if ( sending_msg_count ) { - NTSTATUS status; - WERROR werr; - union spoolss_ReplyPrinterInfo info; - struct spoolss_NotifyInfo info0; - uint32_t reply_result; - - info0.version = 0x2; - info0.flags = count ? 0x00020000 /* ??? */ : PRINTER_NOTIFY_INFO_DISCARDED; - info0.count = count; - info0.notifies = notifies; - - info.info0 = &info0; - - status = rpccli_spoolss_RouterReplyPrinterEx(back_channel.cli_pipe, mem_ctx, - &p->notify.client_hnd, - p->notify.change, /* color */ - p->notify.flags, - &reply_result, - 0, /* reply_type, must be 0 */ - info, - &werr); - if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) { - DEBUG(1,("RouterReplyPrinterEx to client: %s failed: %s\n", - back_channel.cli_pipe->srv_name_slash, - win_errstr(werr))); - } - switch (reply_result) { - case 0: - break; - case PRINTER_NOTIFY_INFO_DISCARDED: - case PRINTER_NOTIFY_INFO_DISCARDNOTED: - case PRINTER_NOTIFY_INFO_COLOR_MISMATCH: - break; - default: - break; - } + for (p = printers_list; p; p = p->next) { + ret = send_notify2_printer(mem_ctx, p, msg_group); + if (ret) { + goto done; } } |