diff options
Diffstat (limited to 'source/rpc_server/srv_spoolss_nt.c')
-rw-r--r-- | source/rpc_server/srv_spoolss_nt.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c index 613d516971f..582c74942a1 100644 --- a/source/rpc_server/srv_spoolss_nt.c +++ b/source/rpc_server/srv_spoolss_nt.c @@ -559,6 +559,144 @@ static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size) return True; } +/********************************************************************** + Release the memory held by a SPOOL_NOTIFY_INFO_DATA + *********************************************************************/ + +static void free_notify_data(SPOOL_NOTIFY_INFO_DATA *data, uint32 len) +{ + uint32 i; + + if (!data) + return; + + for (i=0; i<len; i++) { + if (data[i].size == POINTER) + SAFE_FREE(data[i].notify_data.data.string); + } + + SAFE_FREE(data); +} + +/*************************************************************************** + Send a notify to the client. +****************************************************************************/ + +static BOOL cli_spoolss_reply_rrpcn(struct cli_state *pcli, POLICY_HND *handle, + char* printername, uint32 change_low, uint32 change_high, + WERROR *status) +{ + prs_struct rbuf; + prs_struct buf; + + SPOOL_NOTIFY_INFO notify_info; + SPOOL_NOTIFY_INFO_DATA *notify_data = NULL, *data; + uint32 idx = 0; + + WERROR result; + + NT_PRINTER_INFO_LEVEL *printer = NULL; + + SPOOL_Q_REPLY_RRPCN q_s; + SPOOL_R_REPLY_RRPCN r_s; + + prs_init(&buf, 1024, pcli->mem_ctx, MARSHALL); + prs_init(&rbuf, 0, pcli->mem_ctx, UNMARSHALL ); + + ZERO_STRUCT(notify_info); + + /* lookup the printer if we have a name */ + + if (*printername) { + result = get_a_printer(&printer, 2, printername); + if (! W_ERROR_IS_OK(result)) { + *status = result; + goto done; + } + } + + /* + * See comments in _spoolss_setprinter() about PRINTER_CHANGE_XXX + * events. --jerry + */ + + /* Did the driver change? */ + + if (change_low & PRINTER_CHANGE_SET_PRINTER_DRIVER) { + change_low &= ~PRINTER_CHANGE_SET_PRINTER_DRIVER; + DEBUG(10,("cli_spoolss_reply_rrpcn: PRINTER_CHANGE_SET_PRINTER_DRIVER set on [%s][%d]\n", + printername, idx)); + if ((data=Realloc(notify_data, (idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) { + DEBUG(0,("cli_spoolss_reply_rrpcn: Realloc() failed with size [%d]!\n", + (idx+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))); + *status = WERR_NOMEM; + goto done; + } + notify_data = data; + + memset(notify_data+idx, 0x0, sizeof(SPOOL_NOTIFY_INFO_DATA)); + + /* + * 'id' (last param here) is undefined when type == PRINTER_NOTIFY_TYPE + * See PRINTER_NOTIFY_INFO_DATA entries in MSDN + * --jerry + */ + construct_info_data(notify_data+idx, PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, 0x00); + + spoolss_notify_driver_name(-1, notify_data+idx, NULL, printer, pcli->mem_ctx); + idx++; + } + + +#if 0 /* JERRY -- do not delete */ + DEBUG(4,("cli_spoolss_reply_open_printer: srv:%s acct:%s sc: %d mc: %s clnt %s %x\n", + pcli->srv_name_slash, pcli->mach_acct, sec_chan_type, global_myname, + credstr(new_clnt_cred.challenge.data), new_clnt_cred.timestamp.time)); +#endif + + /* create and send a MSRPC command with api */ + + /* store the parameters */ + + notify_info.flags = 0x00000200; + notify_info.count = idx; + notify_info.data = notify_data; + + make_spoolss_q_reply_rrpcn(&q_s, handle, change_low, change_high, ¬ify_info); + + /* turn parameters into data stream */ + if(!spoolss_io_q_reply_rrpcn("", &q_s, &buf, 0)) { + DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to marshall SPOOL_Q_REPLY_RRPCN struct.\n")); + *status = WERR_BADFUNC; + goto done; + } + + /* send the data on \PIPE\ */ + if (!rpc_api_pipe_req(pcli, SPOOLSS_RRPCN, &buf, &rbuf)) { + DEBUG(0,("cli_spoolss_reply_rrpcn: SPOOLSS_RRPCN failed!\n")); + *status = WERR_BADFUNC; + goto done; + } + + + /* turn data stream into parameters*/ + if(!spoolss_io_r_reply_rrpcn("", &r_s, &rbuf, 0)) { + DEBUG(0,("cli_spoolss_reply_rrpcn: Error : failed to unmarshall SPOOL_R_REPLY_RRPCN struct.\n")); + *status = WERR_BADFUNC; + goto done; + } + + *status = r_s.status; + +done: + prs_mem_free(&buf); + prs_mem_free(&rbuf); + free_a_printer(&printer, 2); + free_notify_data(notify_data, idx); + + return W_ERROR_IS_OK(*status); +} + /*************************************************************************** Receive the notify message. ****************************************************************************/ |