diff options
Diffstat (limited to 'source3/rpc_server/srv_spoolss_nt.c')
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 1330 |
1 files changed, 414 insertions, 916 deletions
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 68c792f8b0..322efa22b5 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -5,7 +5,7 @@ * 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-2002, + * Copyright (C) Gerald Carter 2000-2001, * Copyright (C) Tim Potter 2001-2002. * * This program is free software; you can redistribute it and/or modify @@ -28,10 +28,6 @@ #include "includes.h" -#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 #endif @@ -41,15 +37,6 @@ #define PRINTER_HANDLE_IS_PRINTER 0 #define PRINTER_HANDLE_IS_PRINTSERVER 1 -/* Table to map the driver version */ -/* to OS */ -char * drv_ver_to_os[] = { - "WIN9X", /* driver version/cversion 0 */ - "", /* unused ? */ - "WINNT", /* driver version/cversion 2 */ - "WIN2K", /* driver version/cversion 3 */ -}; - struct table_node { char *long_archi; char *short_archi; @@ -81,7 +68,6 @@ typedef struct _Printer{ SPOOL_NOTIFY_OPTION *option; POLICY_HND client_hnd; uint32 client_connected; - uint32 change; } notify; struct { fstring machine; @@ -192,10 +178,10 @@ static void srv_spoolss_replycloseprinter(POLICY_HND *handle) /* if it's the last connection, deconnect the IPC$ share */ if (smb_connections==1) { - cli_nt_session_close(&cli); - cli_ulogoff(&cli); - cli_shutdown(&cli); - message_deregister(MSG_PRINTER_NOTIFY2); + if(!spoolss_disconnect_from_client(&cli)) + return; + + message_deregister(MSG_PRINTER_NOTIFY); } smb_connections--; @@ -440,7 +426,7 @@ static BOOL set_printer_hnd_name(Printer_entry *Printer, char *handlename) * 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++) { @@ -549,417 +535,229 @@ static BOOL alloc_buffer_size(NEW_BUFFER *buffer, uint32 buffer_size) return True; } - /*************************************************************************** - check to see if the client motify handle is monitoring the notification - given by (notify_type, notify_field). + 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. **************************************************************************/ - -static BOOL is_monitoring_event_flags(uint32 flags, uint16 notify_type, - uint16 notify_field) +static BOOL valid_notify_options(Printer_entry *printer) { + if (printer->notify.option == NULL) + return False; + return True; } -static BOOL is_monitoring_event(Printer_entry *p, uint16 notify_type, - uint16 notify_field) +/*************************************************************************** + Simple check to see if the client motify handle is set to watch for events + represented by 'flags' + + FIXME!!!! only a stub right now --jerry + **************************************************************************/ + +static BOOL is_client_monitoring_event(Printer_entry *p, uint32 flags) { - SPOOL_NOTIFY_OPTION *option = p->notify.option; - uint32 i, j; - - 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; + return True; } -static void notify_string(struct spoolss_notify_msg *msg, - SPOOL_NOTIFY_INFO_DATA *data, - TALLOC_CTX *mem_ctx) +/*************************************************************************** + 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 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) { - UNISTR2 unistr; + WERROR result; + uint32 condition = 0x0; - /* 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; - } + if (info->flags & PRINTER_MESSAGE_DRIVER) + condition = PRINTER_CHANGE_SET_PRINTER_DRIVER; - memcpy(data->notify_data.data.string, unistr.buffer, msg->len * 2); + result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition, + printer->info_2->changeid); + + return result; } -static void notify_system_time(struct spoolss_notify_msg *msg, - SPOOL_NOTIFY_INFO_DATA *data, - TALLOC_CTX *mem_ctx) +/*********************************************************************** + Wrapper around the decision of which RPC use to in the change + notification + **********************************************************************/ + +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) { - 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; - } + WERROR result; + + 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; - if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) { - DEBUG(5, ("notify_system_time: prs_init() failed\n")); - return; + result = cli_spoolss_reply_rrpcn(send_cli, send_cli->mem_ctx, &Printer->notify.client_hnd, + msg, info); } - - if (!make_systemtime(&systime, localtime((time_t *)msg->notify.data))) { - DEBUG(5, ("notify_system_time: unable to make systemtime\n")); - return; + 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); } - - 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); + + return result; } -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", NULL }, - /* 0x01 */ { "PRINTER_NOTIFY_PRINTER_NAME", NULL }, - /* 0x02 */ { "PRINTER_NOTIFY_SHARE_NAME", NULL }, - /* 0x03 */ { "PRINTER_NOTIFY_PORT_NAME", NULL }, - /* 0x04 */ { "PRINTER_NOTIFY_DRIVER_NAME", NULL }, - /* 0x05 */ { "PRINTER_NOTIFY_COMMENT", NULL }, - /* 0x06 */ { "PRINTER_NOTIFY_LOCATION", NULL }, - /* 0x07 */ { "PRINTER_NOTIFY_DEVMODE", NULL }, - /* 0x08 */ { "PRINTER_NOTIFY_SEPFILE", NULL }, - /* 0x09 */ { "PRINTER_NOTIFY_PRINT_PROCESSOR", NULL }, - /* 0x0a */ { "PRINTER_NOTIFY_PARAMETERS", NULL }, - /* 0x0b */ { "PRINTER_NOTIFY_DATATYPE", NULL }, - /* 0x0c */ { "PRINTER_NOTIFY_SECURITY_DESCRIPTOR", NULL }, - /* 0x0d */ { "PRINTER_NOTIFY_ATTRIBUTES", NULL }, - /* 0x0e */ { "PRINTER_NOTIFY_PRIORITY", NULL }, - /* 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 }, -}; /*********************************************************************** Send a change notication message on all handles which have a call back registered **********************************************************************/ -static void process_notify2_message(struct spoolss_notify_msg *msg, - TALLOC_CTX *mem_ctx) +static void send_spoolss_event_notification(PRINTER_MESSAGE_INFO *msg) { - Printer_entry *p; - - for (p = printers_list; p; p = p->next) { - SPOOL_NOTIFY_INFO_DATA *data; - uint32 data_len = 1; - uint32 id; - - /* Is there notification on this handle? */ - - if (!p->notify.client_connected) - continue; - - /* For this printer? Print servers always receive - notifications. */ - - if (p->printer_type == PRINTER_HANDLE_IS_PRINTER && - !strequal(msg->printer, p->dev.handlename)) - continue; - - /* Are we monitoring this event? */ - - if (!is_monitoring_event(p, msg->type, msg->field)) - continue; - - /* OK - send the event to the client */ - - data = talloc(mem_ctx, sizeof(SPOOL_NOTIFY_INFO_DATA)); - - ZERO_STRUCTP(data); + Printer_entry *find_printer; + WERROR result; + NT_PRINTER_INFO_LEVEL *printer = NULL; - /* Convert unix jobid to smb jobid */ + if (!msg) { + DEBUG(0,("send_spoolss_event_notification: NULL msg pointer!\n")); + return; + } - id = msg->id; + for(find_printer = printers_list; find_printer; find_printer = find_printer->next) { - if (msg->flags & SPOOLSS_NOTIFY_MSG_UNIX_JOBID) { + /* + * 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. + * + * 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 + */ - id = sysjob_to_jobid(msg->id); + if (find_printer->notify.client_connected==True) { + + /* does the client care about what changed? */ - if (id == -1) { - DEBUG(3, ("no such unix jobid %d\n", msg->id)); - goto done; + 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; } - } - construct_info_data(data, msg->type, msg->field, id); - - switch(msg->type) { - case PRINTER_NOTIFY_TYPE: - if (printer_notify_table[msg->field].fn) - printer_notify_table[msg->field].fn( - msg, data, mem_ctx); - else - goto done; - break; - case JOB_NOTIFY_TYPE: - if (job_notify_table[msg->field].fn) - job_notify_table[msg->field].fn( - msg, data, mem_ctx); + if (find_printer->printer_type == PRINTER_HANDLE_IS_PRINTSERVER) + DEBUG(10,("send_spoolss_event_notification: printserver [%s]\n", find_printer->dev.printerservername )); else - goto done; - break; - default: - DEBUG(5, ("Unknown notification type %d\n", - msg->type)); - goto done; - } - - if (!p->notify.flags) - cli_spoolss_rrpcn( - &cli, mem_ctx, &p->notify.client_hnd, - data_len, data, p->notify.change, 0); - else { - NT_PRINTER_INFO_LEVEL *printer = NULL; + DEBUG(10,("send_spoolss_event_notification: printer [%s]\n", find_printer->dev.handlename)); - get_a_printer(&printer, 2, msg->printer); + /* + * if handle is a printer, only send if the printer_name matches. + * ...else if handle is a printerserver, send to all + */ - if (!printer) { - DEBUG(5, ("unable to load info2 for %s\n", - msg->printer)); - goto done; + if (*msg->printer_name && (find_printer->printer_type==PRINTER_HANDLE_IS_PRINTER) + && !strequal(msg->printer_name, find_printer->dev.handlename)) + { + DEBUG(10,("send_spoolss_event_notification: ignoring message sent to %s [%s]\n", + msg->printer_name, find_printer->dev.handlename )); + continue; } - /* XXX: This needs to be updated for - PRINTER_CHANGE_SET_PRINTER_DRIVER. */ - cli_spoolss_routerreplyprinter( - &cli, mem_ctx, &p->notify.client_hnd, - 0, printer->info_2->changeid); + /* 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)) + { + + 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; + } - free_a_printer(&printer, 2); + /* issue the client call */ + + 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))); } } -done: - return; } -/* Receive a notify2 message */ + 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 receive_notify2_message(int msg_type, pid_t src, void *buf, - size_t len) +static void srv_spoolss_receive_message(int msg_type, pid_t src, void *buf, size_t len) { - struct spoolss_notify_msg msg; - int offset = 0; - TALLOC_CTX *mem_ctx = talloc_init(); - - /* Unpack message */ - - ZERO_STRUCT(msg); - - offset += tdb_unpack((char *)buf + offset, len - offset, "f", - msg.printer); + PRINTER_MESSAGE_INFO msg; - offset += tdb_unpack((char *)buf + offset, len - offset, "ddddd", - &msg.type, &msg.field, &msg.id, &msg.len, &msg.flags); - - if (msg.len == 0) - tdb_unpack((char *)buf + offset, len - offset, "dd", - &msg.notify.value[0], &msg.notify.value[1]); - else - tdb_unpack((char *)buf + offset, len - offset, "B", - &msg.len, &msg.notify.data); - - DEBUG(3, ("got NOTIFY2 message, type %d, field 0x%02x, flags 0x%04x\n", - msg.type, msg.field, msg.flags)); - - if (msg.len == 0) - DEBUG(3, ("value1 = %d, value2 = %d\n", msg.notify.value[0], - msg.notify.value[1])); - else - dump_data(3, msg.notify.data, msg.len); - - /* Process message */ - - process_notify2_message(&msg, mem_ctx); - - /* Free message */ + if (len < sizeof(msg)) { + DEBUG(2,("srv_spoolss_receive_message: got incorrect message size (%u)!\n", (unsigned int)len)); + return; + } - if (msg.len > 0) - free(msg.notify.data); + 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 )); - talloc_destroy(mem_ctx); + /* Iterate the printer list */ + + send_spoolss_event_notification(&msg); + } /*************************************************************************** - 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 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) + Send a notify event. +****************************************************************************/ + +static BOOL srv_spoolss_sendnotify(char* printer_name, uint32 high, uint32 low, uint32 flags) { - WERROR result; - uint32 condition = 0x0; + char msg[sizeof(PRINTER_MESSAGE_INFO)]; + PRINTER_MESSAGE_INFO info; - if (info->flags & PRINTER_MESSAGE_DRIVER) - condition = PRINTER_CHANGE_SET_PRINTER_DRIVER; - - result = cli_spoolss_routerreplyprinter(reply_cli, mem_ctx, pol, condition, - printer->info_2->changeid); - - return result; -} + ZERO_STRUCT(info); -/******************************************************************** - 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); + info.low = low; + info.high = high; + info.flags = flags; + fstrcpy(info.printer_name, printer_name); - if (!len) - return False; + memcpy(msg, &info, sizeof(PRINTER_MESSAGE_INFO)); - DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n", - drivername)); + 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_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False); + message_send_all(conn_tdb_ctx(), MSG_PRINTER_NOTIFY, msg, sizeof(PRINTER_MESSAGE_INFO), + False, NULL); return True; -} - -/********************************************************************** - callback to receive a MSG_PRINTER_DRVUPGRADE message and interate - 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)); - - /* all we care about currently is the change_id */ - - result = mod_a_printer(*printer, 2); - if (!W_ERROR_IS_OK(result)) { - DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n", - dos_errstr(result))); - } - } - - free_a_printer(&printer, 2); - } - } - - /* all done */ -} +} /******************************************************************** Copy routines used by convert_to_openprinterex() @@ -1126,6 +924,16 @@ Can't find printer handle we created for printer %s\n", name )); return WERR_INVALID_PRINTER_NAME; } +/* + if (printer_default->datatype_ptr != NULL) + { + unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1); + set_printer_hnd_datatype(handle, datatype); + } + else + set_printer_hnd_datatype(handle, ""); +*/ + /* First case: the user is opening the print server: @@ -1189,7 +997,7 @@ Can't find printer handle we created for printer %s\n", name )); user_in_list(uidtoname(user.uid), lp_printer_admin(snum))) return WERR_OK; - + close_printer_handle(p, handle); return WERR_ACCESS_DENIED; } @@ -1223,9 +1031,7 @@ Can't find printer handle we created for printer %s\n", name )); printer_default->access_required = PRINTER_ACCESS_USE; } - /* check smb.conf parameters and the the sec_desc */ - - if (!user_ok(uidtoname(user.uid), snum) || !print_access_check(&user, snum, printer_default->access_required)) { + if (!print_access_check(&user, snum, printer_default->access_required)) { DEBUG(3, ("access DENIED for printer open\n")); close_printer_handle(p, handle); return WERR_ACCESS_DENIED; @@ -1502,6 +1308,10 @@ WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL update_c_setprinter(False); + if (W_ERROR_IS_OK(result)) { + srv_spoolss_sendnotify(Printer->dev.handlename, 0, PRINTER_CHANGE_DELETE_PRINTER, 0x0); + } + return result; } @@ -1534,17 +1344,26 @@ static int get_version_id (char * arch) /******************************************************************** * _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; int version; - struct current_user user; - - 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 ); @@ -1554,89 +1373,21 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER /* this is what NT returns */ return WERR_INVALID_ENVIRONMENT; } - - /* if they said "Windows NT x86", then try for version 2 & 3 */ - - if ( version == 2 ) - version = DRIVER_ANY_VERSION; ZERO_STRUCT(info); - - if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) + if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) { return WERR_UNKNOWN_PRINTER_DRIVER; - - if (printer_driver_in_use(info.info_3)) - return WERR_PRINTER_DRIVER_IN_USE; - - return delete_printer_driver(info.info_3, &user, DRIVER_ANY_VERSION, False); -} - -/******************************************************************** - * spoolss_deleteprinterdriverex - ********************************************************************/ - -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; - int version; - uint32 flags = q_u->delete_flags; - BOOL delete_files; - struct current_user user; - - 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; - else if ( version == 2 ) - /* if they said "Windows NT x86", then try for version 2 & 3 */ - version = DRIVER_ANY_VERSION; - - ZERO_STRUCT(info); - - if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) - return WERR_UNKNOWN_PRINTER_DRIVER; - - if ( printer_driver_in_use(info.info_3) ) - return WERR_PRINTER_DRIVER_IN_USE; - - /* - * 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); - - if ( delete_files ) + + if (printer_driver_in_use(arch, driver)) { - /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */ - - if ( printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) - /* no idea of the correct error here */ - return WERR_ACCESS_DENIED; + return WERR_PRINTER_DRIVER_IN_USE; } - return delete_printer_driver(info.info_3, &user, version, delete_files); + return delete_printer_driver(info.info_3); } - /******************************************************************** GetPrinterData on a printer server Handle. ********************************************************************/ @@ -1687,11 +1438,7 @@ static BOOL getprinterdata_printer_server(TALLOC_CTX *ctx, fstring value, uint32 *type = 0x4; if((*data = (uint8 *)talloc(ctx, 4*sizeof(uint8) )) == NULL) return False; -#ifndef EMULATE_WIN2K_HACK /* JERRY */ SIVAL(*data, 0, 2); -#else - SIVAL(*data, 0, 3); -#endif *needed = 0x4; return True; } @@ -1859,96 +1606,6 @@ WERROR _spoolss_getprinterdata(pipes_struct *p, SPOOL_Q_GETPRINTERDATA *q_u, SPO return WERR_OK; } -/********************************************************* - Connect to the client machine. -**********************************************************/ - -static BOOL spoolss_connect_to_client(struct cli_state *the_cli, 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(!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)); - 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, PIPE_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. ****************************************************************************/ @@ -1969,14 +1626,15 @@ static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uin if(!spoolss_connect_to_client(&cli, unix_printer)) return False; - message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message); + message_register(MSG_PRINTER_NOTIFY, srv_spoolss_receive_message); + } smb_connections++; result = cli_spoolss_reply_open_printer(&cli, 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))); @@ -1988,8 +1646,9 @@ static BOOL srv_spoolss_replyopenprinter(char *printer, uint32 localprinter, uin * _spoolss_rffpcnex * ReplyFindFirstPrinterChangeNotifyEx * - * before replying OK: status=0 a rpc call is made to the workstation - * asking ReplyOpenPrinter + * jfmxxxx: before replying OK: status=0 + * should do a rpc call to the workstation asking ReplyOpenPrinter + * have to code it, later. * * in fact ReplyOpenPrinter is the changenotify equivalent on the spoolss pipe * called from api_spoolss_rffpcnex @@ -2022,17 +1681,15 @@ WERROR _spoolss_rffpcnex(pipes_struct *p, SPOOL_Q_RFFPCNEX *q_u, SPOOL_R_RFFPCNE Printer->notify.option=dup_spool_notify_option(option); - unistr2_to_ascii(Printer->notify.localmachine, localmachine, - sizeof(Printer->notify.localmachine)-1); - - /* Connect to the client machine and send a ReplyOpenPrinter */ + unistr2_to_ascii(Printer->notify.localmachine, localmachine, sizeof(Printer->notify.localmachine)-1); - if(!srv_spoolss_replyopenprinter(Printer->notify.localmachine, + /* connect to the client machine and send a ReplyOpenPrinter */ + if(srv_spoolss_replyopenprinter(Printer->notify.localmachine, Printer->notify.printerlocal, 1, &Printer->notify.client_hnd)) - return WERR_SERVER_UNAVAILABLE; - - Printer->notify.client_connected=True; + { + Printer->notify.client_connected=True; + } return WERR_OK; } @@ -2054,7 +1711,7 @@ void spoolss_notify_server_name(int snum, len = rpcstr_push(temp, temp_name, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2089,7 +1746,7 @@ void spoolss_notify_printer_name(int snum, len = rpcstr_push(temp, p, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2115,7 +1772,7 @@ void spoolss_notify_share_name(int snum, len = rpcstr_push(temp, lp_servicename(snum), sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2143,7 +1800,7 @@ void spoolss_notify_port_name(int snum, len = rpcstr_push(temp, printer->info_2->portname, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2169,8 +1826,7 @@ void spoolss_notify_driver_name(int snum, uint32 len; len = rpcstr_push(temp, printer->info_2->drivername, sizeof(temp)-2, STR_TERMINATE); - - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2199,7 +1855,7 @@ void spoolss_notify_comment(int snum, else len = rpcstr_push(temp, printer->info_2->comment, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2226,7 +1882,7 @@ void spoolss_notify_location(int snum, len = rpcstr_push(temp, printer->info_2->location,sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2265,7 +1921,7 @@ void spoolss_notify_sepfile(int snum, len = rpcstr_push(temp, printer->info_2->sepfile, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2292,7 +1948,7 @@ void spoolss_notify_print_processor(int snum, len = rpcstr_push(temp, printer->info_2->printprocessor, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2319,7 +1975,7 @@ void spoolss_notify_parameters(int snum, len = rpcstr_push(temp, printer->info_2->parameters, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2346,7 +2002,7 @@ void spoolss_notify_datatype(int snum, len = rpcstr_push(temp, printer->info_2->datatype, sizeof(pstring)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2506,7 +2162,7 @@ static void spoolss_notify_username(int snum, len = rpcstr_push(temp, queue->fs_user, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2546,7 +2202,7 @@ static void spoolss_notify_job_name(int snum, len = rpcstr_push(temp, queue->fs_file, sizeof(temp)-2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2596,7 +2252,7 @@ static void spoolss_notify_job_status_string(int snum, len = rpcstr_push(temp, p, sizeof(temp) - 2, STR_TERMINATE); - data->notify_data.data.length = len; + data->notify_data.data.length = len / 2 - 1; data->notify_data.data.string = (uint16 *)talloc(mem_ctx, len); if (!data->notify_data.data.string) { @@ -2720,6 +2376,8 @@ static void spoolss_notify_submitted_time(int snum, SSVAL(p, 14, st.milliseconds); } +#define END 65535 + struct s_notify_info_data_table { uint16 type; @@ -2731,61 +2389,59 @@ struct s_notify_info_data_table NT_PRINTER_INFO_LEVEL *printer, TALLOC_CTX *mem_ctx); }; -/* A table describing the various print notification constants and - whether the notification data is a pointer to a variable sized - buffer, a one value uint32 or a two value uint32. */ - struct s_notify_info_data_table notify_info_data_table[] = { -{ 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_POINTER, 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 }, +{ 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 } }; /******************************************************************* @@ -2796,46 +2452,43 @@ static uint32 size_of_notify_info_data(uint16 type, uint16 field) { int i=0; - 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) { - 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; - } + while (notify_info_data_table[i].type != END) + { + if ( (notify_info_data_table[i].type == type ) && + (notify_info_data_table[i].field == field ) ) + { + return (notify_info_data_table[i].size); } + i++; } - - DEBUG(5, ("invalid notify data type %d/%d\n", type, field)); - - return 0; + return (65535); } /******************************************************************* Return the type of notify_info_data. ********************************************************************/ -static int type_of_notify_info_data(uint16 type, uint16 field) +static BOOL type_of_notify_info_data(uint16 type, uint16 field) { int i=0; - 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; + 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++; } - - return False; + return (False); } /**************************************************************************** @@ -2843,18 +2496,21 @@ static int type_of_notify_info_data(uint16 type, uint16 field) static int search_notify(uint16 type, uint16 field, int *value) { - int i; + int j; + BOOL found; - 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; - } + 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; } - - return False; + *value=--j; + + if ( found && (notify_info_data_table[j].fn != NULL) ) + return True; + else + return False; } /**************************************************************************** @@ -2865,12 +2521,7 @@ void construct_info_data(SPOOL_NOTIFY_INFO_DATA *info_data, uint16 type, uint16 info_data->type = type; info_data->field = field; info_data->reserved = 0; - - if (type == JOB_NOTIFY_TYPE) - info_data->id = id; - else - info_data->id = 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); } @@ -2919,7 +2570,7 @@ static BOOL construct_notify_printer_info(SPOOL_NOTIFY_INFO *info, int 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 )); @@ -3161,6 +2812,7 @@ static WERROR printer_notify_info(pipes_struct *p, POLICY_HND *hnd, SPOOL_NOTIFY 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; @@ -3178,19 +2830,17 @@ WERROR _spoolss_rfnpcnex( pipes_struct *p, SPOOL_Q_RFNPCNEX *q_u, SPOOL_R_RFNPCN DEBUG(4,("Printer type %x\n",Printer->printer_type)); - /* - * We are now using the change value, and + /* 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 * 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) - Printer->notify.change = q_u->change; - /* just ignore the SPOOL_NOTIFY_OPTION */ switch (Printer->printer_type) { @@ -3282,7 +2932,7 @@ static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum) printer->global_counter = global_counter; printer->total_pages = 0; -#ifndef EMULATE_WIN2K_HACK /* JERRY */ +#if 0 /* JERRY */ printer->major_version = 0x0004; /* NT 4 */ printer->build_version = 0x0565; /* build 1381 */ #else @@ -3321,6 +2971,7 @@ static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum) * 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; @@ -3395,10 +3046,8 @@ static DEVICEMODE *construct_dev_mode(int snum) if (printer->info_2->devmode) ntdevmode = dup_nt_devicemode(printer->info_2->devmode); - if (ntdevmode == NULL) { - DEBUG(5, ("BONG! There was no device mode!\n")); + if (ntdevmode == NULL) goto fail; - } DEBUGADD(8,("loading DEVICEMODE\n")); @@ -3759,26 +3408,10 @@ static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer, enum_all_printers_info_1_network. *********************************************************************/ -static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) { - char *s = name; - DEBUG(4,("enum_all_printers_info_1_network\n")); - /* If we respond to a enum_printers level 1 on our name with flags - set to PRINTER_ENUM_REMOTE with a list of printers then these - printers incorrectly appear in the APW browse list. - Specifically the printers for the server appear at the workgroup - level where all the other servers in the domain are - listed. Windows responds to this call with a - WERR_CAN_NOT_COMPLETE so we should do the same. */ - - if (name[0] == '\\' && name[1] == '\\') - s = name + 2; - - if (is_myname_or_ipaddr(s)) - return WERR_CAN_NOT_COMPLETE; - return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned); } @@ -3816,9 +3449,9 @@ static WERROR enum_all_printers_info_2(NEW_BUFFER *buffer, uint32 offered, uint3 } /* 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); @@ -3865,7 +3498,7 @@ static WERROR enumprinters_level1( uint32 flags, fstring name, return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned); if (flags & PRINTER_ENUM_NETWORK) - return enum_all_printers_info_1_network(name, buffer, offered, needed, returned); + return enum_all_printers_info_1_network(buffer, offered, needed, returned); return WERR_OK; /* NT4sp5 does that */ } @@ -4048,7 +3681,7 @@ static WERROR getprinter_level_2(int snum, NEW_BUFFER *buffer, uint32 offered, u /* 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; @@ -5095,7 +4728,6 @@ static BOOL check_printer_ok(NT_PRINTER_INFO_LEVEL_2 *info, int snum) 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; @@ -5110,13 +4742,13 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer) get_called_name()); /* change \ to \\ for the shell */ all_string_sub(driverlocation,"\\","\\\\",sizeof(pstring)); - 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); + /* Convert script args to unix-codepage */ DEBUG(10,("Running [%s]\n", command)); ret = smbrun(command, &fd); DEBUGADD(10,("returned [%d]\n", ret)); @@ -5407,10 +5039,13 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, 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) { @@ -5524,11 +5159,8 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, * 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)); - } - notify_printer_driver(snum, printer->info_2->drivername); + set_driver_init(printer, 2); + msg.flags |= PRINTER_MESSAGE_DRIVER; } } @@ -5539,18 +5171,28 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, all the possible changes */ if (!strequal(printer->info_2->comment, old_printer->info_2->comment)) - notify_printer_comment(snum, printer->info_2->comment); + msg.flags |= PRINTER_MESSAGE_COMMENT; if (!strequal(printer->info_2->sharename, old_printer->info_2->sharename)) - notify_printer_sharename(snum, printer->info_2->sharename); + msg.flags |= PRINTER_MESSAGE_SHARENAME; if (!strequal(printer->info_2->portname, old_printer->info_2->portname)) - notify_printer_port(snum, printer->info_2->portname); + msg.flags |= PRINTER_MESSAGE_PORT; if (!strequal(printer->info_2->location, old_printer->info_2->location)) - notify_printer_location(snum, printer->info_2->location); + msg.flags |= PRINTER_MESSAGE_LOCATION; -done: + ZERO_STRUCT(msg); + + 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: free_a_printer(&printer, 2); free_a_printer(&old_printer, 2); @@ -5668,7 +5310,7 @@ static void fill_job_info_1(JOB_INFO_1 *job_info, print_queue_struct *queue, 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; @@ -5785,7 +5427,7 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum, *returned = 0; goto done; } - + if (!(devmode = construct_dev_mode(snum))) { *returned = 0; result = WERR_NOMEM; @@ -5828,7 +5470,6 @@ static WERROR enumjobs_level2(print_queue_struct *queue, int snum, SAFE_FREE(info); return result; - } /**************************************************************************** @@ -5897,6 +5538,8 @@ WERROR _spoolss_setjob(pipes_struct *p, SPOOL_Q_SETJOB *q_u, SPOOL_R_SETJOB *r_u { 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; @@ -5954,7 +5597,9 @@ static WERROR enumprinterdrivers_level1(fstring servername, fstring architecture *returned=0; - for (version=0; version<DRIVER_MAX_VERSION; version++) { +#define MAX_VERSION 4 + + for (version=0; version<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)); @@ -6033,7 +5678,9 @@ static WERROR enumprinterdrivers_level2(fstring servername, fstring architecture *returned=0; - for (version=0; version<DRIVER_MAX_VERSION; version++) { +#define MAX_VERSION 4 + + for (version=0; version<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)); @@ -6113,7 +5760,9 @@ static WERROR enumprinterdrivers_level3(fstring servername, fstring architecture *returned=0; - for (version=0; version<DRIVER_MAX_VERSION; version++) { +#define MAX_VERSION 4 + + for (version=0; version<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)); @@ -6766,6 +6415,9 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_ } 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; @@ -6810,12 +6462,10 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, WERROR err = WERR_OK; NT_PRINTER_DRIVER_INFO_LEVEL driver; struct current_user user; - fstring driver_name; - uint32 version; - + ZERO_STRUCT(driver); - get_current_user(&user, p); + get_current_user(&user, p); if (!convert_printer_driver_info(info, &driver, level)) { err = WERR_NOMEM; @@ -6839,131 +6489,11 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u, goto done; } - /* 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; - } - /* 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 - */ - - if (!srv_spoolss_drv_upgrade_printer(driver_name)) { - DEBUG(0,("_spoolss_addprinterdriver: Failed to send message about upgrading driver [%s]!\n", - driver_name)); - } - - /* - * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp), - * decide if the driver init data should be deleted. The rules are: - * 1) never delete init data if it is a 9x driver, they don't use it anyway - * 2) delete init data only if there is no 2k/Xp driver - * 3) always delete init data - * The generalized rule is always use init data from the highest order driver. - * It is necessary to follow the driver install by an initialization step to - * finish off this process. - */ - if (level == 3) - version = driver.info_3->cversion; - else if (level == 6) - version = driver.info_6->version; - else - version = -1; - switch (version) { - /* - * 9x printer driver - never delete init data - */ - case 0: - DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n", - driver_name)); - break; - - /* - * Nt or 2k (compatiblity mode) printer driver - only delete init data if - * there is no 2k/Xp driver init data for this driver name. - */ - case 2: - { - NT_PRINTER_DRIVER_INFO_LEVEL driver1; - - if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) { - /* - * No 2k/Xp driver found, delete init data (if any) for the new Nt driver. - */ - if (!del_driver_init(driver_name)) - DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name)); - } else { - /* - * a 2k/Xp driver was found, don't delete init data because Nt driver will use it. - */ - free_a_printer_driver(driver1,3); - DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n", - driver_name)); - } - } - break; - - /* - * 2k or Xp printer driver - always delete init data - */ - case 3: - if (!del_driver_init(driver_name)) - DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name)); - break; - - 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; - - /* just pass the information off to _spoolss_addprinterdriver() */ - ZERO_STRUCT(q_u_local); - ZERO_STRUCT(r_u_local); - - 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 ); -} - /**************************************************************************** ****************************************************************************/ @@ -7102,6 +6632,23 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S if ( (in_value_len==0) && (in_data_len==0) ) { DEBUGADD(6,("Activating NT mega-hack to find sizes\n")); +#if 0 + /* + * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS + * if this parameter size doesn't exist. + * Ok - my opinion here is that the client is not asking for the greatest + * possible size of all the parameters, but is asking specifically for the size needed + * for this specific parameter. In that case we can remove the loop below and + * simplify this lookup code considerably. JF - comments welcome. JRA. + */ + + if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) { + SAFE_FREE(data); + free_a_printer(&printer, 2); + return WERR_NO_MORE_ITEMS; + } +#endif + SAFE_FREE(data); param_index=0; @@ -7145,7 +6692,7 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S if((*out_value=(uint16 *)talloc_zero(p->mem_ctx, in_value_len*sizeof(uint8))) == NULL) return WERR_NOMEM; - *out_value_len = (uint32)rpcstr_push((char *)*out_value, "", in_value_len, 0); + *out_value_len = rpcstr_push((char *)*out_value, "", in_value_len, 0); /* the data is counted in bytes */ *out_max_data_len = in_data_len; @@ -7173,7 +6720,7 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S return WERR_NOMEM; } - *out_value_len = (uint32)rpcstr_push((char *)*out_value,value, in_value_len, 0); + *out_value_len = rpcstr_push((char *)*out_value,value, in_value_len, 0); *out_type=type; @@ -7200,8 +6747,10 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP 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. */ NT_PRINTER_INFO_LEVEL *printer = NULL; NT_PRINTER_PARAM *param = NULL, old_param; @@ -7473,6 +7022,8 @@ done: 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; @@ -7563,10 +7114,12 @@ static WERROR enumprintprocessors_level_1(NEW_BUFFER *buffer, uint32 offered, ui 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 */ @@ -7630,6 +7183,8 @@ static WERROR enumprintprocdatatypes_level_1(NEW_BUFFER *buffer, uint32 offered, 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; @@ -7724,10 +7279,11 @@ static WERROR enumprintmonitors_level_2(NEW_BUFFER *buffer, uint32 offered, uint 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 */ @@ -7871,7 +7427,7 @@ static WERROR getjob_level_2(print_queue_struct *queue, int count, int snum, uin free_job_info_2(info_2); /* Also frees devmode */ SAFE_FREE(info_2); free_a_printer(&ntprinter, 2); - + return ret; } @@ -8038,34 +7594,6 @@ WERROR _spoolss_setprinterdataex(pipes_struct *p, SPOOL_Q_SETPRINTERDATAEX *q_u, return _spoolss_setprinterdata(p, &q_u_local, &r_u_local); } - -/******************************************************************** - * spoolss_deleteprinterdataex - ********************************************************************/ - -WERROR _spoolss_deleteprinterdataex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDATAEX *q_u, SPOOL_R_DELETEPRINTERDATAEX *r_u) -{ - SPOOL_Q_DELETEPRINTERDATA q_u_local; - SPOOL_R_DELETEPRINTERDATA r_u_local; - fstring key; - - /* From MSDN documentation of SetPrinterDataEx: pass request to - SetPrinterData if key is "PrinterDriverData" */ - - unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1); - - if (strcmp(key, "PrinterDriverData") != 0) - return WERR_INVALID_PARAM; - - memcpy(&q_u_local.handle, &q_u->handle, sizeof(POLICY_HND)); - copy_unistr2(&q_u_local.valuename, &q_u->valuename); - - return _spoolss_deleteprinterdata( p, &q_u_local, &r_u_local ); -} - - - - /******************************************************************** * spoolss_enumprinterkey ********************************************************************/ @@ -8133,34 +7661,6 @@ WERROR _spoolss_enumprinterkey(pipes_struct *p, SPOOL_Q_ENUMPRINTERKEY *q_u, SPO } /******************************************************************** - * spoolss_deleteprinterkey - ********************************************************************/ - -WERROR _spoolss_deleteprinterkey(pipes_struct *p, SPOOL_Q_DELETEPRINTERKEY *q_u, SPOOL_R_DELETEPRINTERKEY *r_u) -{ - Printer_entry *Printer = find_printer_index_by_hnd(p, &q_u->handle); - fstring key; - - if (!Printer) { - DEBUG(2,("_spoolss_deleteprinterkey: Invalid handle (%s:%u:%u).\n", OUR_HANDLE(&q_u->handle))); - return WERR_BADFID; - } - - unistr2_to_ascii(key, &q_u->keyname, sizeof(key) - 1); - - if (strcmp(key, "PrinterDriverData") != 0) - return WERR_INVALID_PARAM; - - /* - * this is what 2k returns when you try to delete the "PrinterDriverData" - * key - */ - - return WERR_ACCESS_DENIED; -} - - -/******************************************************************** * spoolss_enumprinterdataex ********************************************************************/ @@ -8301,7 +7801,7 @@ static WERROR getprintprocessordirectory_level_1(UNISTR2 *name, unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1); - if (get_short_archi(short_archi, long_archi)==False) + if (get_short_archi(short_archi, long_archi)==FALSE) return WERR_INVALID_ENVIRONMENT; if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL) @@ -8334,7 +7834,6 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC NEW_BUFFER *buffer = NULL; uint32 offered = q_u->offered; uint32 *needed = &r_u->needed; - WERROR result; /* that's an [in out] buffer */ spoolss_move_buffer(q_u->buffer, &r_u->buffer); @@ -8346,13 +7845,12 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC switch(level) { case 1: - result = getprintprocessordirectory_level_1 + return getprintprocessordirectory_level_1 (&q_u->name, &q_u->environment, buffer, offered, needed); default: - result = WERR_UNKNOWN_LEVEL; + return WERR_UNKNOWN_LEVEL; } - return result; + return WERR_ACCESS_DENIED; } - |