diff options
author | Jeremy Allison <jra@samba.org> | 2002-01-22 06:39:20 +0000 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2002-01-22 06:39:20 +0000 |
commit | 6798d9b2d53f9a5ddf689ee6acbddb047712074c (patch) | |
tree | 780605d7193e186c7d6a10ba110186e421bb37f6 | |
parent | 3ff4d33e6d3b14bec3993d9e2c1eb950e84d0d0f (diff) | |
download | samba-6798d9b2d53f9a5ddf689ee6acbddb047712074c.tar.gz samba-6798d9b2d53f9a5ddf689ee6acbddb047712074c.tar.xz samba-6798d9b2d53f9a5ddf689ee6acbddb047712074c.zip |
Merged in the new c_setprinter code from JohnR - fixed up the tdb_store_int
to use endian independent modes.
Jeremy.
-rw-r--r-- | source/include/proto.h | 21 | ||||
-rw-r--r-- | source/printing/nt_printing.c | 110 | ||||
-rw-r--r-- | source/rpc_server/srv_spoolss_nt.c | 61 |
3 files changed, 146 insertions, 46 deletions
diff --git a/source/include/proto.h b/source/include/proto.h index 28ead2085e0..8a8d6340982 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -2290,6 +2290,8 @@ BOOL parse_lpq_entry(int snum,char *line, /*The following definitions come from printing/nt_printing.c */ BOOL nt_printing_init(void); +uint32 update_c_setprinter(BOOL initialize); +uint32 get_c_setprinter(void); int get_builtin_ntforms(nt_forms_struct **list); BOOL get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form); int get_ntforms(nt_forms_struct **list); @@ -2315,6 +2317,7 @@ void get_printer_subst_params(int snum, fstring *printername, fstring *sharename WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level); WERROR add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level); uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level); +uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level); WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param); WERROR get_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level, fstring sharename); uint32 free_a_printer(NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level); @@ -3424,11 +3427,8 @@ BOOL make_spoolss_q_addprinterex( const char* user_name, uint32 level, PRINTER_INFO_CTR *ctr); -BOOL make_spoolss_printer_info_2( - TALLOC_CTX *mem_ctx, - SPOOL_PRINTER_INFO_LEVEL_2 **spool_info2, - PRINTER_INFO_2 *info -); +BOOL make_spoolss_printer_info_2(TALLOC_CTX *mem_ctx, SPOOL_PRINTER_INFO_LEVEL_2 **spool_info2, + PRINTER_INFO_2 *info); BOOL spoolss_io_q_open_printer_ex(char *desc, SPOOL_Q_OPEN_PRINTER_EX *q_u, prs_struct *ps, int depth); BOOL make_spoolss_q_deleteprinterdriver( TALLOC_CTX *mem_ctx, @@ -3545,14 +3545,9 @@ BOOL make_spoolss_q_getprinter( NEW_BUFFER *buffer, uint32 offered ); -BOOL make_spoolss_q_setprinter( - TALLOC_CTX *mem_ctx, - SPOOL_Q_SETPRINTER *q_u, - const POLICY_HND *hnd, - uint32 level, - PRINTER_INFO_CTR *info, - uint32 command -); +BOOL make_spoolss_q_setprinter(TALLOC_CTX *mem_ctx, SPOOL_Q_SETPRINTER *q_u, + const POLICY_HND *hnd, uint32 level, PRINTER_INFO_CTR *info, + uint32 command); BOOL spoolss_io_r_setprinter(char *desc, SPOOL_R_SETPRINTER *r_u, prs_struct *ps, int depth); BOOL spoolss_io_q_setprinter(char *desc, SPOOL_Q_SETPRINTER *q_u, prs_struct *ps, int depth); BOOL spoolss_io_r_fcpn(char *desc, SPOOL_R_FCPN *r_u, prs_struct *ps, int depth); diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c index a1d696b63e6..890f20efecb 100644 --- a/source/printing/nt_printing.c +++ b/source/printing/nt_printing.c @@ -33,6 +33,7 @@ static TDB_CONTEXT *tdb_printers; /* used for printers files */ #define DRIVER_INIT_PREFIX "DRIVER_INIT/" #define PRINTERS_PREFIX "PRINTERS/" #define SECDESC_PREFIX "SECDESC/" +#define GLOBAL_C_SETPRINTER "GLOBALS/c_setprinter" #define NTDRIVERS_DATABASE_VERSION_1 1 #define NTDRIVERS_DATABASE_VERSION_2 2 @@ -289,12 +290,81 @@ BOOL nt_printing_init(void) } tdb_unlock_bystring(tdb_drivers, vstring); + update_c_setprinter(True); + return True; } +/******************************************************************* + tdb traversal function for counting printers. +********************************************************************/ + +static int traverse_counting_printers(TDB_CONTEXT *t, TDB_DATA key, + TDB_DATA data, void *context) +{ + int *printer_count = (int*)context; + + if (memcmp(PRINTERS_PREFIX, key.dptr, sizeof(PRINTERS_PREFIX)-1) == 0) { + (*printer_count)++; + DEBUG(10,("traverse_counting_printers: printer = [%s] printer_count = %d\n", key.dptr, *printer_count)); + } + + return 0; +} + +/******************************************************************* + Update the spooler global c_setprinter. This variable is initialized + when the parent smbd starts whith the number of existing printers. It + is monotonically increased by the current number of printers *after* + each add or delete printer RPC. Only Microsoft knows why... JRR020119 +********************************************************************/ + +uint32 update_c_setprinter(BOOL initialize) +{ + int32 c_setprinter; + int32 printer_count = 0; + + tdb_lock_bystring(tdb_printers, GLOBAL_C_SETPRINTER); + + /* Traverse the tdb, counting the printers */ + tdb_traverse(tdb_printers, traverse_counting_printers, (void *)&printer_count); + + /* If initializing, set c_setprinter to current printers count + * otherwise, bump it by the current printer count + */ + if (!initialize) + c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER) + printer_count; + else + c_setprinter = printer_count; + + DEBUG(10,("update_c_setprinter: c_setprinter = %u\n", (unsigned int)c_setprinter)); + tdb_store_int32(tdb_printers, GLOBAL_C_SETPRINTER, c_setprinter); + + tdb_unlock_bystring(tdb_printers, GLOBAL_C_SETPRINTER); + + return (uint32)c_setprinter; +} + +/******************************************************************* + Get the spooler global c_setprinter, accounting for initialization. +********************************************************************/ + +uint32 get_c_setprinter(void) +{ + int32 c_setprinter = tdb_fetch_int32(tdb_printers, GLOBAL_C_SETPRINTER); + + if (c_setprinter == (int32)-1) + c_setprinter = update_c_setprinter(True); + + DEBUG(10,("get_c_setprinter: c_setprinter = %d\n", c_setprinter)); + + return (uint32)c_setprinter; +} + /**************************************************************************** - get builtin form struct list + Get builtin form struct list. ****************************************************************************/ + int get_builtin_ntforms(nt_forms_struct **list) { *list = (nt_forms_struct *)memdup(&default_forms[0], sizeof(default_forms)); @@ -2697,8 +2767,9 @@ static uint32 rev_changeid(void) struct timeval tv; get_process_uptime(&tv); - /* This value is in ms * 100 */ - return (((tv.tv_sec * 1000000) + tv.tv_usec)/100); + + /* Return changeid as msec since spooler restart */ + return tv.tv_sec * 1000 + tv.tv_usec / 1000; } /* @@ -2800,6 +2871,7 @@ WERROR add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) /**************************************************************************** Initialize printer devmode & data with previously saved driver init values. ****************************************************************************/ + static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) { int len = 0; @@ -2808,6 +2880,17 @@ static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) NT_PRINTER_PARAM *current; NT_PRINTER_INFO_LEVEL_2 info; + /* + * Delete any printer data 'specifics' already set. When called for driver + * replace, there will generally be some, but during an add printer, there + * should not be any (if there are delete them). + */ + while ( (current=info_ptr->specific) != NULL ) { + info_ptr->specific=current->next; + SAFE_FREE(current->data); + SAFE_FREE(current); + } + ZERO_STRUCT(info); slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, info_ptr->drivername); @@ -2817,8 +2900,14 @@ static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) kbuf.dsize = strlen(key)+1; dbuf = tdb_fetch(tdb_drivers, kbuf); - if (!dbuf.dptr) + if (!dbuf.dptr) { + /* + * When changing to a driver that has no init info in the tdb, remove + * the previous drivers init info and leave the new on blank. + */ + free_nt_devicemode(&info_ptr->devmode); return False; + } /* * Get the saved DEVMODE.. @@ -2842,16 +2931,6 @@ static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr) info_ptr->printername, info_ptr->drivername)); /* - * There should not be any printer data 'specifics' already set during the - * add printer operation, if there are delete them. - */ - while ( (current=info_ptr->specific) != NULL ) { - info_ptr->specific=current->next; - SAFE_FREE(current->data); - SAFE_FREE(current); - } - - /* * Add the printer data 'specifics' to the new printer */ len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len); @@ -2894,6 +2973,7 @@ uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level) of whether it was installed from NT or 2K. Technically, they should be different, but they work out to the same struct. ****************************************************************************/ + static uint32 update_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info) { pstring key; @@ -2950,7 +3030,7 @@ done: Update (i.e. save) the driver init info (DEVMODE and specifics) for a printer ****************************************************************************/ -static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level) +uint32 update_driver_init(NT_PRINTER_INFO_LEVEL printer, uint32 level) { uint32 result; diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c index d4c1e7f974c..cc83d8b957a 100644 --- a/source/rpc_server/srv_spoolss_nt.c +++ b/source/rpc_server/srv_spoolss_nt.c @@ -32,6 +32,7 @@ #define MAX_OPEN_PRINTER_EXS 50 #endif +#define MAGIC_DISPLAY_FREQUENCY 0xfade2bad #define PHANTOM_DEVMODE_KEY "_p_f_a_n_t_0_m_" #define PRINTER_HANDLE_IS_PRINTER 0 #define PRINTER_HANDLE_IS_PRINTSERVER 1 @@ -242,7 +243,7 @@ static Printer_entry *find_printer_index_by_hnd(pipes_struct *p, POLICY_HND *hnd } /**************************************************************************** - close printer index by handle + Close printer index by handle. ****************************************************************************/ static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd) @@ -260,8 +261,9 @@ static BOOL close_printer_handle(pipes_struct *p, POLICY_HND *hnd) } /**************************************************************************** - delete a printer given a handle + Delete a printer given a handle. ****************************************************************************/ + static WERROR delete_printer_handle(pipes_struct *p, POLICY_HND *hnd) { Printer_entry *Printer = find_printer_index_by_hnd(p, hnd); @@ -1115,6 +1117,8 @@ WERROR _spoolss_deleteprinter(pipes_struct *p, SPOOL_Q_DELETEPRINTER *q_u, SPOOL result = delete_printer_handle(p, handle); + update_c_setprinter(FALSE); + if (W_ERROR_IS_OK(result)) { srv_spoolss_sendnotify(p, handle); } @@ -2664,7 +2668,7 @@ static BOOL construct_printer_info_0(PRINTER_INFO_0 *printer, int snum) printer->unknown18 = 0x0; printer->status = nt_printq_status(status.status); printer->unknown20 = 0x0; - printer->c_setprinter = ntprinter->info_2->c_setprinter; /* how many times setprinter has been called */ + printer->c_setprinter = get_c_setprinter(); /* monotonically increasing sum of delta printer counts */ printer->unknown22 = 0x0; printer->unknown23 = 0x6; /* 6 ???*/ printer->unknown24 = 0; /* unknown 24 to 26 are always 0 */ @@ -4676,8 +4680,8 @@ static BOOL nt_printer_info_level_equal(NT_PRINTER_INFO_LEVEL *p1, } /******************************************************************** - * called by spoolss_api_setprinter - * when updating a printer description + * Called by spoolss_api_setprinter + * when updating a printer description. ********************************************************************/ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, @@ -4694,7 +4698,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, result = WERR_OK; if (level!=2) { - DEBUG(0,("Send a mail to samba@samba.org\n")); + DEBUG(0,("update_printer: Send a mail to samba@samba.org\n")); DEBUGADD(0,("with the following message: update_printer: level!=2\n")); result = WERR_UNKNOWN_LEVEL; goto done; @@ -4733,7 +4737,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, /* we have a valid devmode convert it and link it*/ - DEBUGADD(8,("Converting the devicemode struct\n")); + DEBUGADD(8,("update_printer: Converting the devicemode struct\n")); if (!convert_devicemode(printer->info_2->printername, devmode, &printer->info_2->devmode)) { result = WERR_NOMEM; @@ -4753,7 +4757,7 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, annoying permission denied dialog box. */ if (nt_printer_info_level_equal(printer, old_printer)) { - DEBUG(3, ("printer info has not changed\n")); + DEBUG(3, ("update_printer: printer info has not changed\n")); result = WERR_OK; goto done; } @@ -4761,20 +4765,11 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, /* Check calling user has permission to update printer description */ if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) { - DEBUG(3, ("printer property change denied by security " - "descriptor\n")); + DEBUG(3, ("update_printer: printer property change denied by security descriptor\n")); result = WERR_ACCESS_DENIED; goto done; } - /* - * 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)) - set_driver_init(printer, 2); - /* Call addprinter hook */ if (*lp_addprinter_cmd()) { @@ -4784,6 +4779,32 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, } } + /* + * 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). + */ + 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)) + set_driver_init(printer, 2); + } + /* Update printer info */ result = add_a_printer(*printer, 2); @@ -5976,6 +5997,8 @@ static WERROR spoolss_addprinterex_level_2( pipes_struct *p, const UNISTR2 *uni_ free_a_printer(&printer,2); + update_c_setprinter(False); + srv_spoolss_sendnotify(p, handle); return WERR_OK; @@ -6399,6 +6422,8 @@ WERROR _spoolss_setprinterdata( pipes_struct *p, SPOOL_Q_SETPRINTERDATA *q_u, SP free_nt_printer_param(¶m); SAFE_FREE(old_param.data); + srv_spoolss_sendnotify(p, handle); + return status; } |