📄 srv_spoolss_nt.c
字号:
}/*********************************************************************** Send a change notication message on all handles which have a call back registered **********************************************************************/static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx ){ Printer_entry *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; if ( !msg_group ) { DEBUG(5,("send_notify2_changes() called with no msg group!\n")); return; } messages = msg_group->msgs; if ( !messages ) { DEBUG(5,("send_notify2_changes() called with no messages!\n")); return; } DEBUG(8,("send_notify2_changes: Enter...[%s]\n", msg_group->printername)); /* loop over all printers */ for (p = printers_list; p; p = p->next) { SPOOL_NOTIFY_INFO_DATA *data; uint32 data_len = 0; uint32 id; int i; /* Is there notification on this handle? */ if ( !p->notify.client_connected ) continue; DEBUG(10,("Client connected! [\\\\%s\\%s]\n", p->servername, p->sharename)); /* For this printer? Print servers always receive notifications. */ if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( !strequal(msg_group->printername, p->sharename) ) ) continue; DEBUG(10,("Our printer\n")); /* allocate the max entries possible */ data = TALLOC_ARRAY( mem_ctx, SPOOL_NOTIFY_INFO_DATA, msg_group->num_msgs); ZERO_STRUCTP(data); /* build the array of change notifications */ sending_msg_count = 0; for ( i=0; i<msg_group->num_msgs; i++ ) { SPOOLSS_NOTIFY_MSG *msg = &messages[i]; /* Are we monitoring this event? */ if (!is_monitoring_event(p, msg->type, msg->field)) continue; sending_msg_count++; DEBUG(10,("process_notify2_message: Sending message type [0x%x] field [0x%2x] for printer [%s]\n", msg->type, msg->field, p->sharename)); /* * 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 */ if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) ) id = 0; else id = msg->id; /* Convert unix jobid to smb jobid */ if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) { id = sysjob_to_jobid(msg->id); if (id == -1) { DEBUG(3, ("no such unix jobid %d\n", msg->id)); goto done; } } construct_info_data( &data[data_len], msg->type, msg->field, id ); switch(msg->type) { case PRINTER_NOTIFY_TYPE: if ( printer_notify_table[msg->field].fn ) printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx); break; case JOB_NOTIFY_TYPE: if ( job_notify_table[msg->field].fn ) job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx); break; default: DEBUG(5, ("Unknown notification type %d\n", msg->type)); goto done; } data_len++; } if ( sending_msg_count ) { rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd, data_len, data, p->notify.change, 0 ); } } done: DEBUG(8,("send_notify2_changes: Exit...\n")); return;}/*********************************************************************** **********************************************************************/static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, void *buf, size_t len ){ uint32 tv_sec, tv_usec; size_t offset = 0; /* Unpack message */ offset += tdb_unpack((char *)buf + offset, len - offset, "f", msg->printer); offset += tdb_unpack((char *)buf + offset, len - offset, "ddddddd", &tv_sec, &tv_usec, &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags); if (msg->len == 0) tdb_unpack((char *)buf + offset, len - offset, "dd", &msg->notify.value[0], &msg->notify.value[1]); else tdb_unpack((char *)buf + offset, len - offset, "B", &msg->len, &msg->notify.data); DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message for printer %s, jobid %u type %d, field 0x%02x, flags 0x%04x\n", msg->printer, (unsigned int)msg->id, msg->type, msg->field, msg->flags)); tv->tv_sec = tv_sec; tv->tv_usec = tv_usec; if (msg->len == 0) DEBUG(3, ("notify2_unpack_msg: value1 = %d, value2 = %d\n", msg->notify.value[0], msg->notify.value[1])); else dump_data(3, msg->notify.data, msg->len); return True;}/******************************************************************** Receive a notify2 message list ********************************************************************/static void receive_notify2_message_list(int msg_type, struct process_id src, void *msg, size_t len){ size_t msg_count, i; char *buf = (char *)msg; char *msg_ptr; size_t msg_len; SPOOLSS_NOTIFY_MSG notify; SPOOLSS_NOTIFY_MSG_CTR messages; int num_groups; if (len < 4) { DEBUG(0,("receive_notify2_message_list: bad message format (len < 4)!\n")); return; } msg_count = IVAL(buf, 0); msg_ptr = buf + 4; DEBUG(5, ("receive_notify2_message_list: got %lu messages in list\n", (unsigned long)msg_count)); if (msg_count == 0) { DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n")); return; } /* initialize the container */ ZERO_STRUCT( messages ); notify_msg_ctr_init( &messages ); /* * build message groups for each printer identified * in a change_notify msg. Remember that a PCN message * includes the handle returned for the srv_spoolss_replyopenprinter() * call. Therefore messages are grouped according to printer handle. */ for ( i=0; i<msg_count; i++ ) { struct timeval msg_tv; if (msg_ptr + 4 - buf > len) { DEBUG(0,("receive_notify2_message_list: bad message format (len > buf_size) !\n")); return; } msg_len = IVAL(msg_ptr,0); msg_ptr += 4; if (msg_ptr + msg_len - buf > len) { DEBUG(0,("receive_notify2_message_list: bad message format (bad len) !\n")); return; } /* unpack messages */ ZERO_STRUCT( notify ); notify2_unpack_msg( ¬ify, &msg_tv, msg_ptr, msg_len ); msg_ptr += msg_len; /* add to correct list in container */ notify_msg_ctr_addmsg( &messages, ¬ify ); /* free memory that might have been allocated by notify2_unpack_msg() */ if ( notify.len != 0 ) SAFE_FREE( notify.notify.data ); } /* process each group of messages */ num_groups = notify_msg_ctr_numgroups( &messages ); for ( i=0; i<num_groups; i++ ) send_notify2_changes( &messages, i ); /* cleanup */ DEBUG(10,("receive_notify2_message_list: processed %u messages\n", (uint32)msg_count )); notify_msg_ctr_destroy( &messages ); return;}/******************************************************************** Send a message to ourself about new driver being installed so we can upgrade the information for each printer bound to this driver ********************************************************************/ static BOOL srv_spoolss_drv_upgrade_printer(char* drivername){ int len = strlen(drivername); if (!len) return False; DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n", drivername)); message_send_pid(pid_to_procid(sys_getpid()), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False); return True;}/********************************************************************** callback to receive a MSG_PRINTER_DRVUPGRADE message and interate over all printers, upgrading ones as necessary **********************************************************************/ void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len){ fstring drivername; int snum; int n_services = lp_numservices(); len = MIN(len,sizeof(drivername)-1); strncpy(drivername, buf, len); DEBUG(10,("do_drv_upgrade_printer: Got message for new driver [%s]\n", drivername )); /* Iterate the printer list */ for (snum=0; snum<n_services; snum++) { if (lp_snum_ok(snum) && lp_print_ok(snum) ) { WERROR result; NT_PRINTER_INFO_LEVEL *printer = NULL; result = get_a_printer(NULL, &printer, 2, lp_const_servicename(snum)); if (!W_ERROR_IS_OK(result)) continue; if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername)) { DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername)); /* all we care about currently is the change_id */ result = mod_a_printer(printer, 2); if (!W_ERROR_IS_OK(result)) { DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n", dos_errstr(result))); } } free_a_printer(&printer, 2); } } /* all done */ }/******************************************************************** Update the cache for all printq's with a registered client connection ********************************************************************/void update_monitored_printq_cache( void ){ Printer_entry *printer = printers_list; int snum; /* loop through all printers and update the cache where client_connected == True */ while ( printer ) { if ( (printer->printer_type == PRINTER_HANDLE_IS_PRINTER) && printer->notify.client_connected ) { snum = print_queue_snum(printer->sharename); print_queue_status( snum, NULL, NULL ); } printer = printer->next; } return;}/******************************************************************** Send a message to ourself about new driver being installed so we can upgrade the information for each printer bound to this driver ********************************************************************/ static BOOL srv_spoolss_reset_printerdata(char* drivername){ int len = strlen(drivername); if (!len) return False; DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n", drivername)); message_send_pid(pid_to_procid(sys_getpid()), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False); return True;}/********************************************************************** callback to receive a MSG_PRINTERDATA_INIT_RESET message and interate over all printers, resetting printer data as neessary **********************************************************************/ void reset_all_printerdata(int msg_type, struct process_id src, void *buf, size_t len){ fstring drivername; int snum; int n_services = lp_numservices(); len = MIN( len, sizeof(drivername)-1 ); strncpy( drivername, buf, len ); DEBUG(10,("reset_all_printerdata: Got message for new driver [%s]\n", drivername )); /* Iterate the printer list */ for ( snum=0; snum<n_services; snum++ ) { if ( lp_snum_ok(snum) && lp_print_ok(snum) ) { WERROR result; NT_PRINTER_INFO_LEVEL *printer = NULL; result = get_a_printer( NULL, &printer, 2, lp_const_servicename(snum) ); if ( !W_ERROR_IS_OK(result) ) continue; /* * if the printer is bound to the driver, * then reset to the new driver initdata */ if ( printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername) ) { DEBUG(6,("reset_all_printerdata: Updating printer [%s]\n", printer->info_2->printername)); if ( !set_driver_init(printer, 2) ) { DEBUG(5,("reset_all_printerdata: Error resetting printer data for printer [%s], driver [%s]!\n", printer->info_2->printername, printer->info_2->drivername)); } result = mod_a_printer( printer, 2 ); if ( !W_ERROR_IS_OK(result) ) { DEBUG(3,("reset_all_printerdata: mod_a_printer() failed! (%s)\n", get_dos_error_msg(result))); } } free_a_printer( &printer, 2 ); } } /* all done */ return;}/******************************************************************** Copy routines used by convert_to_openprinterex()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -