* Copyright (C) Andrew Tridgell 1992-2000,
* Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
* Copyright (C) Jean François Micouleau 1998-2000,
- * Copyright (C) Jeremy Allison 2001,
- * Copyright (C) Gerald Carter 2000-2001,
+ * Copyright (C) Jeremy Allison 2001-2002,
+ * Copyright (C) Gerald Carter 2000-2002,
* Copyright (C) Tim Potter 2001-2002.
*
* This program is free software; you can redistribute it and/or modify
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_RPC_SRV
+/* #define EMULATE_WIN2K_HACK 1 */
#ifndef MAX_OPEN_PRINTER_EXS
#define MAX_OPEN_PRINTER_EXS 50
struct _Printer *prev, *next;
BOOL document_started;
BOOL page_started;
- int jobid; /* jobid in printing backend */
+ uint32 jobid; /* jobid in printing backend */
BOOL printer_type;
union {
fstring handlename;
SPOOL_NOTIFY_OPTION *option;
POLICY_HND client_hnd;
uint32 client_connected;
+ uint32 change;
} notify;
struct {
fstring machine;
fstring user;
} client;
+
+ /* devmode sent in the OpenPrinter() call */
+ NT_DEVICEMODE *nt_devmode;
+
} Printer_entry;
static Printer_entry *printers_list;
static ubi_dlList counter_list;
-static struct cli_state cli;
+static struct cli_state notify_cli; /* print notify back-channel */
static uint32 smb_connections=0;
Disconnect from the client
****************************************************************************/
-static void srv_spoolss_replycloseprinter(POLICY_HND *handle)
+static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle)
{
WERROR result;
+ /*
+ * Tell the specific printing tdb we no longer want messages for this printer
+ * by deregistering our PID.
+ */
+
+ if (!print_notify_deregister_pid(snum))
+ DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", lp_const_servicename(snum) ));
+
/* weird if the test succeds !!! */
if (smb_connections==0) {
DEBUG(0,("srv_spoolss_replycloseprinter:Trying to close non-existant notify backchannel !\n"));
return;
}
- result = cli_spoolss_reply_close_printer(&cli, cli.mem_ctx, handle);
+ result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle);
if (!W_ERROR_IS_OK(result))
DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n",
/* if it's the last connection, deconnect the IPC$ share */
if (smb_connections==1) {
- if(!spoolss_disconnect_from_client(&cli))
- return;
+ cli_nt_session_close(¬ify_cli);
+ cli_ulogoff(¬ify_cli);
+ cli_shutdown(¬ify_cli);
+ message_deregister(MSG_PRINTER_NOTIFY2);
+
+ /* Tell the connections db we're no longer interested in
+ * printer notify messages. */
- message_deregister(MSG_PRINTER_NOTIFY);
+ register_message_flags( False, FLAG_MSG_PRINTING );
}
smb_connections--;
{
Printer_entry *Printer = (Printer_entry *)ptr;
- if (Printer->notify.client_connected==True)
- srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
+ if (Printer->notify.client_connected==True) {
+ int snum = -1;
+
+ if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
+ snum = -1;
+ srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
+ } else if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) {
+ snum = print_queue_snum(Printer->dev.handlename);
+ if (snum != -1)
+ srv_spoolss_replycloseprinter(snum,
+ &Printer->notify.client_hnd);
+ }
+ }
Printer->notify.flags=0;
Printer->notify.options=0;
free_spool_notify_option(&Printer->notify.option);
Printer->notify.option=NULL;
Printer->notify.client_connected=False;
+
+ free_nt_devicemode( &Printer->nt_devmode );
/* Remove from the internal list. */
DLIST_REMOVE(printers_list, Printer);
return WERR_BADFID;
}
- if (del_a_printer(Printer->dev.handlename) != 0) {
- DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
- return WERR_BADFID;
+ /*
+ * It turns out that Windows allows delete printer on a handle
+ * opened by an admin user, then used on a pipe handle created
+ * by an anonymous user..... but they're working on security.... riiight !
+ * JRA.
+ */
+
+ if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+ DEBUG(3, ("delete_printer_handle: denied by handle\n"));
+ return WERR_ACCESS_DENIED;
}
+#if 0
/* Check calling user has permission to delete printer. Note that
since we set the snum parameter to -1 only administrators can
delete the printer. This stops people with the Full Control
DEBUG(3, ("printer delete denied by security descriptor\n"));
return WERR_ACCESS_DENIED;
}
+#endif
+
+ if (del_a_printer(Printer->dev.handlename) != 0) {
+ DEBUG(3,("Error deleting printer %s\n", Printer->dev.handlename));
+ return WERR_BADFID;
+ }
if (*lp_deleteprinter_cmd()) {
/* Send SIGHUP to process group... is there a better way? */
kill(0, SIGHUP);
- if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) >= 0 ) {
- lp_killservice( i );
- return WERR_OK;
- } else
+ /* go ahead and re-read the services immediately */
+ reload_services( False );
+
+ if ( ( i = lp_servicenumber( Printer->dev.handlename ) ) < 0 )
return WERR_ACCESS_DENIED;
}
* anymore, so I've simplified this loop greatly. Here
* we are just verifying that the printer name is a valid
* printer service defined in smb.conf
- * --jerry [Fri Feb 15 11:17:46 CST 2002]
+ * --jerry [Fri Feb 15 11:17:46 CST 2002]
*/
for (snum=0; snum<n_services; snum++) {
return True;
}
+
/***************************************************************************
- Always give preference Printer_entry.notify.option over
- Printer_entry.notify.flags. Return True if we should send notification
- events using SPOOLSS_RRPCN. False means that we should use
- SPOOLSS_ROUTERREPLYPRINTER.
+ check to see if the client motify handle is monitoring the notification
+ given by (notify_type, notify_field).
**************************************************************************/
-static BOOL valid_notify_options(Printer_entry *printer)
+
+static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type,
+ uint16 notify_field)
{
- if (printer->notify.option == NULL)
- return False;
-
return True;
}
-/***************************************************************************
- Simple check to see if the client motify handle is set to watch for events
- represented by 'flags'
+static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type,
+ uint16 notify_field)
+{
+ SPOOL_NOTIFY_OPTION *option = p->notify.option;
+ uint32 i, j;
+
+ /*
+ * Flags should always be zero when the change notify
+ * is registered by the cliebnt's spooler. A user Win32 app
+ * might use the flags though instead of the NOTIFY_OPTION_INFO
+ * --jerry
+ */
+
+ if (p->notify.flags)
+ return is_monitoring_event_flags(
+ p->notify.flags, notify_type, notify_field);
+
+ for (i = 0; i < option->count; i++) {
+
+ /* Check match for notify_type */
+
+ if (option->ctr.type[i].type != notify_type)
+ continue;
+
+ /* Check match for field */
+
+ for (j = 0; j < option->ctr.type[i].count; j++) {
+ if (option->ctr.type[i].fields[j] == notify_field) {
+ return True;
+ }
+ }
+ }
+
+ DEBUG(10, ("%s is not monitoring 0x%02x/0x%02x\n",
+ (p->printer_type == PRINTER_HANDLE_IS_PRINTER) ?
+ p->dev.handlename : p->dev.printerservername,
+ notify_type, notify_field));
+
+ return False;
+}
+
+/* Convert a notification message to a SPOOL_NOTIFY_INFO_DATA struct */
+
+static void notify_one_value(struct spoolss_notify_msg *msg,
+ SPOOL_NOTIFY_INFO_DATA *data,
+ TALLOC_CTX *mem_ctx)
+{
+ data->notify_data.value[0] = msg->notify.value[0];
+ data->notify_data.value[1] = 0;
+}
+
+static void notify_string(struct spoolss_notify_msg *msg,
+ SPOOL_NOTIFY_INFO_DATA *data,
+ TALLOC_CTX *mem_ctx)
+{
+ UNISTR2 unistr;
+
+ /* The length of the message includes the trailing \0 */
+
+ init_unistr2(&unistr, msg->notify.data, msg->len);
+
+ data->notify_data.data.length = msg->len * 2;
+ data->notify_data.data.string = (uint16 *)talloc(mem_ctx, msg->len * 2);
+
+ if (!data->notify_data.data.string) {
+ data->notify_data.data.length = 0;
+ return;
+ }
+
+ memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2);
+}
+
+static void notify_system_time(struct spoolss_notify_msg *msg,
+ SPOOL_NOTIFY_INFO_DATA *data,
+ TALLOC_CTX *mem_ctx)
+{
+ SYSTEMTIME systime;
+ prs_struct ps;
+
+ if (msg->len != sizeof(time_t)) {
+ DEBUG(5, ("notify_system_time: received wrong sized message (%d)\n",
+ msg->len));
+ return;
+ }
+
+ if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) {
+ DEBUG(5, ("notify_system_time: prs_init() failed\n"));
+ return;
+ }
+
+ if (!make_systemtime(&systime, gmtime((time_t *)msg->notify.data))) {
+ DEBUG(5, ("notify_system_time: unable to make systemtime\n"));
+ return;
+ }
+
+ if (!spoolss_io_system_time("", &ps, 0, &systime))
+ return;
+
+ data->notify_data.data.length = prs_offset(&ps);
+ data->notify_data.data.string =
+ talloc(mem_ctx, prs_offset(&ps));
+
+ memcpy(data->notify_data.data.string, prs_data_p(&ps), prs_offset(&ps));
+
+ prs_mem_free(&ps);
+}
+
+struct notify2_message_table {
+ char *name;
+ void (*fn)(struct spoolss_notify_msg *msg,
+ SPOOL_NOTIFY_INFO_DATA *data, TALLOC_CTX *mem_ctx);
+};
+
+static struct notify2_message_table printer_notify_table[] = {
+ /* 0x00 */ { "PRINTER_NOTIFY_SERVER_NAME", notify_string },
+ /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", notify_string },
+ /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", notify_string },
+ /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", notify_string },
+ /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", notify_string },
+ /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", notify_string },
+ /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", notify_string },
+ /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL },
+ /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", notify_string },
+ /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", notify_string },
+ /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL },
+ /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", notify_string },
+ /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL },
+ /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", notify_one_value },
+ /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", notify_one_value },
+ /* 0x0f */ { "PRINTER_NOTIFY_DEFAULT_PRIORITY", NULL },
+ /* 0x10 */ { "PRINTER_NOTIFY_START_TIME", NULL },
+ /* 0x11 */ { "PRINTER_NOTIFY_UNTIL_TIME", NULL },
+ /* 0x12 */ { "PRINTER_NOTIFY_STATUS", notify_one_value },
+};
+
+static struct notify2_message_table job_notify_table[] = {
+ /* 0x00 */ { "JOB_NOTIFY_PRINTER_NAME", NULL },
+ /* 0x01 */ { "JOB_NOTIFY_MACHINE_NAME", NULL },
+ /* 0x02 */ { "JOB_NOTIFY_PORT_NAME", NULL },
+ /* 0x03 */ { "JOB_NOTIFY_USER_NAME", notify_string },
+ /* 0x04 */ { "JOB_NOTIFY_NOTIFY_NAME", NULL },
+ /* 0x05 */ { "JOB_NOTIFY_DATATYPE", NULL },
+ /* 0x06 */ { "JOB_NOTIFY_PRINT_PROCESSOR", NULL },
+ /* 0x07 */ { "JOB_NOTIFY_PARAMETERS", NULL },
+ /* 0x08 */ { "JOB_NOTIFY_DRIVER_NAME", NULL },
+ /* 0x09 */ { "JOB_NOTIFY_DEVMODE", NULL },
+ /* 0x0a */ { "JOB_NOTIFY_STATUS", notify_one_value },
+ /* 0x0b */ { "JOB_NOTIFY_STATUS_STRING", NULL },
+ /* 0x0c */ { "JOB_NOTIFY_SECURITY_DESCRIPTOR", NULL },
+ /* 0x0d */ { "JOB_NOTIFY_DOCUMENT", notify_string },
+ /* 0x0e */ { "JOB_NOTIFY_PRIORITY", NULL },
+ /* 0x0f */ { "JOB_NOTIFY_POSITION", NULL },
+ /* 0x10 */ { "JOB_NOTIFY_SUBMITTED", notify_system_time },
+ /* 0x11 */ { "JOB_NOTIFY_START_TIME", NULL },
+ /* 0x12 */ { "JOB_NOTIFY_UNTIL_TIME", NULL },
+ /* 0x13 */ { "JOB_NOTIFY_TIME", NULL },
+ /* 0x14 */ { "JOB_NOTIFY_TOTAL_PAGES", notify_one_value },
+ /* 0x15 */ { "JOB_NOTIFY_PAGES_PRINTED", NULL },
+ /* 0x16 */ { "JOB_NOTIFY_TOTAL_BYTES", notify_one_value },
+ /* 0x17 */ { "JOB_NOTIFY_BYTES_PRINTED", NULL },
+};
+
+
+/***********************************************************************
+ Allocate talloc context for container object
+ **********************************************************************/
- FIXME!!!! only a stub right now --jerry
- **************************************************************************/
+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 BOOL is_client_monitoring_event(Printer_entry *p, uint32 flags)
+static void notify_msg_ctr_destroy( SPOOLSS_NOTIFY_MSG_CTR *ctr )
{
+ if ( !ctr )
+ return;
- return True;
+ if ( ctr->ctx )
+ talloc_destroy(ctr->ctx);
+
+ ZERO_STRUCTP(ctr);
+
+ return;
}
-/***************************************************************************
- Server wrapper for cli_spoolss_routerreplyprinter() since the client
- function can only send a single change notification at a time.
+/***********************************************************************
+ **********************************************************************/
- FIXME!!! only handles one change currently (PRINTER_CHANGE_SET_PRINTER_DRIVER)
- --jerry
- **************************************************************************/
+static TALLOC_CTX* notify_ctr_getctx( SPOOLSS_NOTIFY_MSG_CTR *ctr )
+{
+ if ( !ctr )
+ return NULL;
+
+ return ctr->ctx;
+}
+
+/***********************************************************************
+ **********************************************************************/
-static WERROR srv_spoolss_routerreplyprinter (struct cli_state *reply_cli, TALLOC_CTX *mem_ctx,
- POLICY_HND *pol, PRINTER_MESSAGE_INFO *info,
- NT_PRINTER_INFO_LEVEL *printer)
+static SPOOLSS_NOTIFY_MSG_GROUP* notify_ctr_getgroup( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
{
- WERROR result;
- uint32 condition = 0x0;
-
- if (info->flags & PRINTER_MESSAGE_DRIVER)
- condition = PRINTER_CHANGE_SET_PRINTER_DRIVER;
+ if ( !ctr || !ctr->msg_groups )
+ return NULL;
- result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition,
- printer->info_2->changeid);
+ if ( idx >= ctr->num_groups )
+ return NULL;
+
+ return &ctr->msg_groups[idx];
- return result;
}
/***********************************************************************
- Wrapper around the decision of which RPC use to in the change
- notification
+ How many groups of change messages do we have ?
**********************************************************************/
-static WERROR srv_spoolss_send_event_to_client(Printer_entry* Printer,
- struct cli_state *send_cli, PRINTER_MESSAGE_INFO *msg,
- NT_PRINTER_INFO_LEVEL *info)
+static int notify_msg_ctr_numgroups( SPOOLSS_NOTIFY_MSG_CTR *ctr )
{
- WERROR result;
+ 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;
+ }
- if (valid_notify_options(Printer)) {
- /* This is a single call that can send information about multiple changes */
- if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
- msg->flags |= PRINTER_MESSAGE_ATTRIBUTES;
+ /* 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;
- result = cli_spoolss_reply_rrpcn(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd,
- msg, info);
+ /* 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 );
}
- else {
- /* This requires that the server send an individual event notification for each change */
- result = srv_spoolss_routerreplyprinter(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd,
- msg, info);
+
+ /* 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;
- return result;
+ 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 send_spoolss_event_notification(PRINTER_MESSAGE_INFO *msg)
+static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx )
{
- Printer_entry *find_printer;
- WERROR result;
- NT_PRINTER_INFO_LEVEL *printer = NULL;
-
- if (!msg) {
- DEBUG(0,("send_spoolss_event_notification: NULL msg pointer!\n"));
+ 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;
+
+
+ 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;
- for(find_printer = printers_list; find_printer; find_printer = find_printer->next) {
+ /* Is there notification on this handle? */
- /*
- * If the entry has a connected client we send the message. There should
- * only be one of these normally when dealing with the NT/2k spooler.
- * However, iterate over all to make sure we deal with user applications
- * in addition to spooler service.
+ if ( !p->notify.client_connected )
+ continue;
+
+ DEBUG(10,("Client connected! [%s]\n", p->dev.handlename));
+
+ /* For this printer? Print servers always receive
+ notifications. */
+
+ if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) &&
+ ( !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));
+
+ /*
+ * 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.
*
- * While we are only maintaining a single connection to the client,
- * the FindFirstPrinterChangeNotification() call is made on a printer
- * handle, so "client_connected" represents the whether or not the
- * client asked for change notication on this handle.
- *
* --jerry
*/
- if (find_printer->notify.client_connected==True) {
-
- /* does the client care about what changed? */
-
- if (msg->flags && !is_client_monitoring_event(find_printer, msg->flags)) {
- DEBUG(10,("send_spoolss_event_notification: Client [%s] not monitoring these events\n",
- find_printer->client.machine));
- continue;
- }
+ if ( ( p->printer_type == PRINTER_HANDLE_IS_PRINTER ) && ( msg->type == PRINTER_NOTIFY_TYPE ) )
+ id = 0;
+ else
+ id = msg->id;
- if (find_printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
- DEBUG(10,("send_spoolss_event_notification: printserver [%s]\n", find_printer->dev.printerservername ));
- else
- DEBUG(10,("send_spoolss_event_notification: printer [%s]\n", find_printer->dev.handlename));
- /*
- * if handle is a printer, only send if the printer_name matches.
- * ...else if handle is a printerserver, send to all
- */
+ /* Convert unix jobid to smb jobid */
- if (*msg->printer_name && (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER)
- && !strequal(msg->printer_name, find_printer->dev.handlename))
+ if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID)
{
- DEBUG(10,("send_spoolss_event_notification: ignoring message sent to %s [%s]\n",
- msg->printer_name, find_printer->dev.handlename ));
- continue;
+ 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 );
- /* lookup the printer if we have a name if we don't already have a
- valid NT_PRINTER_INFO_LEVEL structure. And yes I'm assuming we
- will always have a non-empty msg.printer_name */
-
- if (!printer || !printer->info_2 || strcmp(msg->printer_name, printer->info_2->printername))
- {
+ switch(msg->type) {
+ case PRINTER_NOTIFY_TYPE:
+ if ( !printer_notify_table[msg->field].fn )
+ goto done;
+ printer_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
+
+ break;
- if (printer) {
- free_a_printer(&printer, 2);
- printer = NULL;
- }
-
- result = get_a_printer(&printer, 2, msg->printer_name);
- if (!W_ERROR_IS_OK(result))
- continue;
- }
+ case JOB_NOTIFY_TYPE:
+ if ( !job_notify_table[msg->field].fn )
+ goto done;
+ job_notify_table[msg->field].fn(msg, &data[data_len], mem_ctx);
+
+ break;
- /* issue the client call */
+ default:
+ DEBUG(5, ("Unknown notification type %d\n", msg->type));
+ goto done;
+ }
- result = srv_spoolss_send_event_to_client(find_printer, &cli, msg, printer);
-
- if (!W_ERROR_IS_OK(result)) {
- DEBUG(5,("send_spoolss_event_notification: Event notification failed [%s]\n",
- dos_errstr(result)));
+ data_len++;
}
- }
-}
+ cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd,
+ data_len, data, p->notify.change, 0 );
+ }
+
+done:
+ DEBUG(8,("send_notify2_changes: Exit...\n"));
return;
}
-/***************************************************************************
- Receive the notify message and decode the message. Do not send
- notification if we sent this originally as that would result in
- duplicates.
-****************************************************************************/
-static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len)
-{
- PRINTER_MESSAGE_INFO msg;
-
- if (len < sizeof(msg)) {
- DEBUG(2,("srv_spoolss_receive_message: got incorrect message size (%u)!\n", (unsigned int)len));
- return;
- }
+/***********************************************************************
+ **********************************************************************/
- memcpy(&msg, buf, sizeof(PRINTER_MESSAGE_INFO));
-
- DEBUG(10,("srv_spoolss_receive_message: Got message printer change [queue = %s] low=0x%x high=0x%x flags=0x%x\n",
- msg.printer_name, (unsigned int)msg.low, (unsigned int)msg.high, msg.flags ));
+static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, void *buf, size_t len )
+{
- /* Iterate the printer list */
-
- send_spoolss_event_notification(&msg);
-
-}
+ int offset = 0;
-/***************************************************************************
- Send a notify event.
-****************************************************************************/
+ /* Unpack message */
-static BOOL srv_spoolss_sendnotify(char* printer_name, uint32 high, uint32 low, uint32 flags)
-{
- char msg[sizeof(PRINTER_MESSAGE_INFO)];
- PRINTER_MESSAGE_INFO info;
+ offset += tdb_unpack((char *)buf + offset, len - offset, "f",
+ msg->printer);
- ZERO_STRUCT(info);
+ offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd",
+ &msg->type, &msg->field, &msg->id, &msg->len, &msg->flags);
- info.low = low;
- info.high = high;
- info.flags = flags;
- fstrcpy(info.printer_name, printer_name);
-
- memcpy(msg, &info, sizeof(PRINTER_MESSAGE_INFO));
+ 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(10,("srv_spoolss_sendnotify: printer change low=0x%x high=0x%x [%s], flags=0x%x\n",
- low, high, printer_name, flags));
-
- message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, msg, sizeof(PRINTER_MESSAGE_INFO),
- False, NULL);
+ 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, ("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;
-}
+}
/********************************************************************
- Send a message to ourself about new driver being installed
- so we can upgrade the information for each printer bound to this
- driver
-********************************************************************/
+ Receive a notify2 message list
+ ********************************************************************/
-static BOOL srv_spoolss_drv_upgrade_printer(char* drivername)
+static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len)
{
- int len = strlen(drivername);
-
- if (!len)
- return False;
+ 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) {
+ 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++ )
+ {
+ 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_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(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 neessary
-**********************************************************************/
-
+ over all printers, upgrading ones as neessary
+ **********************************************************************/
+
void do_drv_upgrade_printer(int msg_type, pid_t 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(&printer, 2, lp_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));
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)));
+ DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",
+ dos_errstr(result)));
}
}
- free_a_printer(&printer, 2);
+ free_a_printer(&printer, 2);
}
}
+
+ /* all done */
+}
+
+/********************************************************************
+ 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(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, pid_t 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 ));
- /* all done */
+ /* 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( &printer, 2, lp_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;
}
/********************************************************************
/********************************************************************
* spoolss_open_printer
*
- * called from the spoolss dispatcher
+ * If the openprinterex rpc call contains a devmode,
+ * it's a per-user one. This per-user devmode is derivated
+ * from the global devmode. Openprinterex() contains a per-user
+ * devmode for when you do EMF printing and spooling.
+ * In the EMF case, the NT workstation is only doing half the job
+ * of rendering the page. The other half is done by running the printer
+ * driver on the server.
+ * The EMF file doesn't contain the page description (paper size, orientation, ...).
+ * The EMF file only contains what is to be printed on the page.
+ * So in order for the server to know how to print, the NT client sends
+ * a devicemode attached to the openprinterex call.
+ * But this devicemode is short lived, it's only valid for the current print job.
+ *
+ * If Samba would have supported EMF spooling, this devicemode would
+ * have been attached to the handle, to sent it to the driver to correctly
+ * rasterize the EMF file.
+ *
+ * As Samba only supports RAW spooling, we only receive a ready-to-print file,
+ * we just act as a pass-thru between windows and the printer.
+ *
+ * In order to know that Samba supports only RAW spooling, NT has to call
+ * getprinter() at level 2 (attribute field) or NT has to call startdoc()
+ * and until NT sends a RAW job, we refuse it.
+ *
+ * But to call getprinter() or startdoc(), you first need a valid handle,
+ * and to get an handle you have to call openprintex(). Hence why you have
+ * a devicemode in the openprinterex() call.
+ *
+ *
+ * Differences between NT4 and NT 2000.
+ * NT4:
+ * ---
+ * On NT4, you only have a global devicemode. This global devicemode can be changed
+ * by the administrator (or by a user with enough privs). Everytime a user
+ * wants to print, the devicemode is resetted to the default. In Word, everytime
+ * you print, the printer's characteristics are always reset to the global devicemode.
+ *
+ * NT 2000:
+ * -------
+ * In W2K, there is the notion of per-user devicemode. The first time you use
+ * a printer, a per-user devicemode is build from the global devicemode.
+ * If you change your per-user devicemode, it is saved in the registry, under the
+ * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
+ * printer preferences available.
+ *
+ * To change the per-user devicemode: it's the "Printing Preferences ..." button
+ * on the General Tab of the printer properties windows.
+ *
+ * To change the global devicemode: it's the "Printing Defaults..." button
+ * on the Advanced Tab of the printer properties window.
+ *
+ * JFM.
********************************************************************/
WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u, SPOOL_R_OPEN_PRINTER_EX *r_u)
{
- UNISTR2 *printername = NULL;
- PRINTER_DEFAULT *printer_default = &q_u->printer_default;
-/* uint32 user_switch = q_u->user_switch; - notused */
-/* SPOOL_USER_CTR user_ctr = q_u->user_ctr; - notused */
- POLICY_HND *handle = &r_u->handle;
+ UNISTR2 *printername = NULL;
+ PRINTER_DEFAULT *printer_default = &q_u->printer_default;
+ POLICY_HND *handle = &r_u->handle;
fstring name;
int snum;
return WERR_INVALID_PRINTER_NAME;
}
-/*
- First case: the user is opening the print server:
-
- Disallow MS AddPrinterWizard if parameter disables it. A Win2k
- client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
-
- Then both Win2k and WinNT clients try an OpenPrinterEx with
- SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
- or if the user is listed in the smb.conf printer admin parameter.
-
- Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
- client view printer folder, but does not show the MSAPW.
-
- Note: this test needs code to check access rights here too. Jeremy
- could you look at this?
-
-
- Second case: the user is opening a printer:
- NT doesn't let us connect to a printer if the connecting user
- doesn't have print permission.
-
- */
-
get_current_user(&user, p);
- if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
+ /*
+ * First case: the user is opening the print server:
+ *
+ * Disallow MS AddPrinterWizard if parameter disables it. A Win2k
+ * client 1st tries an OpenPrinterEx with access==0, MUST be allowed.
+ *
+ * Then both Win2k and WinNT clients try an OpenPrinterEx with
+ * SERVER_ALL_ACCESS, which we allow only if the user is root (uid=0)
+ * or if the user is listed in the smb.conf printer admin parameter.
+ *
+ * Then they try OpenPrinterEx with SERVER_READ which we allow. This lets the
+ * client view printer folder, but does not show the MSAPW.
+ *
+ * Note: this test needs code to check access rights here too. Jeremy
+ * could you look at this?
+ *
+ * Second case: the user is opening a printer:
+ * NT doesn't let us connect to a printer if the connecting user
+ * doesn't have print permission.
+ */
+ if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
+ {
/* Printserver handles use global struct... */
snum = -1;
- /* Map standard access rights to object specific access
- rights */
+ /* Map standard access rights to object specific access rights */
se_map_standard(&printer_default->access_required,
&printserver_std_mapping);
/* Allow admin access */
- if (printer_default->access_required &
- SERVER_ACCESS_ADMINISTER) {
-
+ if ( printer_default->access_required & SERVER_ACCESS_ADMINISTER )
+ {
if (!lp_ms_add_printer_wizard()) {
close_printer_handle(p, handle);
return WERR_ACCESS_DENIED;
}
- if (user.uid == 0 ||
- user_in_list(uidtoname(user.uid),
- lp_printer_admin(snum)))
- return WERR_OK;
+ /* if the user is not root and not a printer admin, then fail */
- close_printer_handle(p, handle);
- return WERR_ACCESS_DENIED;
+ if ( user.uid != 0
+ && !user_in_list(uidtoname(user.uid), lp_printer_admin(snum)) )
+ {
+ close_printer_handle(p, handle);
+ return WERR_ACCESS_DENIED;
+ }
+
+ printer_default->access_required = SERVER_ACCESS_ADMINISTER;
+ }
+ else
+ {
+ printer_default->access_required = SERVER_ACCESS_ENUMERATE;
}
+ DEBUG(4,("Setting print server access = %s\n", (printer_default->access_required == SERVER_ACCESS_ADMINISTER)
+ ? "SERVER_ACCESS_ADMINISTER" : "SERVER_ACCESS_ENUMERATE" ));
+
/* We fall through to return WERR_OK */
}
else
printer_default->access_required = PRINTER_ACCESS_USE;
- DEBUG(4,("Setting printer access=%x\n", printer_default->access_required));
- Printer->access_granted = printer_default->access_required;
+ DEBUG(4,("Setting printer access = %s\n", (printer_default->access_required == PRINTER_ACCESS_ADMINISTER)
+ ? "PRINTER_ACCESS_ADMINISTER" : "PRINTER_ACCESS_USE" ));
- /*
- * If we have a default device pointer in the
- * printer_default struct, then we need to get
- * the printer info from the tdb and if there is
- * no default devicemode there then we do a *SET*
- * here ! This is insanity.... JRA.
- */
-
- /*
- * If the openprinterex rpc call contains a devmode,
- * it's a per-user one. This per-user devmode is derivated
- * from the global devmode. Openprinterex() contains a per-user
- * devmode for when you do EMF printing and spooling.
- * In the EMF case, the NT workstation is only doing half the job
- * of rendering the page. The other half is done by running the printer
- * driver on the server.
- * The EMF file doesn't contain the page description (paper size, orientation, ...).
- * The EMF file only contains what is to be printed on the page.
- * So in order for the server to know how to print, the NT client sends
- * a devicemode attached to the openprinterex call.
- * But this devicemode is short lived, it's only valid for the current print job.
- *
- * If Samba would have supported EMF spooling, this devicemode would
- * have been attached to the handle, to sent it to the driver to correctly
- * rasterize the EMF file.
- *
- * As Samba only supports RAW spooling, we only receive a ready-to-print file,
- * we just act as a pass-thru between windows and the printer.
- *
- * In order to know that Samba supports only RAW spooling, NT has to call
- * getprinter() at level 2 (attribute field) or NT has to call startdoc()
- * and until NT sends a RAW job, we refuse it.
- *
- * But to call getprinter() or startdoc(), you first need a valid handle,
- * and to get an handle you have to call openprintex(). Hence why you have
- * a devicemode in the openprinterex() call.
- *
- *
- * Differences between NT4 and NT 2000.
- * NT4:
- * ---
- * On NT4, you only have a global devicemode. This global devicemode can be changed
- * by the administrator (or by a user with enough privs). Everytime a user
- * wants to print, the devicemode is resetted to the default. In Word, everytime
- * you print, the printer's characteristics are always reset to the global devicemode.
- *
- * NT 2000:
- * -------
- * In W2K, there is the notion of per-user devicemode. The first time you use
- * a printer, a per-user devicemode is build from the global devicemode.
- * If you change your per-user devicemode, it is saved in the registry, under the
- * H_KEY_CURRENT_KEY sub_tree. So that everytime you print, you have your default
- * printer preferences available.
- *
- * To change the per-user devicemode: it's the "Printing Preferences ..." button
- * on the General Tab of the printer properties windows.
- *
- * To change the global devicemode: it's the "Printing Defaults..." button
- * on the Advanced Tab of the printer properties window.
- *
- * JFM.
- */
-
-
-
-#if 0
- if (printer_default->devmode_cont.devmode != NULL) {
- result = printer_write_default_dev( snum, printer_default);
- if (result != 0) {
- close_printer_handle(p, handle);
- return result;
- }
- }
-#endif
}
+
+ Printer->access_granted = printer_default->access_required;
+
+ /*
+ * If the client sent a devmode in the OpenPrinter() call, then
+ * save it here in case we get a job submission on this handle
+ */
+
+ if ( (Printer->printer_type != PRINTER_HANDLE_IS_PRINTSERVER)
+ && q_u->printer_default.devmode_cont.devmode_ptr )
+ {
+ convert_devicemode( Printer->dev.handlename, q_u->printer_default.devmode_cont.devmode,
+ &Printer->nt_devmode );
+ }
return WERR_OK;
}
static WERROR _spoolss_enddocprinter_internal(pipes_struct *p, POLICY_HND *handle)
{
Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
-
+ int snum;
+
if (!Printer) {
DEBUG(2,("_spoolss_enddocprinter_internal: Invalid handle (%s:%u:%u)\n", OUR_HANDLE(handle)));
return WERR_BADFID;
}
+ if (!get_printer_snum(p, handle, &snum))
+ return WERR_BADFID;
+
Printer->document_started=False;
- print_job_end(Printer->jobid,True);
+ print_job_end(snum, Printer->jobid,True);
/* error codes unhandled so far ... */
return WERR_OK;
update_c_setprinter(False);
- if (W_ERROR_IS_OK(result)) {
- srv_spoolss_sendnotify(Printer->dev.handlename, 0, PRINTER_CHANGE_DELETE_PRINTER, 0x0);
- }
-
return result;
}
/********************************************************************
* _spoolss_deleteprinterdriver
- *
- * We currently delete the driver for the architecture only.
- * This can leave the driver for other archtectures. However,
- * since every printer associates a "Windows NT x86" driver name
- * and we cannot delete that one while it is in use, **and** since
- * it is impossible to assign a driver to a Samba printer without
- * having the "Windows NT x86" driver installed,...
- *
- * ....we should not get into trouble here.
- *
- * --jerry
********************************************************************/
-WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u,
- SPOOL_R_DELETEPRINTERDRIVER *r_u)
+WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER *q_u, SPOOL_R_DELETEPRINTERDRIVER *r_u)
{
fstring driver;
fstring arch;
NT_PRINTER_DRIVER_INFO_LEVEL info;
+ NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
int version;
+ struct current_user user;
+ WERROR status;
+ WERROR status_win2k = WERR_ACCESS_DENIED;
+
+ get_current_user(&user, p);
unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
/* check that we have a valid driver name first */
- if ((version=get_version_id(arch)) == -1) {
- /* this is what NT returns */
+
+ if ((version=get_version_id(arch)) == -1)
return WERR_INVALID_ENVIRONMENT;
- }
-
+
ZERO_STRUCT(info);
- if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
- return WERR_UNKNOWN_PRINTER_DRIVER;
- }
+ ZERO_STRUCT(info_win2k);
-
- if (printer_driver_in_use(arch, driver))
+ if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version)))
{
- return WERR_PRINTER_DRIVER_IN_USE;
+ /* try for Win2k driver if "Windows NT x86" */
+
+ if ( version == 2 ) {
+ version = 3;
+ if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
+ status = WERR_UNKNOWN_PRINTER_DRIVER;
+ goto done;
+ }
+ }
+ /* otherwise it was a failure */
+ else {
+ status = WERR_UNKNOWN_PRINTER_DRIVER;
+ goto done;
+ }
+
+ }
+
+ if (printer_driver_in_use(info.info_3)) {
+ status = WERR_PRINTER_DRIVER_IN_USE;
+ goto done;
+ }
+
+ if ( version == 2 )
+ {
+ if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
+ {
+ /* if we get to here, we now have 2 driver info structures to remove */
+ /* remove the Win2k driver first*/
+
+ status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False );
+ free_a_printer_driver( info_win2k, 3 );
+
+ /* this should not have failed---if it did, report to client */
+ if ( !W_ERROR_IS_OK(status_win2k) )
+ goto done;
+ }
}
+
+ status = delete_printer_driver(info.info_3, &user, version, False);
+
+ /* if at least one of the deletes succeeded return OK */
+
+ if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
+ status = WERR_OK;
+
+done:
+ free_a_printer_driver( info, 3 );
- return delete_printer_driver(info.info_3);
+ return status;
}
/********************************************************************
- GetPrinterData on a printer server Handle.
-********************************************************************/
+ * spoolss_deleteprinterdriverex
+ ********************************************************************/
-static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
-{
- int i;
+WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVEREX *q_u, SPOOL_R_DELETEPRINTERDRIVEREX *r_u)
+{
+ fstring driver;
+ fstring arch;
+ NT_PRINTER_DRIVER_INFO_LEVEL info;
+ NT_PRINTER_DRIVER_INFO_LEVEL info_win2k;
+ int version;
+ uint32 flags = q_u->delete_flags;
+ BOOL delete_files;
+ struct current_user user;
+ WERROR status;
+ WERROR status_win2k = WERR_ACCESS_DENIED;
- DEBUG(8,("getprinterdata_printer_server:%s\n", value));
-
- if (!strcmp(value, "W3SvcInstalled")) {
- *type = 0x4;
- if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
- return False;
- *needed = 0x4;
- return True;
- }
+ get_current_user(&user, p);
+
+ unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 );
+ unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 );
+
+ /* check that we have a valid driver name first */
+ if ((version=get_version_id(arch)) == -1) {
+ /* this is what NT returns */
+ return WERR_INVALID_ENVIRONMENT;
+ }
+
+ if ( flags & DPD_DELETE_SPECIFIC_VERSION )
+ version = q_u->version;
+
+ ZERO_STRUCT(info);
+ ZERO_STRUCT(info_win2k);
+
+ status = get_a_printer_driver(&info, 3, driver, arch, version);
+
+ if ( !W_ERROR_IS_OK(status) )
+ {
+ /*
+ * if the client asked for a specific version,
+ * or this is something other than Windows NT x86,
+ * then we've failed
+ */
+
+ if ( (flags&DPD_DELETE_SPECIFIC_VERSION) || (version !=2) )
+ goto done;
+
+ /* try for Win2k driver if "Windows NT x86" */
+
+ version = 3;
+ if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) {
+ status = WERR_UNKNOWN_PRINTER_DRIVER;
+ goto done;
+ }
+ }
+
+ if ( printer_driver_in_use(info.info_3) ) {
+ status = WERR_PRINTER_DRIVER_IN_USE;
+ goto done;
+ }
+
+ /*
+ * we have a couple of cases to consider.
+ * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set,
+ * then the delete should fail if **any** files overlap with
+ * other drivers
+ * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all
+ * non-overlapping files
+ * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES
+ * is set, the do not delete any files
+ * Refer to MSDN docs on DeletePrinterDriverEx() for details.
+ */
+
+ delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES);
+
+ /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */
+
+ if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
+ /* no idea of the correct error here */
+ status = WERR_ACCESS_DENIED;
+ goto done;
+ }
+
+
+ /* also check for W32X86/3 if necessary; maybe we already have? */
+
+ if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) {
+ if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3)))
+ {
+
+ if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) {
+ /* no idea of the correct error here */
+ free_a_printer_driver( info_win2k, 3 );
+ status = WERR_ACCESS_DENIED;
+ goto done;
+ }
+
+ /* if we get to here, we now have 2 driver info structures to remove */
+ /* remove the Win2k driver first*/
+
+ status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, delete_files);
+ free_a_printer_driver( info_win2k, 3 );
+
+ /* this should not have failed---if it did, report to client */
+
+ if ( !W_ERROR_IS_OK(status_win2k) )
+ goto done;
+ }
+ }
+
+ status = delete_printer_driver(info.info_3, &user, version, delete_files);
+
+ if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) )
+ status = WERR_OK;
+done:
+ free_a_printer_driver( info, 3 );
+
+ return status;
+}
+
+
+/****************************************************************************
+ Internal routine for retreiving printerdata
+ ***************************************************************************/
+
+static WERROR get_printer_dataex( TALLOC_CTX *ctx, NT_PRINTER_INFO_LEVEL *printer,
+ char *key, char *value, uint32 *type, uint8 **data,
+ uint32 *needed, uint32 in_size )
+{
+ REGISTRY_VALUE *val;
+ int size, data_len;
+
+ if ( !(val = get_printer_data( printer->info_2, key, value)) )
+ return WERR_BADFILE;
+
+ *type = regval_type( val );
+
+ DEBUG(5,("get_printer_dataex: allocating %d\n", in_size));
+
+ size = regval_size( val );
+
+ /* copy the min(in_size, len) */
+
+ if ( in_size ) {
+ data_len = (size > in_size) ? in_size : size*sizeof(uint8);
+ if ( (*data = (uint8 *)talloc_memdup(ctx, regval_data_p(val), data_len)) == NULL )
+ return WERR_NOMEM;
+ }
+ else
+ *data = NULL;
+
+ *needed = size;
+
+ DEBUG(5,("get_printer_dataex: copy done\n"));
+
+ return WERR_OK;
+}
+
+/****************************************************************************
+ Internal routine for removing printerdata
+ ***************************************************************************/
+
+static WERROR delete_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value )
+{
+ delete_printer_data( printer->info_2, key, value );
+
+ return mod_a_printer(*printer, 2);
+}
+
+/****************************************************************************
+ Internal routine for storing printerdata
+ ***************************************************************************/
+
+static WERROR set_printer_dataex( NT_PRINTER_INFO_LEVEL *printer, char *key, char *value,
+ uint32 type, uint8 *data, int real_len )
+{
+ delete_printer_data( printer->info_2, key, value );
+
+ add_printer_data( printer->info_2, key, value, type, data, real_len );
+
+ return mod_a_printer(*printer, 2);
+}
+
+/********************************************************************
+ GetPrinterData on a printer server Handle.
+********************************************************************/
+
+static WERROR getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type, uint8 **data, uint32 *needed, uint32 in_size)
+{
+ int i;
+
+ DEBUG(8,("getprinterdata_printer_server:%s\n", value));
+
+ if (!strcmp(value, "W3SvcInstalled")) {
+ *type = 0x4;
+ if((*data = (uint8 *)talloc_zero(ctx, 4*sizeof(uint8) )) == NULL)
+ return WERR_NOMEM;
+ *needed = 0x4;
+ return WERR_OK;
+ }
if (!strcmp(value, "BeepEnabled")) {
*type = 0x4;
if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
- return False;
+ return WERR_NOMEM;
SIVAL(*data, 0, 0x00);
*needed = 0x4;
- return True;
+ return WERR_OK;
}
if (!strcmp(value, "EventLog")) {
*type = 0x4;
if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
- return False;
+ return WERR_NOMEM;
/* formally was 0x1b */
SIVAL(*data, 0, 0x0);
*needed = 0x4;
- return True;
+ return WERR_OK;
}
if (!strcmp(value, "NetPopup")) {
*type = 0x4;
if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
- return False;
+ return WERR_NOMEM;
SIVAL(*data, 0, 0x00);
*needed = 0x4;
- return True;
+ return WERR_OK;
}
if (!strcmp(value, "MajorVersion")) {
*type = 0x4;
if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL)
- return False;
+ return WERR_NOMEM;
#ifndef EMULATE_WIN2K_HACK /* JERRY */
SIVAL(*data, 0, 2);
#else
SIVAL(*data, 0, 3);
#endif
*needed = 0x4;
- return True;
+ return WERR_OK;
}
if (!strcmp(value, "DefaultSpoolDirectory")) {
*type = 0x1;
*needed = 2*(strlen(string)+1);
if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
- return False;
+ return WERR_NOMEM;
memset(*data, 0, (*needed > in_size) ? *needed:in_size);
/* it's done by hand ready to go on the wire */
(*data)[2*i]=string[i];
(*data)[2*i+1]='\0';
}
- return True;
+ return WERR_OK;
}
if (!strcmp(value, "Architecture")) {
*type = 0x1;
*needed = 2*(strlen(string)+1);
if((*data = (uint8 *)talloc(ctx, ((*needed > in_size) ? *needed:in_size) *sizeof(uint8))) == NULL)
- return False;
+ return WERR_NOMEM;
memset(*data, 0, (*needed > in_size) ? *needed:in_size);
for (i=0; i<strlen(string); i++) {
(*data)[2*i]=string[i];
(*data)[2*i+1]='\0';
}
- return True;
+ return WERR_OK;
}
- return False;
+ return WERR_INVALID_PARAM;
}
-/********************************************************************
- GetPrinterData on a printer Handle.
-********************************************************************/
-
-static BOOL getprinterdata_printer(pipes_struct *p, TALLOC_CTX *ctx, POLICY_HND *handle,
- fstring value, uint32 *type,
- uint8 **data, uint32 *needed, uint32 in_size )
-{
- NT_PRINTER_INFO_LEVEL *printer = NULL;
- int snum=0;
- uint8 *idata=NULL;
- uint32 len;
- Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
-
- DEBUG(5,("getprinterdata_printer\n"));
-
- if (!Printer) {
- DEBUG(2,("getprinterdata_printer: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
- return False;
- }
-
- if(!get_printer_snum(p, handle, &snum))
- return False;
-
- if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
- return False;
-
- if (!get_specific_param(*printer, 2, value, &idata, type, &len)) {
- free_a_printer(&printer, 2);
- return False;
- }
-
- free_a_printer(&printer, 2);
-
- DEBUG(5,("getprinterdata_printer:allocating %d\n", in_size));
-
- if (in_size) {
- if((*data = (uint8 *)talloc(ctx, in_size *sizeof(uint8) )) == NULL) {
- return False;
- }
-
- memset(*data, 0, in_size *sizeof(uint8));
- /* copy the min(in_size, len) */
- memcpy(*data, idata, (len>in_size)?in_size:len *sizeof(uint8));
- } else {
- *data = NULL;
- }
-
- *needed = len;
-
- DEBUG(5,("getprinterdata_printer:copy done\n"));
-
- SAFE_FREE(idata);
-
- return True;
-}
-
/********************************************************************
* spoolss_getprinterdata
********************************************************************/
WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPOOL_R_GETPRINTERDATA *r_u)
{
- POLICY_HND *handle = &q_u->handle;
- UNISTR2 *valuename = &q_u->valuename;
- uint32 in_size = q_u->size;
- uint32 *type = &r_u->type;
- uint32 *out_size = &r_u->size;
- uint8 **data = &r_u->data;
- uint32 *needed = &r_u->needed;
-
- fstring value;
- BOOL found=False;
- Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+ POLICY_HND *handle = &q_u->handle;
+ UNISTR2 *valuename = &q_u->valuename;
+ uint32 in_size = q_u->size;
+ uint32 *type = &r_u->type;
+ uint32 *out_size = &r_u->size;
+ uint8 **data = &r_u->data;
+ uint32 *needed = &r_u->needed;
+ WERROR status;
+ fstring value;
+ Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ int snum = 0;
/*
* Reminder: when it's a string, the length is in BYTES
* JFM, 4/19/1999
*/
- *out_size=in_size;
+ *out_size = in_size;
/* in case of problem, return some default values */
- *needed=0;
- *type=0;
+
+ *needed = 0;
+ *type = 0;
DEBUG(4,("_spoolss_getprinterdata\n"));
- if (!Printer) {
- if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
- return WERR_NOMEM;
+ if ( !Printer ) {
DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
- return WERR_BADFID;
+ status = WERR_BADFID;
+ goto done;
}
unistr2_to_ascii(value, valuename, sizeof(value)-1);
- if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
- found=getprinterdata_printer_server(p->mem_ctx, value, type, data, needed, *out_size);
+ if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER )
+ status = getprinterdata_printer_server( p->mem_ctx, value, type, data, needed, *out_size );
else
- found= getprinterdata_printer(p, p->mem_ctx, handle, value, type, data, needed, *out_size);
+ {
+ if ( !get_printer_snum(p,handle, &snum) ) {
+ status = WERR_BADFID;
+ goto done;
+ }
- if (found==False) {
- DEBUG(5, ("value not found, allocating %d\n", *out_size));
+ status = get_a_printer(&printer, 2, lp_servicename(snum));
+ if ( !W_ERROR_IS_OK(status) )
+ goto done;
+
+ status = get_printer_dataex( p->mem_ctx, printer, SPOOL_PRINTERDATA_KEY, value, type, data, needed, *out_size );
+ }
+
+ if (*needed > *out_size)
+ status = WERR_MORE_DATA;
+
+done:
+ if ( !W_ERROR_IS_OK(status) )
+ {
+ DEBUG(5, ("error: allocating %d\n", *out_size));
+
/* reply this param doesn't exist */
- if (*out_size) {
- if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
+
+ if ( *out_size ) {
+ if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL) {
+ if ( printer )
+ free_a_printer( &printer, 2 );
return WERR_NOMEM;
- } else {
+ }
+ }
+ else {
*data = NULL;
}
+ }
+
+ /* cleanup & exit */
- /* error depends on handle type */
+ if ( printer )
+ free_a_printer( &printer, 2 );
+
+ return status;
+}
- if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
- return WERR_INVALID_PARAM;
- else
- return WERR_BADFILE;
+/*********************************************************
+ Connect to the client machine.
+**********************************************************/
+
+static BOOL spoolss_connect_to_client(struct cli_state *the_cli, const char *remote_machine)
+{
+ extern pstring global_myname;
+
+ ZERO_STRUCTP(the_cli);
+ if(cli_initialise(the_cli) == NULL) {
+ DEBUG(0,("connect_to_client: unable to initialize client connection.\n"));
+ return False;
}
-
- if (*needed > *out_size)
- return WERR_MORE_DATA;
- else
- return WERR_OK;
+
+ if(!resolve_name( remote_machine, &the_cli->dest_ip, 0x20)) {
+ DEBUG(0,("connect_to_client: Can't resolve address for %s\n", remote_machine));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (ismyip(the_cli->dest_ip)) {
+ DEBUG(0,("connect_to_client: Machine %s is one of our addresses. Cannot add to ourselves.\n", remote_machine));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (!cli_connect(the_cli, remote_machine, &the_cli->dest_ip)) {
+ DEBUG(0,("connect_to_client: unable to connect to SMB server on machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (!attempt_netbios_session_request(the_cli, global_myname, remote_machine, &the_cli->dest_ip)) {
+ DEBUG(0,("connect_to_client: machine %s rejected the NetBIOS session request.\n",
+ remote_machine));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ the_cli->protocol = PROTOCOL_NT1;
+
+ if (!cli_negprot(the_cli)) {
+ DEBUG(0,("connect_to_client: machine %s rejected the negotiate protocol. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (the_cli->protocol != PROTOCOL_NT1) {
+ DEBUG(0,("connect_to_client: machine %s didn't negotiate NT protocol.\n", remote_machine));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ /*
+ * Do an anonymous session setup.
+ */
+
+ if (!cli_session_setup(the_cli, "", "", 0, "", 0, "")) {
+ DEBUG(0,("connect_to_client: machine %s rejected the session setup. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (!(the_cli->sec_mode & 1)) {
+ DEBUG(0,("connect_to_client: machine %s isn't in user level security mode\n", remote_machine));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ if (!cli_send_tconX(the_cli, "IPC$", "IPC", "", 1)) {
+ DEBUG(0,("connect_to_client: machine %s rejected the tconX on the IPC$ share. Error was : %s.\n", remote_machine, cli_errstr(the_cli) ));
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ /*
+ * Ok - we have an anonymous connection to the IPC$ share.
+ * Now start the NT Domain stuff :-).
+ */
+
+ if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) {
+ DEBUG(0,("connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli)));
+ cli_nt_session_close(the_cli);
+ cli_ulogoff(the_cli);
+ cli_shutdown(the_cli);
+ return False;
+ }
+
+ return True;
}
/***************************************************************************
Connect to the client.
****************************************************************************/
-static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
+static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, uint32 localprinter, uint32 type, POLICY_HND *handle)
{
WERROR result;
fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */
- if(!spoolss_connect_to_client(&cli, unix_printer))
+ if(!spoolss_connect_to_client(¬ify_cli, unix_printer))
return False;
- message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message);
-
+ message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list);
+ /* Tell the connections db we're now interested in printer
+ * notify messages. */
+ register_message_flags( True, FLAG_MSG_PRINTING );
}
+ /*
+ * Tell the specific printing tdb we want messages for this printer
+ * by registering our PID.
+ */
+
+ if (!print_notify_register_pid(snum))
+ DEBUG(0,("print_notify_register_pid: Failed to register our pid for printer %s\n", printer ));
+
smb_connections++;
- result = cli_spoolss_reply_open_printer(&cli, cli.mem_ctx, printer, localprinter,
+ result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter,
type, handle);
-
+
if (!W_ERROR_IS_OK(result))
DEBUG(5,("srv_spoolss_reply_open_printer: Client RPC returned [%s]\n",
dos_errstr(result)));
uint32 options = q_u->options;
UNISTR2 *localmachine = &q_u->localmachine;
uint32 printerlocal = q_u->printerlocal;
+ int snum = -1;
SPOOL_NOTIFY_OPTION *option = q_u->option;
/* store the notify value in the printer struct */
Printer->notify.option=dup_spool_notify_option(option);
- unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1);
+ unistr2_to_ascii(Printer->notify.localmachine, localmachine,
+ sizeof(Printer->notify.localmachine)-1);
+
+ /* Connect to the client machine and send a ReplyOpenPrinter */
- /* connect to the client machine and send a ReplyOpenPrinter */
- if(srv_spoolss_replyopenprinter(Printer->notify.localmachine,
+ if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
+ snum = -1;
+ else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
+ !get_printer_snum(p, handle, &snum) )
+ return WERR_BADFID;
+
+ if(!srv_spoolss_replyopenprinter(snum, Printer->notify.localmachine,
Printer->notify.printerlocal, 1,
&Printer->notify.client_hnd))
- {
- Printer->notify.client_connected=True;
- }
+ return WERR_SERVER_UNAVAILABLE;
+
+ Printer->notify.client_connected=True;
return WERR_OK;
}
len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
uint32 len;
len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
else
len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
NT_PRINTER_INFO_LEVEL *printer,
TALLOC_CTX *mem_ctx)
{
- data->notify_data.data.length=0;
- data->notify_data.data.string = NULL;
+ data->notify_data.sd.size = printer->info_2->secdesc_buf->len;
+ data->notify_data.sd.desc = dup_sec_desc( mem_ctx, printer->info_2->secdesc_buf->sec ) ;
}
/*******************************************************************
len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE);
- data->notify_data.data.length = len / 2 - 1;
+ data->notify_data.data.length = len;
data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len);
if (!data->notify_data.data.string) {
SSVAL(p, 14, st.milliseconds);
}
-#define END 65535
-
struct s_notify_info_data_table
{
uint16 type;
struct s_notify_info_data_table notify_info_data_table[] =
{
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", POINTER, spoolss_notify_server_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", POINTER, spoolss_notify_share_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", POINTER, spoolss_notify_comment },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", POINTER, spoolss_notify_location },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", POINTER, spoolss_notify_sepfile },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", POINTER, spoolss_notify_security_desc },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", ONE_VALUE, spoolss_notify_attributes },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", ONE_VALUE, spoolss_notify_default_priority },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_status },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", POINTER, NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", ONE_VALUE, spoolss_notify_cjobs },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", ONE_VALUE, spoolss_notify_average_ppm },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", POINTER, NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", POINTER, NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", POINTER, NULL },
-{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", POINTER, NULL },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", POINTER, spoolss_notify_printer_name },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", POINTER, spoolss_notify_server_name },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", POINTER, spoolss_notify_port_name },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", POINTER, spoolss_notify_username },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", POINTER, spoolss_notify_username },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", POINTER, spoolss_notify_datatype },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", POINTER, spoolss_notify_print_processor },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", POINTER, spoolss_notify_parameters },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", POINTER, spoolss_notify_driver_name },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", POINTER, spoolss_notify_devmode },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", ONE_VALUE, spoolss_notify_job_status },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", POINTER, spoolss_notify_job_status_string },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", POINTER, NULL },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", POINTER, spoolss_notify_job_name },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", ONE_VALUE, spoolss_notify_priority },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", ONE_VALUE, spoolss_notify_job_position },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", POINTER, spoolss_notify_submitted_time },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", ONE_VALUE, spoolss_notify_start_time },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", ONE_VALUE, spoolss_notify_until_time },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", ONE_VALUE, spoolss_notify_job_time },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", ONE_VALUE, spoolss_notify_total_pages },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", ONE_VALUE, spoolss_notify_pages_printed },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", ONE_VALUE, spoolss_notify_job_size },
-{ JOB_NOTIFY_TYPE, JOB_NOTIFY_BYTES_PRINTED, "JOB_NOTIFY_BYTES_PRINTED", ONE_VALUE, NULL },
-{ END, END, "", END, NULL }
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SERVER_NAME, "PRINTER_NOTIFY_SERVER_NAME", NOTIFY_STRING, spoolss_notify_server_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINTER_NAME, "PRINTER_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SHARE_NAME, "PRINTER_NOTIFY_SHARE_NAME", NOTIFY_STRING, spoolss_notify_share_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PORT_NAME, "PRINTER_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DRIVER_NAME, "PRINTER_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_COMMENT, "PRINTER_NOTIFY_COMMENT", NOTIFY_STRING, spoolss_notify_comment },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_LOCATION, "PRINTER_NOTIFY_LOCATION", NOTIFY_STRING, spoolss_notify_location },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEVMODE, "PRINTER_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SEPFILE, "PRINTER_NOTIFY_SEPFILE", NOTIFY_STRING, spoolss_notify_sepfile },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRINT_PROCESSOR, "PRINTER_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PARAMETERS, "PRINTER_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DATATYPE, "PRINTER_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_SECURITY_DESCRIPTOR, "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_SECDESC, spoolss_notify_security_desc },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_ATTRIBUTES, "PRINTER_NOTIFY_ATTRIBUTES", NOTIFY_ONE_VALUE, spoolss_notify_attributes },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PRIORITY, "PRINTER_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_DEFAULT_PRIORITY, "PRINTER_NOTIFY_DEFAULT_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_default_priority },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_START_TIME, "PRINTER_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_UNTIL_TIME, "PRINTER_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS, "PRINTER_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_status },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_STATUS_STRING, "PRINTER_NOTIFY_STATUS_STRING", NOTIFY_POINTER, NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_CJOBS, "PRINTER_NOTIFY_CJOBS", NOTIFY_ONE_VALUE, spoolss_notify_cjobs },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_AVERAGE_PPM, "PRINTER_NOTIFY_AVERAGE_PPM", NOTIFY_ONE_VALUE, spoolss_notify_average_ppm },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_PAGES, "PRINTER_NOTIFY_TOTAL_PAGES", NOTIFY_POINTER, NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_PAGES_PRINTED, "PRINTER_NOTIFY_PAGES_PRINTED", NOTIFY_POINTER, NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_TOTAL_BYTES, "PRINTER_NOTIFY_TOTAL_BYTES", NOTIFY_POINTER, NULL },
+{ PRINTER_NOTIFY_TYPE, PRINTER_NOTIFY_BYTES_PRINTED, "PRINTER_NOTIFY_BYTES_PRINTED", NOTIFY_POINTER, NULL },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINTER_NAME, "JOB_NOTIFY_PRINTER_NAME", NOTIFY_STRING, spoolss_notify_printer_name },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_MACHINE_NAME, "JOB_NOTIFY_MACHINE_NAME", NOTIFY_STRING, spoolss_notify_server_name },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PORT_NAME, "JOB_NOTIFY_PORT_NAME", NOTIFY_STRING, spoolss_notify_port_name },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_USER_NAME, "JOB_NOTIFY_USER_NAME", NOTIFY_STRING, spoolss_notify_username },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_NOTIFY_NAME, "JOB_NOTIFY_NOTIFY_NAME", NOTIFY_STRING, spoolss_notify_username },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DATATYPE, "JOB_NOTIFY_DATATYPE", NOTIFY_STRING, spoolss_notify_datatype },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRINT_PROCESSOR, "JOB_NOTIFY_PRINT_PROCESSOR", NOTIFY_STRING, spoolss_notify_print_processor },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PARAMETERS, "JOB_NOTIFY_PARAMETERS", NOTIFY_STRING, spoolss_notify_parameters },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DRIVER_NAME, "JOB_NOTIFY_DRIVER_NAME", NOTIFY_STRING, spoolss_notify_driver_name },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DEVMODE, "JOB_NOTIFY_DEVMODE", NOTIFY_POINTER, spoolss_notify_devmode },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS, "JOB_NOTIFY_STATUS", NOTIFY_ONE_VALUE, spoolss_notify_job_status },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_STATUS_STRING, "JOB_NOTIFY_STATUS_STRING", NOTIFY_STRING, spoolss_notify_job_status_string },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_SECURITY_DESCRIPTOR, "JOB_NOTIFY_SECURITY_DESCRIPTOR", NOTIFY_POINTER, NULL },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_DOCUMENT, "JOB_NOTIFY_DOCUMENT", NOTIFY_STRING, spoolss_notify_job_name },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PRIORITY, "JOB_NOTIFY_PRIORITY", NOTIFY_ONE_VALUE, spoolss_notify_priority },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_POSITION, "JOB_NOTIFY_POSITION", NOTIFY_ONE_VALUE, spoolss_notify_job_position },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_SUBMITTED, "JOB_NOTIFY_SUBMITTED", NOTIFY_POINTER, spoolss_notify_submitted_time },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_START_TIME, "JOB_NOTIFY_START_TIME", NOTIFY_ONE_VALUE, spoolss_notify_start_time },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_UNTIL_TIME, "JOB_NOTIFY_UNTIL_TIME", NOTIFY_ONE_VALUE, spoolss_notify_until_time },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TIME, "JOB_NOTIFY_TIME", NOTIFY_ONE_VALUE, spoolss_notify_job_time },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_PAGES, "JOB_NOTIFY_TOTAL_PAGES", NOTIFY_ONE_VALUE, spoolss_notify_total_pages },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_PAGES_PRINTED, "JOB_NOTIFY_PAGES_PRINTED", NOTIFY_ONE_VALUE, spoolss_notify_pages_printed },
+{ JOB_NOTIFY_TYPE, JOB_NOTIFY_TOTAL_BYTES, "JOB_NOTIFY_TOTAL_BYTES", NOTIFY_ONE_VALUE, spoolss_notify_job_size },
};
/*******************************************************************
{
int i=0;
- while (notify_info_data_table[i].type != END)
+ for (i = 0; i < sizeof(notify_info_data_table); i++)
{
- if ( (notify_info_data_table[i].type == type ) &&
- (notify_info_data_table[i].field == field ) )
+ if ( (notify_info_data_table[i].type == type)
+ && (notify_info_data_table[i].field == field) )
{
- return (notify_info_data_table[i].size);
+ switch(notify_info_data_table[i].size)
+ {
+ case NOTIFY_ONE_VALUE:
+ case NOTIFY_TWO_VALUE:
+ return 1;
+ case NOTIFY_STRING:
+ return 2;
+
+ /* The only pointer notify data I have seen on
+ the wire is the submitted time and this has
+ the notify size set to 4. -tpot */
+
+ case NOTIFY_POINTER:
+ return 4;
+
+ case NOTIFY_SECDESC:
+ return 5;
+ }
}
- i++;
}
- return (65535);
+
+ DEBUG(5, ("invalid notify data type %d/%d\n", type, field));
+
+ return 0;
}
/*******************************************************************
Return the type of notify_info_data.
********************************************************************/
-static BOOL type_of_notify_info_data(uint16 type, uint16 field)
+static int type_of_notify_info_data(uint16 type, uint16 field)
{
int i=0;
- while (notify_info_data_table[i].type != END)
- {
- if ( (notify_info_data_table[i].type == type ) &&
- (notify_info_data_table[i].field == field ) )
- {
- if (notify_info_data_table[i].size == POINTER)
- {
- return (False);
- }
- else
- {
- return (True);
- }
- }
- i++;
+ for (i = 0; i < sizeof(notify_info_data_table); i++) {
+ if (notify_info_data_table[i].type == type &&
+ notify_info_data_table[i].field == field)
+ return notify_info_data_table[i].size;
}
- return (False);
+
+ return False;
}
/****************************************************************************
static int search_notify(uint16 type, uint16 field, int *value)
{
- int j;
- BOOL found;
+ int i;
- for (j=0, found=False; found==False && notify_info_data_table[j].type != END ; j++)
- {
- if ( (notify_info_data_table[j].type == type ) &&
- (notify_info_data_table[j].field == field ) )
- found=True;
+ for (i = 0; i < sizeof(notify_info_data_table); i++) {
+ if (notify_info_data_table[i].type == type &&
+ notify_info_data_table[i].field == field &&
+ notify_info_data_table[i].fn != NULL) {
+ *value = i;
+ return True;
+ }
}
- *value=--j;
-
- if ( found && (notify_info_data_table[j].fn != NULL) )
- return True;
- else
- return False;
+
+ return False;
}
/****************************************************************************
info_data->type = type;
info_data->field = field;
info_data->reserved = 0;
- info_data->id = id;
+
info_data->size = size_of_notify_info_data(type, field);
info_data->enc_type = type_of_notify_info_data(type, field);
+
+ info_data->id = id;
+
}
if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
return False;
- for(field_num=0; field_num<option_type->count; field_num++) {
+ for(field_num=0; field_num<option_type->count; field_num++)
+ {
field = option_type->fields[field_num];
+
DEBUG(4,("construct_notify_printer_info: notify [%d]: type [%x], field [%x]\n", field_num, type, field));
if (!search_notify(type, field, &j) )
continue;
- if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL) {
+ if((tid=(SPOOL_NOTIFY_INFO_DATA *)Realloc(info->data, (info->count+1)*sizeof(SPOOL_NOTIFY_INFO_DATA))) == NULL)
+ {
DEBUG(2,("construct_notify_printer_info: failed to enlarge buffer info->data!\n"));
return False;
}
- else info->data = tid;
+ else
+ info->data = tid;
- current_data=&info->data[info->count];
+ current_data = &info->data[info->count];
- construct_info_data(current_data, type, field, id);
+ construct_info_data(current_data, type, field, id);
DEBUG(10,("construct_notify_printer_info: calling [%s] snum=%d printername=[%s])\n",
notify_info_data_table[j].name, snum, printer->info_2->printername ));
continue;
for (snum=0; snum<n_services; snum++)
+ {
if ( lp_browseable(snum) && lp_snum_ok(snum) && lp_print_ok(snum) )
- if (construct_notify_printer_info
- (info, snum, option_type, id, mem_ctx))
- id++;
+ construct_notify_printer_info ( info, snum, option_type, snum, mem_ctx );
+ }
}
+#if 0
/*
* Debugging information, don't delete.
*/
- /*
+
DEBUG(1,("dumping the NOTIFY_INFO\n"));
DEBUGADD(1,("info->version:[%d], info->flags:[%d], info->count:[%d]\n", info->version, info->flags, info->count));
DEBUGADD(1,("num\ttype\tfield\tres\tid\tsize\tenc_type\n"));
i, info->data[i].type, info->data[i].field, info->data[i].reserved,
info->data[i].id, info->data[i].size, info->data[i].enc_type));
}
- */
+#endif
return WERR_OK;
}
WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCNEX *r_u)
{
POLICY_HND *handle = &q_u->handle;
-/* uint32 change = q_u->change; - notused. */
-/* SPOOL_NOTIFY_OPTION *option = q_u->option; - notused. */
SPOOL_NOTIFY_INFO *info = &r_u->info;
Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
DEBUG(4,("Printer type %x\n",Printer->printer_type));
- /* jfm: the change value isn't used right now.
- * we will honour it when
- * a) we'll be able to send notification to the client
- * b) we'll have a way to communicate between the spoolss process.
- *
- * same thing for option->flags
+ /*
+ * We are now using the change value, and
* I should check for PRINTER_NOTIFY_OPTIONS_REFRESH but as
* I don't have a global notification system, I'm sending back all the
* informations even when _NOTHING_ has changed.
*/
+ /* We need to keep track of the change value to send back in
+ RRPCN replies otherwise our updates are ignored. */
+
+ if (Printer->notify.client_connected) {
+ DEBUG(10,("_spoolss_rfnpcnex: Saving change value in request [%x]\n", q_u->change));
+ Printer->notify.change = q_u->change;
+ }
+
/* just ignore the SPOOL_NOTIFY_OPTION */
switch (Printer->printer_type) {
* construct_printer_info_1
* fill a printer_info_1 struct
********************************************************************/
-
static BOOL construct_printer_info_1(uint32 flags, PRINTER_INFO_1 *printer, int snum)
{
pstring chaine;
SAFE_FREE(dev);
}
+
/****************************************************************************
- Create a DEVMODE struct. Returns malloced memory.
+ Convert an NT_DEVICEMODE to a DEVICEMODE structure. Both pointers
+ should be valid upon entry
****************************************************************************/
-static DEVICEMODE *construct_dev_mode(int snum)
+static BOOL convert_nt_devicemode( DEVICEMODE *devmode, NT_DEVICEMODE *ntdevmode )
{
- char adevice[32];
- char aform[32];
- NT_PRINTER_INFO_LEVEL *printer = NULL;
- NT_DEVICEMODE *ntdevmode = NULL;
- DEVICEMODE *devmode = NULL;
-
- DEBUG(7,("construct_dev_mode\n"));
-
- DEBUGADD(8,("getting printer characteristics\n"));
-
- if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
- DEBUG(2,("construct_dev_mode: malloc fail.\n"));
- return NULL;
- }
-
- ZERO_STRUCTP(devmode);
-
- if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
- goto fail;
-
- if (printer->info_2->devmode)
- ntdevmode = dup_nt_devicemode(printer->info_2->devmode);
-
- if (ntdevmode == NULL)
- goto fail;
-
- DEBUGADD(8,("loading DEVICEMODE\n"));
-
- slprintf(adevice, sizeof(adevice)-1, printer->info_2->printername);
- init_unistr(&devmode->devicename, adevice);
+ if ( !devmode || !ntdevmode )
+ return False;
+
+ init_unistr(&devmode->devicename, ntdevmode->devicename);
- slprintf(aform, sizeof(aform)-1, ntdevmode->formname);
- init_unistr(&devmode->formname, aform);
+ init_unistr(&devmode->formname, ntdevmode->formname);
devmode->specversion = ntdevmode->specversion;
devmode->driverversion = ntdevmode->driverversion;
if (ntdevmode->private != NULL) {
if ((devmode->private=(uint8 *)memdup(ntdevmode->private, ntdevmode->driverextra)) == NULL)
- goto fail;
+ return False;
}
+
+ return True;
+}
- free_nt_devicemode(&ntdevmode);
- free_a_printer(&printer,2);
+/****************************************************************************
+ Create a DEVMODE struct. Returns malloced memory.
+****************************************************************************/
- return devmode;
+DEVICEMODE *construct_dev_mode(int snum)
+{
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ DEVICEMODE *devmode = NULL;
+
+ DEBUG(7,("construct_dev_mode\n"));
+
+ DEBUGADD(8,("getting printer characteristics\n"));
- fail:
+ if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
+ return NULL;
- if (ntdevmode)
- free_nt_devicemode(&ntdevmode);
- if (printer)
- free_a_printer(&printer,2);
- free_dev_mode(devmode);
+ if ( !printer->info_2->devmode ) {
+ DEBUG(5, ("BONG! There was no device mode!\n"));
+ goto done;
+ }
+
+ if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) == NULL) {
+ DEBUG(2,("construct_dev_mode: malloc fail.\n"));
+ goto done;
+ }
+
+ ZERO_STRUCTP(devmode);
+
+ DEBUGADD(8,("loading DEVICEMODE\n"));
- return NULL;
+ if ( !convert_nt_devicemode( devmode, printer->info_2->devmode ) ) {
+ free_dev_mode( devmode );
+ devmode = NULL;
+ }
+
+done:
+ free_a_printer(&printer,2);
+
+ return devmode;
}
/********************************************************************
}
/* check the required size. */
- for (i=0; i<*returned; i++)
+ for (i=0; i<*returned; i++)
(*needed) += spoolss_size_printer_info_2(&printers[i]);
-
+
if (!alloc_buffer_size(buffer, *needed)) {
for (i=0; i<*returned; i++) {
free_devmode(printers[i].devmode);
/* check the required size. */
*needed += spoolss_size_printer_info_2(printer);
-
+
if (!alloc_buffer_size(buffer, *needed)) {
free_printer_info_2(printer);
return WERR_INSUFFICIENT_BUFFER;
* convert an array of ascii string to a UNICODE string
********************************************************************/
-static void init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
+static uint32 init_unistr_array(uint16 **uni_array, fstring *char_array, char *servername)
{
int i=0;
int j=0;
DEBUG(6,("init_unistr_array\n"));
*uni_array=NULL;
- while (1) {
- if (char_array == NULL)
+ while (True)
+ {
+ if ( !char_array )
v = "";
- else {
+ else
+ {
v = char_array[i];
- if (!v) v = ""; /* hack to handle null lists */
+ if (!v)
+ v = ""; /* hack to handle null lists */
}
- if (strlen(v) == 0) break;
- slprintf(line, sizeof(line)-1, "\\\\%s%s", servername, v);
+
+ /* hack to allow this to be used in places other than when generating
+ the list of dependent files */
+
+ if ( servername )
+ slprintf( line, sizeof(line)-1, "\\\\%s%s", servername, v );
+ else
+ pstrcpy( line, v );
+
DEBUGADD(6,("%d:%s:%d\n", i, line, strlen(line)));
- if((tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL) {
+
+ if ( (tuary=Realloc(*uni_array, (j+strlen(line)+2)*sizeof(uint16))) == NULL ) {
DEBUG(2,("init_unistr_array: Realloc error\n" ));
- return;
+ return 0;
} else
*uni_array = tuary;
- j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, 0)/ sizeof(uint16));
+
+ if ( !strlen(v) )
+ break;
+
+ j += (rpcstr_push((*uni_array+j), line, sizeof(uint16)*strlen(line)+2, STR_TERMINATE) / sizeof(uint16));
i++;
}
}
DEBUGADD(6,("last one:done\n"));
+
+ /* return size of array in uint16's */
+
+ return j+1;
}
/********************************************************************
init_unistr( &info->name, driver.info_3->name );
init_unistr( &info->architecture, driver.info_3->environment );
- if (strlen(driver.info_3->driverpath)) {
- slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
- init_unistr( &info->driverpath, temp );
- } else
- init_unistr( &info->driverpath, "" );
+ if (strlen(driver.info_3->driverpath)) {
+ slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->driverpath);
+ init_unistr( &info->driverpath, temp );
+ } else
+ init_unistr( &info->driverpath, "" );
- if (strlen(driver.info_3->datafile)) {
- slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
- init_unistr( &info->datafile, temp );
- } else
- init_unistr( &info->datafile, "" );
+ if (strlen(driver.info_3->datafile)) {
+ slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->datafile);
+ init_unistr( &info->datafile, temp );
+ } else
+ init_unistr( &info->datafile, "" );
- if (strlen(driver.info_3->configfile)) {
- slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
- init_unistr( &info->configfile, temp );
- } else
- init_unistr( &info->configfile, "" );
+ if (strlen(driver.info_3->configfile)) {
+ slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->configfile);
+ init_unistr( &info->configfile, temp );
+ } else
+ init_unistr( &info->configfile, "" );
- if (strlen(driver.info_3->helpfile)) {
- slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
- init_unistr( &info->helpfile, temp );
- } else
- init_unistr( &info->helpfile, "" );
+ if (strlen(driver.info_3->helpfile)) {
+ slprintf(temp, sizeof(temp)-1, "\\\\%s%s", servername, driver.info_3->helpfile);
+ init_unistr( &info->helpfile, temp );
+ } else
+ init_unistr( &info->helpfile, "" );
init_unistr( &info->monitorname, driver.info_3->monitorname );
init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
init_unistr( &info->monitorname, driver.info_3->monitorname );
init_unistr( &info->defaultdatatype, driver.info_3->defaultdatatype );
- info->dependentfiles=NULL;
- init_unistr_array(&info->dependentfiles, driver.info_3->dependentfiles, servername);
+ info->dependentfiles = NULL;
+ init_unistr_array( &info->dependentfiles, driver.info_3->dependentfiles, servername );
info->previousdrivernames=NULL;
init_unistr_array(&info->previousdrivernames, &nullstr, servername);
* fill a printer_info_6 struct
********************************************************************/
-static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum, fstring servername, fstring architecture, uint32 version)
+static WERROR construct_printer_driver_info_6(DRIVER_INFO_6 *info, int snum,
+ fstring servername, fstring architecture, uint32 version)
{
- NT_PRINTER_INFO_LEVEL *printer = NULL;
- NT_PRINTER_DRIVER_INFO_LEVEL driver;
- WERROR status;
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ NT_PRINTER_DRIVER_INFO_LEVEL driver;
+ WERROR status;
+
ZERO_STRUCT(driver);
status=get_a_printer(&printer, 2, lp_servicename(snum) );
+
DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
+
if (!W_ERROR_IS_OK(status))
return WERR_INVALID_PRINTER_NAME;
- status=get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
+ status = get_a_printer_driver(&driver, 3, printer->info_2->drivername, architecture, version);
+
DEBUG(8,("construct_printer_driver_info_6: status: %s\n", dos_errstr(status)));
- if (!W_ERROR_IS_OK(status)) {
+
+ if (!W_ERROR_IS_OK(status))
+ {
/*
* Is this a W2k client ?
*/
UNISTR2 *uni_arch = &q_u->architecture;
uint32 level = q_u->level;
uint32 clientmajorversion = q_u->clientmajorversion;
-/* uint32 clientminorversion = q_u->clientminorversion; - notused. */
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
uint32 *needed = &r_u->needed;
DEBUG(4,("_spoolss_getprinterdriver2\n"));
- *needed=0;
- *servermajorversion=0;
- *serverminorversion=0;
+ *needed = 0;
+ *servermajorversion = 0;
+ *serverminorversion = 0;
pstrcpy(servername, get_called_name());
unistr2_to_ascii(architecture, uni_arch, sizeof(architecture)-1);
WERROR _spoolss_endpageprinter(pipes_struct *p, SPOOL_Q_ENDPAGEPRINTER *q_u, SPOOL_R_ENDPAGEPRINTER *r_u)
{
POLICY_HND *handle = &q_u->handle;
+ int snum;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
return WERR_BADFID;
}
+ if (!get_printer_snum(p, handle, &snum))
+ return WERR_BADFID;
+
Printer->page_started=False;
- print_job_endpage(Printer->jobid);
+ print_job_endpage(snum, Printer->jobid);
return WERR_OK;
}
WERROR _spoolss_startdocprinter(pipes_struct *p, SPOOL_Q_STARTDOCPRINTER *q_u, SPOOL_R_STARTDOCPRINTER *r_u)
{
POLICY_HND *handle = &q_u->handle;
-/* uint32 level = q_u->doc_info_container.level; - notused. */
DOC_INFO *docinfo = &q_u->doc_info_container.docinfo;
uint32 *jobid = &r_u->jobid;
* in EMF format.
*
* So I add checks like in NT Server ...
- *
- * lkclXXXX jean-francois, i love this kind of thing. oh, well,
- * there's a bug in NT client-side code, so we'll fix it in the
- * server-side code. *nnnnnggggh!*
*/
if (info_1->p_datatype != 0) {
unistr2_to_ascii(jobname, &info_1->docname, sizeof(jobname));
- Printer->jobid = print_job_start(&user, snum, jobname);
+ Printer->jobid = print_job_start(&user, snum, jobname, Printer->nt_devmode);
/* An error occured in print_job_start() so return an appropriate
NT error code. */
uint32 buffer_size = q_u->buffer_size;
uint8 *buffer = q_u->buffer;
uint32 *buffer_written = &q_u->buffer_size2;
-
+ int snum;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
if (!Printer) {
return WERR_BADFID;
}
- (*buffer_written) = print_job_write(Printer->jobid, (char *)buffer, buffer_size);
+ if (!get_printer_snum(p, handle, &snum))
+ return WERR_BADFID;
+ (*buffer_written) = print_job_write(snum, Printer->jobid, (char *)buffer, buffer_size);
+ if (*buffer_written == -1) {
+ r_u->buffer_written = 0;
+ if (errno == ENOSPC)
+ return WERR_NO_SPOOL_SPACE;
+ else
+ return WERR_ACCESS_DENIED;
+ }
r_u->buffer_written = q_u->buffer_size2;
/********************************************************************
* api_spoolss_abortprinter
+ * From MSDN: "Deletes printer's spool file if printer is configured
+ * for spooling"
********************************************************************/
WERROR _spoolss_abortprinter(pipes_struct *p, SPOOL_Q_ABORTPRINTER *q_u, SPOOL_R_ABORTPRINTER *r_u)
{
- POLICY_HND *handle = &q_u->handle;
-
- return control_printer(handle, PRINTER_CONTROL_PURGE, p);
+ POLICY_HND *handle = &q_u->handle;
+ Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+ int snum;
+ struct current_user user;
+ WERROR errcode = WERR_OK;
+
+ if (!Printer) {
+ DEBUG(2,("_spoolss_abortprinter: Invalid handle (%s:%u:%u)\n",OUR_HANDLE(handle)));
+ return WERR_BADFID;
+ }
+
+ if (!get_printer_snum(p, handle, &snum))
+ return WERR_BADFID;
+
+ get_current_user( &user, p );
+
+ print_job_delete( &user, snum, Printer->jobid, &errcode );
+
+ return errcode;
}
/********************************************************************
static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
{
+ extern userdom_struct current_user_info;
char *cmd = lp_addprinter_cmd();
char **qlines;
pstring command;
- pstring driverlocation;
int numlines;
int ret;
int fd;
fstring remote_machine = "%m";
- /* build driver path... only 9X architecture is needed for legacy reasons */
- slprintf(driverlocation, sizeof(driverlocation)-1, "\\\\%s\\print$\\WIN40\\0",
- get_called_name());
- /* change \ to \\ for the shell */
- all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring));
- standard_sub_basic("", remote_machine);
-
+ standard_sub_basic(current_user_info.smb_name, remote_machine,sizeof(remote_machine));
+
slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\" \"%s\"",
cmd, printer->info_2->printername, printer->info_2->sharename,
printer->info_2->portname, printer->info_2->drivername,
- printer->info_2->location, driverlocation, remote_machine);
+ printer->info_2->location, printer->info_2->comment, remote_machine);
- /* Convert script args to unix-codepage */
DEBUG(10,("Running [%s]\n", command));
ret = smbrun(command, &fd);
DEBUGADD(10,("returned [%d]\n", ret));
/* Send SIGHUP to process group... is there a better way? */
kill(0, SIGHUP);
- add_all_printers();
+
+ /* reload our services immediately */
+ reload_services( False );
}
file_lines_free(qlines);
-
- update_server_announce_as_printserver();
-
- return True;
-}
-
-#if 0 /* JERRY */
-
-/* Return true if two devicemodes are equal */
-
-#define DEVMODE_CHECK_INT(field) \
- if (d1->field != d2->field) { \
- DEBUG(10, ("nt_devicemode_equal(): " #field " not equal (%d != %d)\n", \
- d1->field, d2->field)); \
- return False; \
- }
-
-/************************************************************************
- Handy, but currently unused functions
- ***********************************************************************/
-
-static BOOL nt_devicemode_equal(NT_DEVICEMODE *d1, NT_DEVICEMODE *d2)
-{
- if (!d1 && !d2) goto equal; /* if both are NULL they are equal */
-
- if (!d1 ^ !d2) {
- DEBUG(10, ("nt_devicemode_equal(): pointers not equal\n"));
- return False; /* if either is exclusively NULL are not equal */
- }
-
- if (!strequal(d1->devicename, d2->devicename)) {
- DEBUG(10, ("nt_devicemode_equal(): device not equal (%s != %s)\n", d1->devicename, d2->devicename));
- return False;
- }
-
- if (!strequal(d1->formname, d2->formname)) {
- DEBUG(10, ("nt_devicemode_equal(): formname not equal (%s != %s)\n", d1->formname, d2->formname));
- return False;
- }
-
- DEVMODE_CHECK_INT(specversion);
- DEVMODE_CHECK_INT(driverversion);
- DEVMODE_CHECK_INT(driverextra);
- DEVMODE_CHECK_INT(orientation);
- DEVMODE_CHECK_INT(papersize);
- DEVMODE_CHECK_INT(paperlength);
- DEVMODE_CHECK_INT(paperwidth);
- DEVMODE_CHECK_INT(scale);
- DEVMODE_CHECK_INT(copies);
- DEVMODE_CHECK_INT(defaultsource);
- DEVMODE_CHECK_INT(printquality);
- DEVMODE_CHECK_INT(color);
- DEVMODE_CHECK_INT(duplex);
- DEVMODE_CHECK_INT(yresolution);
- DEVMODE_CHECK_INT(ttoption);
- DEVMODE_CHECK_INT(collate);
- DEVMODE_CHECK_INT(logpixels);
-
- DEVMODE_CHECK_INT(fields);
- DEVMODE_CHECK_INT(bitsperpel);
- DEVMODE_CHECK_INT(pelswidth);
- DEVMODE_CHECK_INT(pelsheight);
- DEVMODE_CHECK_INT(displayflags);
- DEVMODE_CHECK_INT(displayfrequency);
- DEVMODE_CHECK_INT(icmmethod);
- DEVMODE_CHECK_INT(icmintent);
- DEVMODE_CHECK_INT(mediatype);
- DEVMODE_CHECK_INT(dithertype);
- DEVMODE_CHECK_INT(reserved1);
- DEVMODE_CHECK_INT(reserved2);
- DEVMODE_CHECK_INT(panningwidth);
- DEVMODE_CHECK_INT(panningheight);
-
- /* compare the private data if it exists */
- if (!d1->driverextra && !d2->driverextra) goto equal;
-
-
- DEVMODE_CHECK_INT(driverextra);
-
- if (memcmp(d1->private, d2->private, d1->driverextra)) {
- DEBUG(10, ("nt_devicemode_equal(): private data not equal\n"));
- return False;
- }
-
- equal:
- DEBUG(10, ("nt_devicemode_equal(): devicemodes identical\n"));
- return True;
-}
-
-/* Return true if two NT_PRINTER_PARAM structures are equal */
-
-static BOOL nt_printer_param_equal(NT_PRINTER_PARAM *p1,
- NT_PRINTER_PARAM *p2)
-{
- if (!p1 && !p2) goto equal;
-
- if ((!p1 && p2) || (p1 && !p2)) {
- DEBUG(10, ("nt_printer_param_equal(): pointers differ\n"));
- return False;
- }
-
- /* Compare lists of printer parameters */
-
- while (p1) {
- BOOL found = False;
- NT_PRINTER_PARAM *q = p1;
-
- /* Find the parameter in the second structure */
-
- while(q) {
-
- if (strequal(p1->value, q->value)) {
-
- if (p1->type != q->type) {
- DEBUG(10, ("nt_printer_param_equal():"
- "types for %s differ (%d != %d)\n",
- p1->value, p1->type,
- q->type));
- break;
- }
-
- if (p1->data_len != q->data_len) {
- DEBUG(10, ("nt_printer_param_equal():"
- "len for %s differs (%d != %d)\n",
- p1->value, p1->data_len,
- q->data_len));
- break;
- }
-
- if (memcmp(p1->data, q->data, p1->data_len) == 0) {
- found = True;
- } else {
- DEBUG(10, ("nt_printer_param_equal():"
- "data for %s differs\n", p1->value));
- }
-
- break;
- }
-
- q = q->next;
- }
-
- if (!found) {
- DEBUG(10, ("nt_printer_param_equal(): param %s "
- "does not exist\n", p1->value));
- return False;
- }
-
- p1 = p1->next;
- }
-
- equal:
-
- DEBUG(10, ("nt_printer_param_equal(): printer params identical\n"));
- return True;
-}
-
-/********************************************************************
- * Called by update_printer when trying to work out whether to
- * actually update printer info.
- ********************************************************************/
-
-#define PI_CHECK_INT(field) \
- if (pi1->field != pi2->field) { \
- DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%d != %d)\n", \
- pi1->field, pi2->field)); \
- return False; \
- }
-
-#define PI_CHECK_STR(field) \
- if (!strequal(pi1->field, pi2->field)) { \
- DEBUG(10, ("nt_printer_info_level_equal(): " #field " not equal (%s != %s)\n", \
- pi1->field, pi2->field)); \
- return False; \
- }
-
-static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1,
- NT_PRINTER_INFO_LEVEL *p2)
-{
- NT_PRINTER_INFO_LEVEL_2 *pi1, *pi2;
-
- /* Trivial conditions */
-
- if ((!p1 && !p2) || (!p1->info_2 && !p2->info_2)) {
- goto equal;
- }
-
- if ((!p1 && p2) || (p1 && !p2) ||
- (!p1->info_2 && p2->info_2) ||
- (p1->info_2 && !p2->info_2)) {
- DEBUG(10, ("nt_printer_info_level_equal(): info levels "
- "differ\n"));
- return False;
- }
-
- /* Compare two nt_printer_info_level structures. Don't compare
- status or cjobs as they seem to have something to do with the
- printer queue. */
-
- pi1 = p1->info_2;
- pi2 = p2->info_2;
-
- /* Don't check the attributes as we stomp on the value in
- check_printer_ok() anyway. */
-
-#if 0
- PI_CHECK_INT(attributes);
-#endif
-
- PI_CHECK_INT(priority);
- PI_CHECK_INT(default_priority);
- PI_CHECK_INT(starttime);
- PI_CHECK_INT(untiltime);
- PI_CHECK_INT(averageppm);
-
- /* Yuck - don't check the printername or servername as the
- mod_a_printer() code plays games with them. You can't
- change the printername or the sharename through this interface
- in Samba. */
-
- PI_CHECK_STR(sharename);
- PI_CHECK_STR(portname);
- PI_CHECK_STR(drivername);
- PI_CHECK_STR(comment);
- PI_CHECK_STR(location);
-
- if (!nt_devicemode_equal(pi1->devmode, pi2->devmode)) {
- return False;
- }
-
- PI_CHECK_STR(sepfile);
- PI_CHECK_STR(printprocessor);
- PI_CHECK_STR(datatype);
- PI_CHECK_STR(parameters);
-
- if (!nt_printer_param_equal(pi1->specific, pi2->specific)) {
- return False;
- }
-
- if (!sec_desc_equal(pi1->secdesc_buf->sec, pi2->secdesc_buf->sec)) {
- return False;
- }
-
- PI_CHECK_INT(changeid);
- PI_CHECK_INT(c_setprinter);
- PI_CHECK_INT(setuptime);
-
- equal:
- DEBUG(10, ("nt_printer_info_level_equal(): infos are identical\n"));
return True;
}
-#endif
-
/********************************************************************
* Called by spoolss_api_setprinter
* when updating a printer description.
int snum;
NT_PRINTER_INFO_LEVEL *printer = NULL, *old_printer = NULL;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
- PRINTER_MESSAGE_INFO msg;
WERROR result;
DEBUG(8,("update_printer\n"));
-
- ZERO_STRUCT(msg);
-
+
result = WERR_OK;
if (level!=2) {
result = WERR_NOMEM;
goto done;
}
+
+ /*
+ * make sure we actually reload the services after
+ * this as smb.conf could have a new section in it
+ * .... shouldn't .... but could
+ */
+ reload_services(False);
}
/* Do sanity check on the requested changes for Samba */
goto done;
}
-#if 0 /* JERRY */
-
- /*
- * Another one of those historical misunderstandings...
- * This is reminisent of a similar call we had in _spoolss_setprinterdata()
- * I'm leaving it here as a reminder. --jerry
- */
-
- if (nt_printer_info_level_equal(printer, old_printer)) {
- DEBUG(3, ("update_printer: printer info has not changed\n"));
- result = WERR_OK;
- goto done;
- }
-
-#endif
-
/* Check calling user has permission to update printer description */
if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
}
/* Call addprinter hook */
-
- if (*lp_addprinter_cmd()) {
+ /* Check changes to see if this is really needed */
+
+ if ( *lp_addprinter_cmd()
+ && (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)
+ || !strequal(printer->info_2->comment, old_printer->info_2->comment)
+ || !strequal(printer->info_2->portname, old_printer->info_2->portname)
+ || !strequal(printer->info_2->location, old_printer->info_2->location)) )
+ {
if ( !add_printer_hook(printer) ) {
result = WERR_ACCESS_DENIED;
goto done;
}
/*
- * Set the DRIVER_INIT info in the tdb; trigger on magic value for the
- * DEVMODE.displayfrequency, which is not used for printer drivers. This
- * requires Win32 client code (see other notes elsewhere in the code).
+ * When a *new* driver is bound to a printer, the drivername is used to
+ * lookup previously saved driver initialization info, which is then
+ * bound to the printer, simulating what happens in the Windows arch.
*/
- if (printer->info_2->devmode &&
- printer->info_2->devmode->displayfrequency == MAGIC_DISPLAY_FREQUENCY) {
-
- DEBUG(10,("update_printer: Save printer driver init data\n"));
- printer->info_2->devmode->displayfrequency = 0;
-
- if (update_driver_init(*printer, 2)!=0) {
- DEBUG(10,("update_printer: error updating printer driver init DEVMODE\n"));
- result = WERR_ACCESS_DENIED;
- goto done;
- }
- } else {
- /*
- * When a *new* driver is bound to a printer, the drivername is used to
- * lookup previously saved driver initialization info, which is then
- * bound to the printer, simulating what happens in the Windows arch.
- */
- if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){
- if (!set_driver_init(printer, 2)) {
- DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
- printer->info_2->drivername));
- }
- msg.flags |= PRINTER_MESSAGE_DRIVER;
+ if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername))
+ {
+ if (!set_driver_init(printer, 2))
+ {
+ DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n",
+ printer->info_2->drivername));
}
+
+ DEBUG(10,("update_printer: changing driver [%s]! Sending event!\n",
+ printer->info_2->drivername));
+
+ notify_printer_driver(snum, printer->info_2->drivername);
}
/* Update printer info */
all the possible changes */
if (!strequal(printer->info_2->comment, old_printer->info_2->comment))
- msg.flags |= PRINTER_MESSAGE_COMMENT;
+ notify_printer_comment(snum, printer->info_2->comment);
if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename))
- msg.flags |= PRINTER_MESSAGE_SHARENAME;
+ notify_printer_sharename(snum, printer->info_2->sharename);
if (!strequal(printer->info_2->portname, old_printer->info_2->portname))
- msg.flags |= PRINTER_MESSAGE_PORT;
+ notify_printer_port(snum, printer->info_2->portname);
if (!strequal(printer->info_2->location, old_printer->info_2->location))
- msg.flags |= PRINTER_MESSAGE_LOCATION;
+ notify_printer_location(snum, printer->info_2->location);
- msg.low = PRINTER_CHANGE_ADD_PRINTER;
- fstrcpy(msg.printer_name, printer->info_2->printername);
-
- /* only send a notify if something changed */
- if (msg.flags) {
- srv_spoolss_sendnotify(msg.printer_name, 0, PRINTER_CHANGE_ADD_PRINTER, msg.flags);
- }
-
- done:
+done:
free_a_printer(&printer, 2);
free_a_printer(&old_printer, 2);
WERROR _spoolss_fcpn(pipes_struct *p, SPOOL_Q_FCPN *q_u, SPOOL_R_FCPN *r_u)
{
POLICY_HND *handle = &q_u->handle;
-
Printer_entry *Printer= find_printer_index_by_hnd(p, handle);
if (!Printer) {
return WERR_BADFID;
}
- if (Printer->notify.client_connected==True)
- srv_spoolss_replycloseprinter(&Printer->notify.client_hnd);
+ if (Printer->notify.client_connected==True) {
+ int snum = -1;
+
+ if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
+ snum = -1;
+ else if ( (Printer->printer_type == PRINTER_HANDLE_IS_PRINTER) &&
+ !get_printer_snum(p, handle, &snum) )
+ return WERR_BADFID;
+
+ srv_spoolss_replycloseprinter(snum, &Printer->notify.client_hnd);
+ }
Printer->notify.flags=0;
Printer->notify.options=0;
static BOOL fill_job_info_2(JOB_INFO_2 *job_info, print_queue_struct *queue,
int position, int snum,
- NT_PRINTER_INFO_LEVEL *ntprinter,
+ NT_PRINTER_INFO_LEVEL *ntprinter,
DEVICEMODE *devmode)
{
pstring temp_name;
*returned = 0;
goto done;
}
-
- if (!(devmode = construct_dev_mode(snum))) {
- *returned = 0;
- result = WERR_NOMEM;
- goto done;
- }
+
+ /* this should not be a failure condition if the devmode is NULL */
+
+ devmode = construct_dev_mode(snum);
for (i=0; i<*returned; i++)
fill_job_info_2(&(info[i]), &queue[i], i, snum, ntprinter,
SAFE_FREE(info);
return result;
+
}
/****************************************************************************
WERROR _spoolss_enumjobs( pipes_struct *p, SPOOL_Q_ENUMJOBS *q_u, SPOOL_R_ENUMJOBS *r_u)
{
POLICY_HND *handle = &q_u->handle;
-/* uint32 firstjob = q_u->firstjob; - notused. */
-/* uint32 numofjobs = q_u->numofjobs; - notused. */
uint32 level = q_u->level;
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
{
POLICY_HND *handle = &q_u->handle;
uint32 jobid = q_u->jobid;
-/* uint32 level = q_u->level; - notused. */
-/* JOB_INFO *ctr = &q_u->ctr; - notused. */
uint32 command = q_u->command;
struct current_user user;
return WERR_BADFID;
}
- if (!print_job_exists(jobid)) {
+ if (!print_job_exists(snum, jobid)) {
return WERR_INVALID_PRINTER_NAME;
}
switch (command) {
case JOB_CONTROL_CANCEL:
case JOB_CONTROL_DELETE:
- if (print_job_delete(&user, jobid, &errcode)) {
+ if (print_job_delete(&user, snum, jobid, &errcode)) {
errcode = WERR_OK;
}
break;
case JOB_CONTROL_PAUSE:
- if (print_job_pause(&user, jobid, &errcode)) {
+ if (print_job_pause(&user, snum, jobid, &errcode)) {
errcode = WERR_OK;
}
break;
case JOB_CONTROL_RESTART:
case JOB_CONTROL_RESUME:
- if (print_job_resume(&user, jobid, &errcode)) {
+ if (print_job_resume(&user, snum, jobid, &errcode)) {
errcode = WERR_OK;
}
break;
*returned=0;
-#define MAX_VERSION 4
-
- for (version=0; version<MAX_VERSION; version++) {
+ for (version=0; version<DRIVER_MAX_VERSION; version++) {
list=NULL;
ndrivers=get_ntdrivers(&list, architecture, version);
DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
*returned=0;
-#define MAX_VERSION 4
-
- for (version=0; version<MAX_VERSION; version++) {
+ for (version=0; version<DRIVER_MAX_VERSION; version++) {
list=NULL;
ndrivers=get_ntdrivers(&list, architecture, version);
DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
*returned=0;
-#define MAX_VERSION 4
-
- for (version=0; version<MAX_VERSION; version++) {
+ for (version=0; version<DRIVER_MAX_VERSION; version++) {
list=NULL;
ndrivers=get_ntdrivers(&list, architecture, version);
DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, architecture, version));
WERROR _spoolss_enumprinterdrivers( pipes_struct *p, SPOOL_Q_ENUMPRINTERDRIVERS *q_u, SPOOL_R_ENUMPRINTERDRIVERS *r_u)
{
-/* UNISTR2 *name = &q_u->name; - notused. */
UNISTR2 *environment = &q_u->environment;
uint32 level = q_u->level;
NEW_BUFFER *buffer = NULL;
WERROR _spoolss_enumforms(pipes_struct *p, SPOOL_Q_ENUMFORMS *q_u, SPOOL_R_ENUMFORMS *r_u)
{
-/* POLICY_HND *handle = &q_u->handle; - notused. */
uint32 level = q_u->level;
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
WERROR _spoolss_getform(pipes_struct *p, SPOOL_Q_GETFORM *q_u, SPOOL_R_GETFORM *r_u)
{
-/* POLICY_HND *handle = &q_u->handle; - notused. */
uint32 level = q_u->level;
UNISTR2 *uni_formname = &q_u->formname;
NEW_BUFFER *buffer = NULL;
WERROR _spoolss_enumports( pipes_struct *p, SPOOL_Q_ENUMPORTS *q_u, SPOOL_R_ENUMPORTS *r_u)
{
-/* UNISTR2 *name = &q_u->name; - notused. */
uint32 level = q_u->level;
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
return WERR_PRINTER_ALREADY_EXISTS;
}
- if (*lp_addprinter_cmd() )
+ if (*lp_addprinter_cmd() ) {
if ( !add_printer_hook(printer) ) {
free_a_printer(&printer,2);
return WERR_ACCESS_DENIED;
}
+ }
slprintf(name, sizeof(name)-1, "\\\\%s\\%s", get_called_name(),
printer->info_2->sharename);
+
if ((snum = print_queue_snum(printer->info_2->sharename)) == -1) {
free_a_printer(&printer,2);
return WERR_ACCESS_DENIED;
*/
if (!devmode)
+ {
set_driver_init(printer, 2);
- else {
+ }
+ else
+ {
/* A valid devmode was included, convert and link it
*/
DEBUGADD(10, ("spoolss_addprinterex_level_2: devmode included, converting\n"));
return WERR_NOMEM;
}
- set_driver_init(printer, 2);
-
/* write the ASCII on disk */
err = mod_a_printer(*printer, 2);
if (!W_ERROR_IS_OK(err)) {
}
update_c_setprinter(False);
-
- srv_spoolss_sendnotify(printer->info_2->printername, 0, PRINTER_CHANGE_ADD_PRINTER, 0x0);
-
free_a_printer(&printer,2);
return WERR_OK;
WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, SPOOL_R_ADDPRINTERDRIVER *r_u)
{
-/* UNISTR2 *server_name = &q_u->server_name; - notused. */
uint32 level = q_u->level;
SPOOL_PRINTER_DRIVER_INFO_LEVEL *info = &q_u->info;
WERROR err = WERR_OK;
ZERO_STRUCT(driver);
- get_current_user(&user, p);
+ get_current_user(&user, p);
if (!convert_printer_driver_info(info, &driver, level)) {
err = WERR_NOMEM;
}
/* BEGIN_ADMIN_LOG */
- switch(level) {
- case 3:
- sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
- driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
- fstrcpy(driver_name, driver.info_3->name);
- break;
- case 6:
- sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
- driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
- fstrcpy(driver_name, driver.info_6->name);
- break;
- }
+ switch(level) {
+ case 3:
+ sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
+ driver.info_3->name,drv_ver_to_os[driver.info_3->cversion],uidtoname(user.uid));
+ fstrcpy(driver_name, driver.info_3->name);
+ break;
+ case 6:
+ sys_adminlog(LOG_INFO,"Added printer driver. Print driver name: %s. Print driver OS: %s. Administrator name: %s.",
+ driver.info_6->name,drv_ver_to_os[driver.info_6->version],uidtoname(user.uid));
+ fstrcpy(driver_name, driver.info_6->name);
+ break;
+ }
/* END_ADMIN_LOG */
- /*
+ /*
* I think this is where he DrvUpgradePrinter() hook would be
* be called in a driver's interface DLL on a Windows NT 4.0/2k
* server. Right now, we just need to send ourselves a message
- * to update each printer bound to this driver. --jerry
+ * to update each printer bound to this driver. --jerry
*/
-
+
if (!srv_spoolss_drv_upgrade_printer(driver_name)) {
DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n",
driver_name));
/*
* No 2k/Xp driver found, delete init data (if any) for the new Nt driver.
*/
- if (!del_driver_init(driver_name))
+ if (!del_driver_init(driver_name))
DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));
- } else {
+ } else {
/*
* a 2k/Xp driver was found, don't delete init data because Nt driver will use it.
*/
default:
DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level));
break;
- }
+ }
- done:
+done:
free_a_printer_driver(driver, level);
return err;
}
+/********************************************************************
+ * spoolss_addprinterdriverex
+ ********************************************************************/
+
+WERROR _spoolss_addprinterdriverex(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVEREX *q_u, SPOOL_R_ADDPRINTERDRIVEREX *r_u)
+{
+ SPOOL_Q_ADDPRINTERDRIVER q_u_local;
+ SPOOL_R_ADDPRINTERDRIVER r_u_local;
+
+ /*
+ * we only support the semantics of AddPrinterDriver()
+ * i.e. only copy files that are newer than existing ones
+ */
+
+ if ( q_u->copy_flags != APD_COPY_NEW_FILES )
+ return WERR_ACCESS_DENIED;
+
+ ZERO_STRUCT(q_u_local);
+ ZERO_STRUCT(r_u_local);
+
+ /* just pass the information off to _spoolss_addprinterdriver() */
+ q_u_local.server_name_ptr = q_u->server_name_ptr;
+ copy_unistr2(&q_u_local.server_name, &q_u->server_name);
+ q_u_local.level = q_u->level;
+ memcpy( &q_u_local.info, &q_u->info, sizeof(SPOOL_PRINTER_DRIVER_INFO_LEVEL) );
+
+ return _spoolss_addprinterdriver( p, &q_u_local, &r_u_local );
+}
+
/****************************************************************************
****************************************************************************/
WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, SPOOL_R_ENUMPRINTERDATA *r_u)
{
POLICY_HND *handle = &q_u->handle;
- uint32 idx = q_u->index;
- uint32 in_value_len = q_u->valuesize;
- uint32 in_data_len = q_u->datasize;
+ uint32 idx = q_u->index;
+ uint32 in_value_len = q_u->valuesize;
+ uint32 in_data_len = q_u->datasize;
uint32 *out_max_value_len = &r_u->valuesize;
- uint16 **out_value = &r_u->value;
- uint32 *out_value_len = &r_u->realvaluesize;
- uint32 *out_type = &r_u->type;
+ uint16 **out_value = &r_u->value;
+ uint32 *out_value_len = &r_u->realvaluesize;
+ uint32 *out_type = &r_u->type;
uint32 *out_max_data_len = &r_u->datasize;
- uint8 **data_out = &r_u->data;
- uint32 *out_data_len = &r_u->realdatasize;
+ uint8 **data_out = &r_u->data;
+ uint32 *out_data_len = &r_u->realdatasize;
NT_PRINTER_INFO_LEVEL *printer = NULL;
- fstring value;
+ uint32 param_index;
+ uint32 biggest_valuesize;
+ uint32 biggest_datasize;
+ uint32 data_len;
+ Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+ int snum;
+ WERROR result;
+ REGISTRY_VALUE *val;
+ NT_PRINTER_DATA *p_data;
+ int i, key_index, num_values;
+ int name_length;
- uint32 param_index;
- uint32 biggest_valuesize;
- uint32 biggest_datasize;
- uint32 data_len;
- Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
- int snum;
- uint8 *data=NULL;
- uint32 type;
- WERROR result;
-
- ZERO_STRUCT(printer);
+ ZERO_STRUCT( printer );
- *out_type=0;
+ *out_type = 0;
- *out_max_data_len=0;
- *data_out=NULL;
- *out_data_len=0;
+ *out_max_data_len = 0;
+ *data_out = NULL;
+ *out_data_len = 0;
DEBUG(5,("spoolss_enumprinterdata\n"));
result = get_a_printer(&printer, 2, lp_servicename(snum));
if (!W_ERROR_IS_OK(result))
return result;
+
+ p_data = &printer->info_2->data;
+ key_index = lookup_printerkey( p_data, SPOOL_PRINTERDATA_KEY );
+
+ result = WERR_OK;
/*
* The NT machine wants to know the biggest size of value and data
*
* cf: MSDN EnumPrinterData remark section
*/
- if ( (in_value_len==0) && (in_data_len==0) ) {
+
+ if ( !in_value_len && !in_data_len )
+ {
DEBUGADD(6,("Activating NT mega-hack to find sizes\n"));
- SAFE_FREE(data);
-
- param_index=0;
- biggest_valuesize=0;
- biggest_datasize=0;
+ param_index = 0;
+ biggest_valuesize = 0;
+ biggest_datasize = 0;
+
+ num_values = regval_ctr_numvals( &p_data->keys[key_index].values );
- while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len)) {
- if (strlen(value) > biggest_valuesize) biggest_valuesize=strlen(value);
- if (data_len > biggest_datasize) biggest_datasize=data_len;
-
- DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize, biggest_datasize));
-
- SAFE_FREE(data);
- param_index++;
+ for ( i=0; i<num_values; i++ )
+ {
+ val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
+
+ name_length = strlen(val->valuename);
+ if ( strlen(val->valuename) > biggest_valuesize )
+ biggest_valuesize = name_length;
+
+ if ( val->size > biggest_datasize )
+ biggest_datasize = val->size;
+
+ DEBUG(6,("current values: [%d], [%d]\n", biggest_valuesize,
+ biggest_datasize));
}
- /* the value is an UNICODE string but realvaluesize is the length in bytes including the leading 0 */
- *out_value_len=2*(1+biggest_valuesize);
- *out_data_len=biggest_datasize;
+ /* the value is an UNICODE string but real_value_size is the length
+ in bytes including the trailing 0 */
+
+ *out_value_len = 2 * (1+biggest_valuesize);
+ *out_data_len = biggest_datasize;
DEBUG(6,("final values: [%d], [%d]\n", *out_value_len, *out_data_len));
- free_a_printer(&printer, 2);
- return WERR_OK;
+ goto done;
}
/*
* the value len is wrong in NT sp3
* that's the number of bytes not the number of unicode chars
*/
+
+ val = regval_ctr_specific_value( &p_data->keys[key_index].values, idx );
- if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) {
-
- SAFE_FREE(data);
- free_a_printer(&printer, 2);
+ if ( !val )
+ {
/* out_value should default to "" or else NT4 has
problems unmarshalling the response */
- *out_max_value_len=(in_value_len/sizeof(uint16));
- if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL)
- return WERR_NOMEM;
+ *out_max_value_len = (in_value_len/sizeof(uint16));
+
+ if ( (*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
+ {
+ result = WERR_NOMEM;
+ goto done;
+ }
- *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0);
+ *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0);
/* the data is counted in bytes */
+
*out_max_data_len = in_data_len;
- *out_data_len = in_data_len;
- if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
- return WERR_NOMEM;
+ *out_data_len = in_data_len;
+
+ /* only allocate when given a non-zero data_len */
+
+ if ( in_data_len && ((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) )
+ {
+ result = WERR_NOMEM;
+ goto done;
+ }
- return WERR_NO_MORE_ITEMS;
+ result = WERR_NO_MORE_ITEMS;
}
-
- free_a_printer(&printer, 2);
-
- /*
- * the value is:
- * - counted in bytes in the request
- * - counted in UNICODE chars in the max reply
- * - counted in bytes in the real size
- *
- * take a pause *before* coding not *during* coding
- */
+ else
+ {
+ /*
+ * the value is:
+ * - counted in bytes in the request
+ * - counted in UNICODE chars in the max reply
+ * - counted in bytes in the real size
+ *
+ * take a pause *before* coding not *during* coding
+ */
- *out_max_value_len=(in_value_len/sizeof(uint16));
- if((*out_value=(uint16 *)talloc_zero(p->mem_ctx,in_value_len*sizeof(uint8))) == NULL) {
- SAFE_FREE(data);
- return WERR_NOMEM;
- }
+ /* name */
+ *out_max_value_len = ( in_value_len / sizeof(uint16) );
+ if ( (*out_value = (uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL )
+ {
+ result = WERR_NOMEM;
+ goto done;
+ }
- *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0);
+ *out_value_len = (uint32)rpcstr_push((char *)*out_value, regval_name(val), in_value_len, 0);
- *out_type=type;
+ /* type */
+
+ *out_type = regval_type( val );
- /* the data is counted in bytes */
- *out_max_data_len=in_data_len;
- if((*data_out=(uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL) {
- SAFE_FREE(data);
- return WERR_NOMEM;
+ /* data - counted in bytes */
+
+ *out_max_data_len = in_data_len;
+ if ( (*data_out = (uint8 *)talloc_zero(p->mem_ctx, in_data_len*sizeof(uint8))) == NULL)
+ {
+ result = WERR_NOMEM;
+ goto done;
+ }
+ data_len = (size_t)regval_size(val);
+ memcpy( *data_out, regval_data_p(val), data_len );
+ *out_data_len = data_len;
}
-
- memcpy(*data_out, data, (size_t)data_len);
- *out_data_len=data_len;
- SAFE_FREE(data);
-
- return WERR_OK;
+done:
+ free_a_printer(&printer, 2);
+ return result;
}
/****************************************************************************
WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SPOOL_R_SETPRINTERDATA *r_u)
{
- POLICY_HND *handle = &q_u->handle;
- UNISTR2 *value = &q_u->value;
- uint32 type = q_u->type;
-/* uint32 max_len = q_u->max_len; - notused. */
- uint8 *data = q_u->data;
- uint32 real_len = q_u->real_len;
-/* uint32 numeric_data = q_u->numeric_data; - notused. */
+ POLICY_HND *handle = &q_u->handle;
+ UNISTR2 *value = &q_u->value;
+ uint32 type = q_u->type;
+ uint8 *data = q_u->data;
+ uint32 real_len = q_u->real_len;
- NT_PRINTER_INFO_LEVEL *printer = NULL;
- NT_PRINTER_PARAM *param = NULL, old_param;
- int snum=0;
- WERROR status = WERR_OK;
- Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ int snum=0;
+ WERROR status = WERR_OK;
+ Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+ fstring valuename;
DEBUG(5,("spoolss_setprinterdata\n"));
if (!get_printer_snum(p,handle, &snum))
return WERR_BADFID;
- ZERO_STRUCT(old_param);
-
/*
* Access check : NT returns "access denied" if you make a
* SetPrinterData call without the necessary privildge.
* when connecting to a printer --jerry
*/
- if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+ if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
+ {
DEBUG(3, ("_spoolss_setprinterdata: change denied by handle access permissions\n"));
status = WERR_ACCESS_DENIED;
goto done;
}
- /* Check if we are making any changes or not. Return true if
- nothing is actually changing. This is not needed anymore but
- has been left in as an optimization to keep from from
- writing to disk as often --jerry */
-
status = get_a_printer(&printer, 2, lp_servicename(snum));
if (!W_ERROR_IS_OK(status))
return status;
- convert_specific_param(¶m, value , type, data, real_len);
-
- unlink_specific_param_if_exist(printer->info_2, param);
+ unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
/*
* When client side code sets a magic printer data key, detect it and save
* the current printer data and the magic key's data (its the DEVMODE) for
* future printer/driver initializations.
*/
- if (param->type==3 && !strcmp( param->value, PHANTOM_DEVMODE_KEY)) {
- /*
- * Set devmode and printer initialization info
- */
- status = save_driver_init(printer, 2, param);
+ if ( (type == REG_BINARY) && strequal( valuename, PHANTOM_DEVMODE_KEY))
+ {
+ /* Set devmode and printer initialization info */
+ status = save_driver_init( printer, 2, data, real_len );
+
+ srv_spoolss_reset_printerdata( printer->info_2->drivername );
}
- else {
- add_a_specific_param(printer->info_2, ¶m);
- status = mod_a_printer(*printer, 2);
+ else
+ {
+ status = set_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename,
+ type, data, real_len );
+ if ( W_ERROR_IS_OK(status) )
+ status = mod_a_printer(*printer, 2);
}
- done:
+done:
free_a_printer(&printer, 2);
- if (param)
- free_nt_printer_param(¶m);
- SAFE_FREE(old_param.data);
return status;
}
WERROR _spoolss_resetprinter(pipes_struct *p, SPOOL_Q_RESETPRINTER *q_u, SPOOL_R_RESETPRINTER *r_u)
{
- POLICY_HND *handle = &q_u->handle;
- Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
- int snum;
+ POLICY_HND *handle = &q_u->handle;
+ Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+ int snum;
DEBUG(5,("_spoolss_resetprinter\n"));
}
+/****************************************************************************
+****************************************************************************/
+
WERROR _spoolss_deleteprinterdata(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATA *q_u, SPOOL_R_DELETEPRINTERDATA *r_u)
{
- POLICY_HND *handle = &q_u->handle;
- UNISTR2 *value = &q_u->valuename;
+ POLICY_HND *handle = &q_u->handle;
+ UNISTR2 *value = &q_u->valuename;
- NT_PRINTER_INFO_LEVEL *printer = NULL;
- NT_PRINTER_PARAM param;
- int snum=0;
- WERROR status = WERR_OK;
- Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ int snum=0;
+ WERROR status = WERR_OK;
+ Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+ pstring valuename;
DEBUG(5,("spoolss_deleteprinterdata\n"));
if (!W_ERROR_IS_OK(status))
return status;
- ZERO_STRUCTP(¶m);
- unistr2_to_ascii(param.value, value, sizeof(param.value)-1);
+ unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
- if(!unlink_specific_param_if_exist(printer->info_2, ¶m))
- status = WERR_INVALID_PARAM;
- else
- status = mod_a_printer(*printer, 2);
+ status = delete_printer_dataex( printer, SPOOL_PRINTERDATA_KEY, valuename );
free_a_printer(&printer, 2);
+
return status;
}
WERROR _spoolss_addform( pipes_struct *p, SPOOL_Q_ADDFORM *q_u, SPOOL_R_ADDFORM *r_u)
{
POLICY_HND *handle = &q_u->handle;
-/* uint32 level = q_u->level; - notused. */
FORM *form = &q_u->form;
nt_forms_struct tmpForm;
int snum;
DEBUG(2,("_spoolss_addform: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
return WERR_BADFID;
}
+
+
+ /* forms can be added on printer of on the print server handle */
+
+ if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ {
+ if (!get_printer_snum(p,handle, &snum))
+ return WERR_BADFID;
+
+ status = get_a_printer(&printer, 2, lp_servicename(snum));
+ if (!W_ERROR_IS_OK(status))
+ goto done;
+ }
- if (!get_printer_snum(p,handle, &snum))
- return WERR_BADFID;
-
- if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+ if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
DEBUG(2,("_spoolss_addform: denied by handle permissions.\n"));
status = WERR_ACCESS_DENIED;
goto done;
}
-
+
/* can't add if builtin */
+
if (get_a_builtin_ntform(&form->name,&tmpForm)) {
- return WERR_ALREADY_EXISTS;
+ status = WERR_ALREADY_EXISTS;
+ goto done;
}
- count=get_ntforms(&list);
- if(!add_a_form(&list, form, &count))
- return WERR_NOMEM;
+ count = get_ntforms(&list);
+
+ if(!add_a_form(&list, form, &count)) {
+ status = WERR_NOMEM;
+ goto done;
+ }
+
write_ntforms(&list, count);
/*
- * ChangeID must always be set
+ * ChangeID must always be set if this is a printer
*/
- status = get_a_printer(&printer, 2, lp_servicename(snum));
- if (!W_ERROR_IS_OK(status))
- goto done;
-
- status = mod_a_printer(*printer, 2);
- if (!W_ERROR_IS_OK(status))
- goto done;
+ if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ status = mod_a_printer(*printer, 2);
done:
- free_a_printer(&printer, 2);
+ if ( printer )
+ free_a_printer(&printer, 2);
SAFE_FREE(list);
return status;
UNISTR2 *form_name = &q_u->name;
nt_forms_struct tmpForm;
int count=0;
- WERROR ret = WERR_OK;
nt_forms_struct *list=NULL;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
int snum;
return WERR_BADFID;
}
- if (!get_printer_snum(p, handle, &snum))
- return WERR_BADFID;
+ /* forms can be deleted on printer of on the print server handle */
+
+ if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ {
+ if (!get_printer_snum(p,handle, &snum))
+ return WERR_BADFID;
+
+ status = get_a_printer(&printer, 2, lp_servicename(snum));
+ if (!W_ERROR_IS_OK(status))
+ goto done;
+ }
- if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
- DEBUG(2,("_spoolss_deleteform: denied by handle permissions\n"));
- return WERR_ACCESS_DENIED;
+ if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
+ DEBUG(2,("_spoolss_deleteform: denied by handle permissions.\n"));
+ status = WERR_ACCESS_DENIED;
+ goto done;
}
/* can't delete if builtin */
+
if (get_a_builtin_ntform(form_name,&tmpForm)) {
- return WERR_INVALID_PARAM;
+ status = WERR_INVALID_PARAM;
+ goto done;
}
count = get_ntforms(&list);
- if(!delete_a_form(&list, form_name, &count, &ret))
- return WERR_INVALID_PARAM;
+
+ if ( !delete_a_form(&list, form_name, &count, &status ))
+ goto done;
/*
- * ChangeID must always be set
+ * ChangeID must always be set if this is a printer
*/
- status = get_a_printer(&printer, 2, lp_servicename(snum));
- if (!W_ERROR_IS_OK(status))
- goto done;
-
- status = mod_a_printer(*printer, 2);
- if (!W_ERROR_IS_OK(status))
- goto done;
+ if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ status = mod_a_printer(*printer, 2);
done:
- free_a_printer(&printer, 2);
+ if ( printer )
+ free_a_printer(&printer, 2);
SAFE_FREE(list);
- return ret;
+ return status;
}
/****************************************************************************
WERROR _spoolss_setform(pipes_struct *p, SPOOL_Q_SETFORM *q_u, SPOOL_R_SETFORM *r_u)
{
POLICY_HND *handle = &q_u->handle;
-/* UNISTR2 *uni_name = &q_u->name; - notused. */
-/* uint32 level = q_u->level; - notused. */
FORM *form = &q_u->form;
nt_forms_struct tmpForm;
int snum;
return WERR_BADFID;
}
- if (!get_printer_snum(p, handle, &snum))
- return WERR_BADFID;
+ /* forms can be modified on printer of on the print server handle */
+
+ if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ {
+ if (!get_printer_snum(p,handle, &snum))
+ return WERR_BADFID;
+
+ status = get_a_printer(&printer, 2, lp_servicename(snum));
+ if (!W_ERROR_IS_OK(status))
+ goto done;
+ }
- if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+ if ( !(Printer->access_granted & (PRINTER_ACCESS_ADMINISTER|SERVER_ACCESS_ADMINISTER)) ) {
DEBUG(2,("_spoolss_setform: denied by handle permissions\n"));
- return WERR_ACCESS_DENIED;
+ status = WERR_ACCESS_DENIED;
+ goto done;
}
/* can't set if builtin */
if (get_a_builtin_ntform(&form->name,&tmpForm)) {
- return WERR_INVALID_PARAM;
+ status = WERR_INVALID_PARAM;
+ goto done;
}
- count=get_ntforms(&list);
+ count = get_ntforms(&list);
update_a_form(&list, form, count);
write_ntforms(&list, count);
/*
- * ChangeID must always be set
+ * ChangeID must always be set if this is a printer
*/
- status = get_a_printer(&printer, 2, lp_servicename(snum));
- if (!W_ERROR_IS_OK(status))
- goto done;
+ if ( Printer->printer_type == PRINTER_HANDLE_IS_PRINTER )
+ status = mod_a_printer(*printer, 2);
- status = mod_a_printer(*printer, 2);
- if (!W_ERROR_IS_OK(status))
- goto done;
done:
- free_a_printer(&printer, 2);
+ if ( printer )
+ free_a_printer(&printer, 2);
SAFE_FREE(list);
- return WERR_OK;
+ return status;
}
/****************************************************************************
WERROR _spoolss_enumprintprocessors(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCESSORS *q_u, SPOOL_R_ENUMPRINTPROCESSORS *r_u)
{
-/* UNISTR2 *name = &q_u->name; - notused. */
-/* UNISTR2 *environment = &q_u->environment; - notused. */
uint32 level = q_u->level;
- NEW_BUFFER *buffer = NULL;
+ NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
- uint32 *needed = &r_u->needed;
+ uint32 *needed = &r_u->needed;
uint32 *returned = &r_u->returned;
/* that's an [in out] buffer */
WERROR _spoolss_enumprintprocdatatypes(pipes_struct *p, SPOOL_Q_ENUMPRINTPROCDATATYPES *q_u, SPOOL_R_ENUMPRINTPROCDATATYPES *r_u)
{
-/* UNISTR2 *name = &q_u->name; - notused. */
-/* UNISTR2 *processor = &q_u->processor; - notused. */
uint32 level = q_u->level;
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
WERROR _spoolss_enumprintmonitors(pipes_struct *p, SPOOL_Q_ENUMPRINTMONITORS *q_u, SPOOL_R_ENUMPRINTMONITORS *r_u)
{
-/* UNISTR2 *name = &q_u->name; - notused. */
uint32 level = q_u->level;
- NEW_BUFFER *buffer = NULL;
+ NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
- uint32 *needed = &r_u->needed;
+ uint32 *needed = &r_u->needed;
uint32 *returned = &r_u->returned;
/* that's an [in out] buffer */
return WERR_NOMEM;
}
- for (i=0; i<count && found==False; i++) {
+ for (i=0; i<count && found==False; i++) {
if (queue[i].job==(int)jobid)
found=True;
}
fill_job_info_1(info_1, &(queue[i-1]), i, snum);
- SAFE_FREE(queue);
-
*needed += spoolss_size_job_info_1(info_1);
if (!alloc_buffer_size(buffer, *needed)) {
static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uint32 jobid, NEW_BUFFER *buffer, uint32 offered, uint32 *needed)
{
- int i=0;
- BOOL found=False;
- JOB_INFO_2 *info_2;
+ int i = 0;
+ BOOL found = False;
+ JOB_INFO_2 *info_2;
NT_PRINTER_INFO_LEVEL *ntprinter = NULL;
- WERROR ret;
- DEVICEMODE *devmode = NULL;
+ WERROR ret;
+ DEVICEMODE *devmode = NULL;
+ NT_DEVICEMODE *nt_devmode = NULL;
info_2=(JOB_INFO_2 *)malloc(sizeof(JOB_INFO_2));
goto done;
}
- for (i=0; i<count && found==False; i++) {
- if (queue[i].job==(int)jobid)
- found=True;
+ for ( i=0; i<count && found==False; i++ )
+ {
+ if (queue[i].job == (int)jobid)
+ found = True;
}
- if (found==False) {
+ if ( !found )
+ {
/* NT treats not found as bad param... yet another bad
choice */
ret = WERR_INVALID_PARAM;
ret = get_a_printer(&ntprinter, 2, lp_servicename(snum));
if (!W_ERROR_IS_OK(ret))
goto done;
- if (construct_dev_mode(snum) == NULL) {
- ret = WERR_NOMEM;
- goto done;
+
+ /*
+ * if the print job does not have a DEVMODE associated with it,
+ * just use the one for the printer. A NULL devicemode is not
+ * a failure condition
+ */
+
+ if ( !(nt_devmode=print_job_devmode( snum, jobid )) )
+ devmode = construct_dev_mode(snum);
+ else {
+ if ((devmode = (DEVICEMODE *)malloc(sizeof(DEVICEMODE))) != NULL) {
+ ZERO_STRUCTP( devmode );
+ convert_nt_devicemode( devmode, nt_devmode );
+ }
}
-
+
fill_job_info_2(info_2, &(queue[i-1]), i, snum, ntprinter, devmode);
*needed += spoolss_size_job_info_2(info_2);
done:
/* Cleanup allocated memory */
- SAFE_FREE(queue);
free_job_info_2(info_2); /* Also frees devmode */
SAFE_FREE(info_2);
free_a_printer(&ntprinter, 2);
-
+
return ret;
}
NEW_BUFFER *buffer = NULL;
uint32 offered = q_u->offered;
uint32 *needed = &r_u->needed;
+ WERROR wstatus = WERR_OK;
int snum;
int count;
- print_queue_struct *queue=NULL;
+ print_queue_struct *queue = NULL;
print_status_struct prt_status;
/* that's an [in out] buffer */
DEBUG(5,("spoolss_getjob\n"));
- *needed=0;
+ *needed = 0;
if (!get_printer_snum(p, handle, &snum))
return WERR_BADFID;
count = print_queue_status(snum, &queue, &prt_status);
- DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
- count, prt_status.status, prt_status.message));
+ DEBUGADD(4,("count:[%d], prt_status:[%d], [%s]\n",
+ count, prt_status.status, prt_status.message));
+
+ switch ( level ) {
+ case 1:
+ wstatus = getjob_level_1(queue, count, snum, jobid,
+ buffer, offered, needed);
+ break;
+ case 2:
+ wstatus = getjob_level_2(queue, count, snum, jobid,
+ buffer, offered, needed);
+ break;
+ default:
+ wstatus = WERR_UNKNOWN_LEVEL;
+ break;
+ }
+
+ SAFE_FREE(queue);
+ return wstatus;
+}
+
+/********************************************************************
+ spoolss_getprinterdataex
+
+ From MSDN documentation of GetPrinterDataEx: pass request
+ to GetPrinterData if key is "PrinterDriverData".
+ ********************************************************************/
+
+WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
+{
+ POLICY_HND *handle = &q_u->handle;
+ uint32 in_size = q_u->size;
+ uint32 *type = &r_u->type;
+ uint32 *out_size = &r_u->size;
+ uint8 **data = &r_u->data;
+ uint32 *needed = &r_u->needed;
+ fstring keyname, valuename;
+
+ Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ int snum = 0;
+ WERROR status = WERR_OK;
+
+ DEBUG(4,("_spoolss_getprinterdataex\n"));
+
+ unistr2_to_ascii(keyname, &q_u->keyname, sizeof(keyname) - 1);
+ unistr2_to_ascii(valuename, &q_u->valuename, sizeof(valuename) - 1);
+
+ DEBUG(10, ("_spoolss_getprinterdataex: key => [%s], value => [%s]\n",
+ keyname, valuename));
+
+ /* in case of problem, return some default values */
+
+ *needed = 0;
+ *type = 0;
+ *out_size = in_size;
+
+ if (!Printer) {
+ DEBUG(2,("_spoolss_getprinterdataex: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+ status = WERR_BADFID;
+ goto done;
+ }
+
+ /* Is the handle to a printer or to the server? */
+
+ if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) {
+ DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
+ status = WERR_INVALID_PARAM;
+ goto done;
+ }
+
+ if ( !get_printer_snum(p,handle, &snum) )
+ return WERR_BADFID;
+
+ status = get_a_printer(&printer, 2, lp_servicename(snum));
+ if ( !W_ERROR_IS_OK(status) )
+ goto done;
+
+ /* check to see if the keyname is valid */
+ if ( !strlen(keyname) ) {
+ status = WERR_INVALID_PARAM;
+ goto done;
+ }
+
+ if ( lookup_printerkey( &printer->info_2->data, keyname ) == -1 ) {
+ DEBUG(4,("_spoolss_getprinterdataex: Invalid keyname [%s]\n", keyname ));
+ free_a_printer( &printer, 2 );
+ status = WERR_BADFILE;
+ goto done;
+ }
+
+ /* When given a new keyname, we should just create it */
+
+ status = get_printer_dataex( p->mem_ctx, printer, keyname, valuename, type, data, needed, in_size );
+
+ if (*needed > *out_size)
+ status = WERR_MORE_DATA;
+
+done:
+ if ( !W_ERROR_IS_OK(status) )
+ {
+ DEBUG(5, ("error: allocating %d\n", *out_size));
- switch (level) {
- case 1:
- return getjob_level_1(queue, count, snum, jobid, buffer, offered, needed);
- case 2:
- return getjob_level_2(queue, count, snum, jobid, buffer, offered, needed);
- default:
- SAFE_FREE(queue);
- return WERR_UNKNOWN_LEVEL;
+ /* reply this param doesn't exist */
+
+ if ( *out_size )
+ {
+ if( (*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL ) {
+ status = WERR_NOMEM;
+ goto done;
+ }
+ }
+ else {
+ *data = NULL;
}
+ }
+
+ if ( printer )
+ free_a_printer( &printer, 2 );
+
+ return status;
}
/********************************************************************
- * spoolss_getprinterdataex
+ * spoolss_setprinterdataex
********************************************************************/
-WERROR _spoolss_getprinterdataex(pipes_struct *p, SPOOL_Q_GETPRINTERDATAEX *q_u, SPOOL_R_GETPRINTERDATAEX *r_u)
+WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
{
- POLICY_HND *handle = &q_u->handle;
- uint32 in_size = q_u->size;
- uint32 *type = &r_u->type;
- uint32 *out_size = &r_u->size;
- uint8 **data = &r_u->data;
- uint32 *needed = &r_u->needed;
+ POLICY_HND *handle = &q_u->handle;
+ uint32 type = q_u->type;
+ uint8 *data = q_u->data;
+ uint32 real_len = q_u->real_len;
- fstring key, value;
- Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
- BOOL found = False;
-
- DEBUG(4,("_spoolss_getprinterdataex\n"));
-
- unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
- unistr2_to_ascii(value, &q_u->valuename, sizeof(value) - 1);
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ int snum = 0;
+ WERROR status = WERR_OK;
+ Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+ fstring valuename;
+ fstring keyname;
+ char *oid_string;
+
+ DEBUG(4,("_spoolss_setprinterdataex\n"));
- /* in case of problem, return some default values */
- *needed=0;
- *type=0;
- *out_size=0;
+ /* From MSDN documentation of SetPrinterDataEx: pass request to
+ SetPrinterData if key is "PrinterDriverData" */
-
if (!Printer) {
- if((*data=(uint8 *)talloc_zero(p->mem_ctx, 4*sizeof(uint8))) == NULL)
- return WERR_NOMEM;
- DEBUG(2,("_spoolss_getprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+ DEBUG(2,("_spoolss_setprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
return WERR_BADFID;
}
-
- /* Is the handle to a printer or to the server? */
+ if ( !get_printer_snum(p,handle, &snum) )
+ return WERR_BADFID;
+
+ /*
+ * Access check : NT returns "access denied" if you make a
+ * SetPrinterData call without the necessary privildge.
+ * we were originally returning OK if nothing changed
+ * which made Win2k issue **a lot** of SetPrinterData
+ * when connecting to a printer --jerry
+ */
- if (Printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER)
+ if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER)
{
- DEBUG(10,("_spoolss_getprinterdatex: Not implemented for server handles yet\n"));
- return WERR_INVALID_PARAM;
+ DEBUG(3, ("_spoolss_setprinterdataex: change denied by handle access permissions\n"));
+ return WERR_ACCESS_DENIED;
}
- else
- {
- /*
- * From MSDN documentation of GetPrinterDataEx: pass request
- * to GetPrinterData if key is "PrinterDriverData". This is
- * the only key we really support. Other keys to implement:
- * (a) DsDriver
- * (b) DsSpooler
- * (c) PnPData
- */
-
- if (strcmp(key, "PrinterDriverData") != 0)
- return WERR_BADFILE;
- DEBUG(10, ("_spoolss_getprinterdataex: pass me to getprinterdata\n"));
- found = getprinterdata_printer(p, p->mem_ctx, handle, value,
- type, data, needed, in_size);
-
+ status = get_a_printer(&printer, 2, lp_servicename(snum));
+ if (!W_ERROR_IS_OK(status))
+ return status;
+
+ unistr2_to_ascii( valuename, &q_u->value, sizeof(valuename) - 1);
+ unistr2_to_ascii( keyname, &q_u->key, sizeof(keyname) - 1);
+
+ /* check for OID in valuename */
+
+ if ( (oid_string = strchr( valuename, ',' )) != NULL )
+ {
+ *oid_string = '\0';
+ oid_string++;
}
-
- if (!found) {
- DEBUG(5, ("value not found, allocating %d\n", *out_size));
-
- /* reply this param doesn't exist */
- if (*out_size) {
- if((*data=(uint8 *)talloc_zero(p->mem_ctx, *out_size*sizeof(uint8))) == NULL)
- return WERR_NOMEM;
- } else {
- *data = NULL;
- }
- return WERR_INVALID_PARAM;
+ /* save the registry data */
+
+ status = set_printer_dataex( printer, keyname, valuename, type, data, real_len );
+
+ /* save the OID if one was specified and the previous set call succeeded */
+
+ if ( W_ERROR_IS_OK(status) && oid_string )
+ {
+
+ fstrcat( keyname, "\\" );
+ fstrcat( keyname, SPOOL_OID_KEY );
+
+ /*
+ * I'm not checking the status here on purpose. Don't know
+ * if this is right, but I'm returning the status from the
+ * previous set_printer_dataex() call. I have no idea if
+ * this is right. --jerry
+ */
+
+ set_printer_dataex( printer, keyname, valuename,
+ REG_SZ, (void*)oid_string, strlen(oid_string)+1 );
}
- if (*needed > *out_size)
- return WERR_MORE_DATA;
- else
- return WERR_OK;
+ free_a_printer(&printer, 2);
+
+ return status;
}
+
/********************************************************************
- * spoolss_setprinterdata
+ * spoolss_deleteprinterdataex
********************************************************************/
-WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, SPOOL_R_SETPRINTERDATAEX *r_u)
+WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u)
{
- SPOOL_Q_SETPRINTERDATA q_u_local;
- SPOOL_R_SETPRINTERDATA r_u_local;
- fstring key;
+ POLICY_HND *handle = &q_u->handle;
+ UNISTR2 *value = &q_u->valuename;
+ UNISTR2 *key = &q_u->keyname;
- DEBUG(4,("_spoolss_setprinterdataex\n"));
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ int snum=0;
+ WERROR status = WERR_OK;
+ Printer_entry *Printer=find_printer_index_by_hnd(p, handle);
+ pstring valuename, keyname;
+
+ DEBUG(5,("spoolss_deleteprinterdataex\n"));
+
+ if (!Printer) {
+ DEBUG(2,("_spoolss_deleteprinterdata: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+ return WERR_BADFID;
+ }
- /* From MSDN documentation of SetPrinterDataEx: pass request to
- SetPrinterData if key is "PrinterDriverData" */
+ if (!get_printer_snum(p, handle, &snum))
+ return WERR_BADFID;
+
+ if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+ DEBUG(3, ("_spoolss_deleteprinterdataex: printer properties change denied by handle\n"));
+ return WERR_ACCESS_DENIED;
+ }
- unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
+ status = get_a_printer(&printer, 2, lp_servicename(snum));
+ if (!W_ERROR_IS_OK(status))
+ return status;
- if (strcmp(key, "PrinterDriverData") != 0)
- return WERR_INVALID_PARAM;
-
- ZERO_STRUCT(q_u_local);
- ZERO_STRUCT(r_u_local);
-
- /* make a copy to call _spoolss_setprinterdata() */
-
- memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND));
- copy_unistr2(&q_u_local.value, &q_u->value);
- q_u_local.type = q_u->type;
- q_u_local.max_len = q_u->max_len;
- q_u_local.data = q_u->data;
- q_u_local.real_len = q_u->real_len;
- q_u_local.numeric_data = q_u->numeric_data;
-
- return _spoolss_setprinterdata(p, &q_u_local, &r_u_local);
+ unistr2_to_ascii( valuename, value, sizeof(valuename)-1 );
+ unistr2_to_ascii( keyname, key, sizeof(keyname)-1 );
+
+ status = delete_printer_dataex( printer, keyname, valuename );
+
+ free_a_printer(&printer, 2);
+
+ return status;
}
/********************************************************************
* spoolss_enumprinterkey
********************************************************************/
-/* constants for EnumPrinterKey() */
-#define ENUMERATED_KEY_SIZE 19
WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPOOL_R_ENUMPRINTERKEY *r_u)
{
- fstring key;
- uint16 enumkeys[ENUMERATED_KEY_SIZE+1];
- char* ptr = NULL;
- int i;
- char *PrinterKey = "PrinterDriverData";
-
+ fstring key;
+ fstring *keynames = NULL;
+ uint16 *enumkeys = NULL;
+ int num_keys;
+ int printerkey_len;
+ POLICY_HND *handle = &q_u->handle;
+ Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
+ NT_PRINTER_DATA *data;
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ int snum = 0;
+ WERROR status = WERR_BADFILE;
+
+
DEBUG(4,("_spoolss_enumprinterkey\n"));
- unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
+ if (!Printer) {
+ DEBUG(2,("_spoolss_enumprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+ return WERR_BADFID;
+ }
- /*
- * we only support enumating all keys (key == "")
- * Of course, the only key we support is the "PrinterDriverData"
- * key
- */
- if (strlen(key) == 0)
- {
- r_u->needed = ENUMERATED_KEY_SIZE *2;
- if (q_u->size < r_u->needed)
- return WERR_MORE_DATA;
-
- ptr = PrinterKey;
- for (i=0; i<ENUMERATED_KEY_SIZE-2; i++)
- {
- enumkeys[i] = (uint16)(*ptr);
- ptr++;
- }
+ if ( !get_printer_snum(p,handle, &snum) )
+ return WERR_BADFID;
- /* tag of with 2 '\0's */
- enumkeys[i++] = '\0';
- enumkeys[i] = '\0';
+ status = get_a_printer(&printer, 2, lp_servicename(snum));
+ if (!W_ERROR_IS_OK(status))
+ return status;
+
+ /* get the list of subkey names */
- if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, ENUMERATED_KEY_SIZE, enumkeys))
- return WERR_BADFILE;
+ unistr2_to_ascii( key, &q_u->key, sizeof(key)-1 );
+ data = &printer->info_2->data;
+
+ num_keys = get_printer_subkeys( data, key, &keynames );
+
+ if ( num_keys == -1 ) {
+ status = WERR_BADFILE;
+ goto done;
+ }
+
+ printerkey_len = init_unistr_array( &enumkeys, keynames, NULL );
+
+ r_u->needed = printerkey_len*2;
+
+ if ( q_u->size < r_u->needed ) {
+ status = WERR_MORE_DATA;
+ goto done;
+ }
+
+ if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, printerkey_len, enumkeys)) {
+ status = WERR_NOMEM;
+ goto done;
+ }
- return WERR_OK;
+ status = WERR_OK;
+
+ if ( q_u->size < r_u->needed )
+ status = WERR_MORE_DATA;
+
+done:
+ free_a_printer( &printer, 2 );
+ SAFE_FREE( keynames );
+
+ return status;
+}
+
+/********************************************************************
+ * spoolss_deleteprinterkey
+ ********************************************************************/
+
+WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u)
+{
+ POLICY_HND *handle = &q_u->handle;
+ Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle);
+ fstring key;
+ NT_PRINTER_INFO_LEVEL *printer = NULL;
+ int snum=0;
+ WERROR status;
+
+ DEBUG(5,("spoolss_deleteprinterkey\n"));
+
+ if (!Printer) {
+ DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(handle)));
+ return WERR_BADFID;
}
+
+ /* if keyname == NULL, return error */
- /* The "PrinterDriverData" key should have no subkeys */
- if (strcmp(key, PrinterKey) == 0)
- {
- r_u-> needed = 2;
- if (q_u->size < r_u->needed)
- return WERR_MORE_DATA;
- enumkeys[0] = 0x0;
- if (!make_spoolss_buffer5(p->mem_ctx, &r_u->keys, 1, enumkeys))
- return WERR_BADFILE;
-
- return WERR_OK;
+ if ( !q_u->keyname.buffer )
+ return WERR_INVALID_PARAM;
+
+ if (!get_printer_snum(p, handle, &snum))
+ return WERR_BADFID;
+
+ if (Printer->access_granted != PRINTER_ACCESS_ADMINISTER) {
+ DEBUG(3, ("_spoolss_deleteprinterkey: printer properties change denied by handle\n"));
+ return WERR_ACCESS_DENIED;
}
+
+ status = get_a_printer(&printer, 2, lp_servicename(snum));
+ if (!W_ERROR_IS_OK(status))
+ return status;
+ /* delete the key and all subneys */
+
+ unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1);
+
+ status = delete_all_printer_data( printer->info_2, key );
- /* The return value for an unknown key is documented in MSDN
- EnumPrinterKey description */
- return WERR_BADFILE;
+ if ( W_ERROR_IS_OK(status) )
+ status = mod_a_printer(*printer, 2);
+
+ free_a_printer( &printer, 2 );
+
+ return status;
}
+
/********************************************************************
* spoolss_enumprinterdataex
********************************************************************/
needed;
NT_PRINTER_INFO_LEVEL *printer = NULL;
PRINTER_ENUM_VALUES *enum_values = NULL;
- fstring key, value;
+ NT_PRINTER_DATA *p_data;
+ fstring key;
Printer_entry *Printer = find_printer_index_by_hnd(p, handle);
int snum;
- uint32 param_index,
- data_len,
- type;
WERROR result;
- uint8 *data=NULL;
+ int key_index;
+ int i;
+ REGISTRY_VALUE *val;
+ char *value_name;
+ int data_len;
DEBUG(4,("_spoolss_enumprinterdataex\n"));
return WERR_BADFID;
}
-
- /*
- * The only key we support is "PrinterDriverData". This should return
- > an array of all the key/value pairs returned by EnumPrinterDataSee
- * _spoolss_getprinterdataex() for details --jerry
- */
-
- unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
- if (strcmp(key, "PrinterDriverData") != 0)
- {
- DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
- return WERR_INVALID_PARAM;
- }
-
-
+ /* first get the printer off of disk */
+
if (!get_printer_snum(p,handle, &snum))
return WERR_BADFID;
result = get_a_printer(&printer, 2, lp_servicename(snum));
if (!W_ERROR_IS_OK(result))
return result;
-
- /*
- * loop through all params and build the array to pass
- * back to the client
- */
+ /* now look for a match on the key name */
+
+ p_data = &printer->info_2->data;
+
+ unistr2_to_ascii(key, &q_u->key, sizeof(key) - 1);
+ if ( (key_index = lookup_printerkey( p_data, key)) == -1 )
+ {
+ DEBUG(10,("_spoolss_enumprinterdataex: Unknown keyname [%s]\n", key));
+ result = WERR_INVALID_PARAM;
+ goto done;
+ }
+
result = WERR_OK;
- param_index = 0;
- needed = 0;
- num_entries = 0;
+ needed = 0;
- while (get_specific_param_by_index(*printer, 2, param_index, value, &data, &type, &data_len))
+ /* allocate the memory for the array of pointers -- if necessary */
+
+ num_entries = regval_ctr_numvals( &p_data->keys[key_index].values );
+ if ( num_entries )
{
- PRINTER_ENUM_VALUES *ptr;
- uint32 add_len = 0;
-
- DEBUG(10,("retrieved value number [%d] [%s]\n", num_entries, value));
-
- if ((ptr=talloc_realloc(p->mem_ctx, enum_values, (num_entries+1) * sizeof(PRINTER_ENUM_VALUES))) == NULL)
+ if ( (enum_values=talloc(p->mem_ctx, num_entries*sizeof(PRINTER_ENUM_VALUES))) == NULL )
{
- DEBUG(0,("talloc_realloc failed to allocate more memory!\n"));
+ DEBUG(0,("_spoolss_enumprinterdataex: talloc() failed to allocate memory for [%d] bytes!\n",
+ num_entries*sizeof(PRINTER_ENUM_VALUES)));
result = WERR_NOMEM;
goto done;
}
- enum_values = ptr;
+
+ memset( enum_values, 0x0, num_entries*sizeof(PRINTER_ENUM_VALUES) );
+ }
+
+ /*
+ * loop through all params and build the array to pass
+ * back to the client
+ */
+
+ for ( i=0; i<num_entries; i++ )
+ {
+ /* lookup the registry value */
+
+ val = regval_ctr_specific_value( &p_data->keys[key_index].values, i );
+ DEBUG(10,("retrieved value number [%d] [%s]\n", i, regval_name(val) ));
/* copy the data */
- init_unistr(&enum_values[num_entries].valuename, value);
- enum_values[num_entries].value_len = (strlen(value)+1) * 2;
- enum_values[num_entries].type = type;
- if (!(enum_values[num_entries].data=talloc_zero(p->mem_ctx, data_len+add_len))) {
- DEBUG(0,("talloc_realloc failed to allocate more memory for data!\n"));
- result = WERR_NOMEM;
- goto done;
+ value_name = regval_name( val );
+ init_unistr( &enum_values[i].valuename, value_name );
+ enum_values[i].value_len = (strlen(value_name)+1) * 2;
+ enum_values[i].type = regval_type( val );
+
+ data_len = regval_size( val );
+ if ( data_len ) {
+ if ( !(enum_values[i].data = talloc_memdup(p->mem_ctx, regval_data_p(val), data_len)) )
+ {
+ DEBUG(0,("talloc_memdup failed to allocate memory [data_len=%d] for data!\n",
+ data_len ));
+ result = WERR_NOMEM;
+ goto done;
+ }
}
- memcpy(enum_values[num_entries].data, data, data_len);
- enum_values[num_entries].data_len = data_len + add_len;
+ enum_values[i].data_len = data_len;
/* keep track of the size of the array in bytes */
- needed += spoolss_size_printer_enum_values(&enum_values[num_entries]);
-
- num_entries++;
- param_index++;
+ needed += spoolss_size_printer_enum_values(&enum_values[i]);
}
- r_u->needed = needed;
- r_u->returned = num_entries;
+ /* housekeeping information in the reply */
+
+ r_u->needed = needed;
+ r_u->returned = num_entries;
if (needed > in_size) {
result = WERR_MORE_DATA;
case 1:
result = getprintprocessordirectory_level_1
(&q_u->name, &q_u->environment, buffer, offered, needed);
+ break;
default:
result = WERR_UNKNOWN_LEVEL;
}
return result;
}
+
+#if 0
+
+WERROR _spoolss_replyopenprinter(pipes_struct *p, SPOOL_Q_REPLYOPENPRINTER *q_u,
+ SPOOL_R_REPLYOPENPRINTER *r_u)
+{
+ DEBUG(5,("_spoolss_replyopenprinter\n"));
+
+ DEBUG(10, ("replyopenprinter for localprinter %d\n", q_u->printer));
+
+ return WERR_OK;
+}
+
+WERROR _spoolss_replycloseprinter(pipes_struct *p, SPOOL_Q_REPLYCLOSEPRINTER *q_u,
+ SPOOL_R_REPLYCLOSEPRINTER *r_u)
+{
+ DEBUG(5,("_spoolss_replycloseprinter\n"));
+ return WERR_OK;
+}
+
+#endif