summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2002-01-22 06:39:20 +0000
committerJeremy Allison <jra@samba.org>2002-01-22 06:39:20 +0000
commit6798d9b2d53f9a5ddf689ee6acbddb047712074c (patch)
tree780605d7193e186c7d6a10ba110186e421bb37f6
parent3ff4d33e6d3b14bec3993d9e2c1eb950e84d0d0f (diff)
downloadsamba-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.h21
-rw-r--r--source/printing/nt_printing.c110
-rw-r--r--source/rpc_server/srv_spoolss_nt.c61
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(&param);
SAFE_FREE(old_param.data);
+ srv_spoolss_sendnotify(p, handle);
+
return status;
}