1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00

change notify merge from APP_HEAD

This commit is contained in:
Gerald Carter 0001-01-01 00:00:00 +00:00
parent 3c9d24d7c3
commit b5227f0a64
3 changed files with 282 additions and 77 deletions

View File

@ -351,7 +351,7 @@ typedef struct _form
#define SPOOLSS_NOTIFY_MSG_UNIX_JOBID 0x0001 /* Job id is unix */
struct spoolss_notify_msg {
typedef struct spoolss_notify_msg {
fstring printer; /* Name of printer notified */
uint32 type; /* Printer or job notify */
uint32 field; /* Notify field changed */
@ -362,6 +362,18 @@ struct spoolss_notify_msg {
uint32 value[2];
char *data;
} notify;
};
} SPOOLSS_NOTIFY_MSG;
typedef struct {
fstring printername;
uint32 num_msgs;
SPOOLSS_NOTIFY_MSG *msgs;
} SPOOLSS_NOTIFY_MSG_GROUP;
typedef struct {
TALLOC_CTX *ctx;
uint32 num_groups;
SPOOLSS_NOTIFY_MSG_GROUP *msg_groups;
} SPOOLSS_NOTIFY_MSG_CTR;
#endif /* NT_PRINTING_H_ */

View File

@ -222,6 +222,9 @@ done:
return result;
}
/*********************************************************************
*********************************************************************/
WERROR cli_spoolss_rffpcnex(struct cli_state *cli, TALLOC_CTX *mem_ctx,
POLICY_HND *pol, uint32 flags, uint32 options,
char *localmachine, uint32 printerlocal,

View File

@ -728,25 +728,177 @@ static struct notify2_message_table job_notify_table[] = {
/* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
};
/***********************************************************************
Allocate talloc context for container object
**********************************************************************/
static void notify_msg_ctr_init( SPOOLSS_NOTIFY_MSG_CTR *ctr )
{
if ( !ctr )
return;
ctr->ctx = talloc_init();
return;
}
/***********************************************************************
release all allocated memory and zero out structure
**********************************************************************/
static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
{
if ( !ctr )
return;
if ( ctr->ctx )
talloc_destroy(ctr->ctx);
ZERO_STRUCTP(ctr);
return;
}
/***********************************************************************
**********************************************************************/
static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
{
if ( !ctr )
return NULL;
return ctr->ctx;
}
/***********************************************************************
**********************************************************************/
static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 index )
{
if ( !ctr || !ctr->msg_groups )
return NULL;
if ( index >= ctr->num_groups )
return NULL;
return &ctr->msg_groups[index];
}
/***********************************************************************
How many groups of change messages do we have ?
**********************************************************************/
static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
{
if ( !ctr )
return 0;
return ctr->num_groups;
}
/***********************************************************************
Add a SPOOLSS_NOTIFY_MSG_CTR to the correct group
**********************************************************************/
static int notify_msg_ctr_addmsg( SPOOLSS_NOTIFY_MSG_CTR *ctr, SPOOLSS_NOTIFY_MSG *msg )
{
SPOOLSS_NOTIFY_MSG_GROUP *groups = NULL;
SPOOLSS_NOTIFY_MSG_GROUP *msg_grp = NULL;
SPOOLSS_NOTIFY_MSG *msg_list = NULL;
int i, new_slot;
if ( !ctr || !msg )
return 0;
/* loop over all groups looking for a matching printer name */
for ( i=0; i<ctr->num_groups; i++ ) {
if ( strcmp(ctr->msg_groups[i].printername, msg->printer) == 0 )
break;
}
/* add a new group? */
if ( i == ctr->num_groups )
{
ctr->num_groups++;
if ( !(groups = talloc_realloc( ctr->ctx, ctr->msg_groups, sizeof(SPOOLSS_NOTIFY_MSG_GROUP)*ctr->num_groups)) ) {
DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed!\n"));
return 0;
}
ctr->msg_groups = groups;
/* clear the new entry and set the printer name */
ZERO_STRUCT( ctr->msg_groups[ctr->num_groups-1] );
fstrcpy( ctr->msg_groups[ctr->num_groups-1].printername, msg->printer );
}
/* add the change messages; 'i' is the correct index now regardless */
msg_grp = &ctr->msg_groups[i];
msg_grp->num_msgs++;
if ( !(msg_list = talloc_realloc( ctr->ctx, msg_grp->msgs, sizeof(SPOOLSS_NOTIFY_MSG)*msg_grp->num_msgs )) ) {
DEBUG(0,("notify_msg_ctr_addmsg: talloc_realloc() failed for new message [%d]!\n", msg_grp->num_msgs));
return 0;
}
msg_grp->msgs = msg_list;
new_slot = msg_grp->num_msgs-1;
memcpy( &msg_grp->msgs[new_slot], msg, sizeof(SPOOLSS_NOTIFY_MSG) );
/* need to allocate own copy of data */
if ( msg->len != 0 )
msg_grp->msgs[new_slot].notify.data = talloc_memdup( ctr->ctx, msg->notify.data, msg->len );
return ctr->num_groups;
}
/***********************************************************************
Send a change notication message on all handles which have a call
back registered
**********************************************************************/
static void process_notify2_message(struct spoolss_notify_msg *msg, TALLOC_CTX *mem_ctx)
static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 index )
{
Printer_entry *p;
DEBUG(8,("process_notify2_message: Enter...[%s]\n", msg->printer));
Printer_entry *p;
TALLOC_CTX *mem_ctx = notify_ctr_getctx( ctr );
SPOOLSS_NOTIFY_MSG_GROUP *msg_group = notify_ctr_getgroup( ctr, index );
SPOOLSS_NOTIFY_MSG *messages;
for (p = printers_list; p; p = p->next) {
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 = 1;
uint32 id;
uint32 data_len = 0;
uint32 id;
int i;
/* Is there notification on this handle? */
if (!p->notify.client_connected)
if ( !p->notify.client_connected )
continue;
DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
@ -755,25 +907,31 @@ static void process_notify2_message(struct spoolss_notify_msg *msg, TALLOC_CTX *
notifications. */
if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
( !strequal(msg->printer, p->dev.handlename) ) )
( !strequal(msg_group->printername, p->dev.handlename) ) )
continue;
DEBUG(10,("Our printer\n"));
/* allocate the max entries possible */
data = talloc( mem_ctx, msg_group->num_msgs*sizeof(SPOOL_NOTIFY_INFO_DATA) );
ZERO_STRUCTP(data);
/* build the array of change notifications */
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;
DEBUG(10,("process_notify2_message: Sending message type [%x] field [%x] for printer [%s]\n",
msg->type, msg->field, p->dev.handlename));
/* OK - send the event to the client */
data = talloc(mem_ctx, sizeof(SPOOL_NOTIFY_INFO_DATA));
ZERO_STRUCTP(data);
/*
* 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
@ -795,8 +953,8 @@ static void process_notify2_message(struct spoolss_notify_msg *msg, TALLOC_CTX *
/* Convert unix jobid to smb jobid */
if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) {
if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
{
id = sysjob_to_jobid(msg->id);
if (id == -1) {
@ -805,22 +963,20 @@ static void process_notify2_message(struct spoolss_notify_msg *msg, TALLOC_CTX *
}
}
construct_info_data(data, msg->type, msg->field, id);
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 )
goto done;
printer_notify_table[msg->field].fn(msg, data, mem_ctx);
printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
break;
case JOB_NOTIFY_TYPE:
if ( !job_notify_table[msg->field].fn )
goto done;
job_notify_table[msg->field].fn(msg, data, mem_ctx);
job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
break;
@ -829,60 +985,51 @@ static void process_notify2_message(struct spoolss_notify_msg *msg, TALLOC_CTX *
goto done;
}
data_len++;
}
cli_spoolss_rrpcn( &notify_cli, mem_ctx, &p->notify.client_hnd,
data_len, data, p->notify.change, 0 );
}
done:
DEBUG(8,("process_notify2_message: Exit...\n"));
DEBUG(8,("send_notify2_changes: Exit...\n"));
return;
}
/********************************************************************
Receive a notify2 message
********************************************************************/
/***********************************************************************
**********************************************************************/
static void receive_notify2_message(void *buf, size_t len)
static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
{
struct spoolss_notify_msg msg;
int offset = 0;
TALLOC_CTX *mem_ctx = talloc_init();
/* Unpack message */
ZERO_STRUCT(msg);
offset += tdb_unpack((char *)buf + offset, len - offset, "f",
msg.printer);
msg->printer);
offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
&msg.type, &msg.field, &msg.id, &msg.len, &msg.flags);
&msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
if (msg.len == 0)
if (msg->len == 0)
tdb_unpack((char *)buf + offset, len - offset, "dd",
&msg.notify.value[0], &msg.notify.value[1]);
&msg->notify.value[0], &msg->notify.value[1]);
else
tdb_unpack((char *)buf + offset, len - offset, "B",
&msg.len, &msg.notify.data);
&msg->len, &msg->notify.data);
DEBUG(3, ("got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
msg.type, msg.field, msg.flags));
DEBUG(3, ("notify2_unpack_msg: got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n",
msg->type, msg->field, msg->flags));
if (msg.len == 0)
DEBUG(3, ("value1 = %d, value2 = %d\n", msg.notify.value[0],
msg.notify.value[1]));
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);
dump_data(3, msg->notify.data, msg->len);
/* Process message */
process_notify2_message(&msg, mem_ctx);
/* Free message */
if (msg.len > 0)
free(msg.notify.data);
talloc_destroy(mem_ctx);
return True;
}
/********************************************************************
@ -891,43 +1038,86 @@ static void receive_notify2_message(void *buf, size_t len)
static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
{
size_t msg_count, i;
char *buf = (char *)msg;
char *msg_ptr;
if (len < 4)
goto bad_msg;
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 %d messages in list\n", msg_count));
if (msg_count == 0)
goto bad_msg;
if (msg_count == 0) {
DEBUG(0,("receive_notify2_message_list: bad message format (msg_count == 0) !\n"));
return;
}
for (i = 0; i < msg_count; i++) {
size_t msg_len;
if (msg_ptr + 4 - buf > len)
goto bad_msg;
/* 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++ )
{
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)
goto bad_msg;
receive_notify2_message(msg_ptr, msg_len);
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( &notify, msg_ptr, msg_len );
msg_ptr += msg_len;
/* add to correct list in container */
notify_msg_ctr_addmsg( &messages, &notify );
/* free memory that might have been allocated by notify2_unpack_msg() */
if ( notify.len != 0 )
SAFE_FREE( notify.notify.data );
}
DEBUG(10,("receive_notify2_message_list: processed %u messages\n",
(unsigned int)msg_count ));
/* 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;
bad_msg:
DEBUG(0,("receive_notify2_message_list: bad message format !\n"));
}
/********************************************************************