/*
- * Unix SMB/Netbios implementation.
- * Version 1.9.
+ * Unix SMB/CIFS implementation.
* RPC Pipe client / server routines
* Copyright (C) Andrew Tridgell 1992-2000,
* Copyright (C) Jean François Micouleau 1998-2000.
#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
+#define NTDRIVERS_DATABASE_VERSION_3 3 /* little endian version of v2 */
-#define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_2
+#define NTDRIVERS_DATABASE_VERSION NTDRIVERS_DATABASE_VERSION_3
/* Map generic permissions to printer object specific permissions */
-struct generic_mapping printer_generic_mapping = {
+GENERIC_MAPPING printer_generic_mapping = {
PRINTER_READ,
PRINTER_WRITE,
PRINTER_EXECUTE,
PRINTER_ALL_ACCESS
};
+STANDARD_MAPPING printer_std_mapping = {
+ PRINTER_READ,
+ PRINTER_WRITE,
+ PRINTER_EXECUTE,
+ PRINTER_ALL_ACCESS
+};
+
+/* Map generic permissions to print server object specific permissions */
+
+GENERIC_MAPPING printserver_generic_mapping = {
+ SERVER_READ,
+ SERVER_WRITE,
+ SERVER_EXECUTE,
+ SERVER_ALL_ACCESS
+};
+
+STANDARD_MAPPING printserver_std_mapping = {
+ SERVER_READ,
+ SERVER_WRITE,
+ SERVER_EXECUTE,
+ SERVER_ALL_ACCESS
+};
+
/* We need one default form to support our default printer. Msoft adds the
forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
array index). Letter is always first, so (for the current code) additions
{"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
};
-static BOOL upgrade_to_version_2(void)
+static BOOL upgrade_to_version_3(void)
{
TDB_DATA kbuf, newkey, dbuf;
- DEBUG(0,("upgrade_to_version_2: upgrading print tdb's to version 2\n"));
+ DEBUG(0,("upgrade_to_version_3: upgrading print tdb's to version 3\n"));
for (kbuf = tdb_firstkey(tdb_drivers); kbuf.dptr;
newkey = tdb_nextkey(tdb_drivers, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
dbuf = tdb_fetch(tdb_drivers, kbuf);
if (strncmp(kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) == 0) {
- DEBUG(0,("upgrade_to_version_2:moving form\n"));
+ DEBUG(0,("upgrade_to_version_3:moving form\n"));
if (tdb_store(tdb_forms, kbuf, dbuf, TDB_REPLACE) != 0) {
- DEBUG(0,("upgrade_to_version_2: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
+ DEBUG(0,("upgrade_to_version_3: failed to move form. Error (%s).\n", tdb_errorstr(tdb_forms)));
return False;
}
if (tdb_delete(tdb_drivers, kbuf) != 0) {
- DEBUG(0,("upgrade_to_version_2: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
+ DEBUG(0,("upgrade_to_version_3: failed to delete form. Error (%s)\n", tdb_errorstr(tdb_drivers)));
return False;
}
}
if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
- DEBUG(0,("upgrade_to_version_2:moving printer\n"));
+ DEBUG(0,("upgrade_to_version_3:moving printer\n"));
if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
- DEBUG(0,("upgrade_to_version_2: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
+ DEBUG(0,("upgrade_to_version_3: failed to move printer. Error (%s)\n", tdb_errorstr(tdb_printers)));
return False;
}
if (tdb_delete(tdb_drivers, kbuf) != 0) {
- DEBUG(0,("upgrade_to_version_2: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
+ DEBUG(0,("upgrade_to_version_3: failed to delete printer. Error (%s)\n", tdb_errorstr(tdb_drivers)));
return False;
}
}
if (strncmp(kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
- DEBUG(0,("upgrade_to_version_2:moving secdesc\n"));
+ DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
- DEBUG(0,("upgrade_to_version_2: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
+ DEBUG(0,("upgrade_to_version_3: failed to move secdesc. Error (%s)\n", tdb_errorstr(tdb_printers)));
return False;
}
if (tdb_delete(tdb_drivers, kbuf) != 0) {
- DEBUG(0,("upgrade_to_version_2: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
+ DEBUG(0,("upgrade_to_version_3: failed to delete secdesc. Error (%s)\n", tdb_errorstr(tdb_drivers)));
return False;
}
}
}
/****************************************************************************
-open the NT printing tdb
+ Open the NT printing tdb.
****************************************************************************/
+
BOOL nt_printing_init(void)
{
static pid_t local_pid;
/* handle a Samba upgrade */
tdb_lock_bystring(tdb_drivers, vstring);
- if (tdb_fetch_int(tdb_drivers, vstring) != NTDRIVERS_DATABASE_VERSION) {
-
- if (tdb_fetch_int(tdb_drivers, vstring) == NTDRIVERS_DATABASE_VERSION_1) {
- if (!upgrade_to_version_2())
- return False;
- } else
- tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
-
- tdb_store_int(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
+ {
+ int32 vers_id;
+
+ /* Cope with byte-reversed older versions of the db. */
+ vers_id = tdb_fetch_int32(tdb_drivers, vstring);
+ if ((vers_id == NTDRIVERS_DATABASE_VERSION_2) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_2)) {
+ /* Written on a bigendian machine with old fetch_int code. Save as le. */
+ /* The only upgrade between V2 and V3 is to save the version in little-endian. */
+ tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
+ vers_id = NTDRIVERS_DATABASE_VERSION;
+ }
+
+ if (vers_id != NTDRIVERS_DATABASE_VERSION) {
+
+ if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
+ if (!upgrade_to_version_3())
+ return False;
+ } else
+ tdb_traverse(tdb_drivers, tdb_traverse_delete_fn, NULL);
+
+ tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION);
+ }
}
tdb_unlock_bystring(tdb_drivers, vstring);
+ update_c_setprinter(True);
+
+ /*
+ * register callback to handle updating printers as new
+ * drivers are installed
+ */
+ message_register(MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer);
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 with 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));
DEBUG(0,("get_ntforms: Realloc fail.\n"));
return 0;
}
- *list = tl;
+ *list = tl;
(*list)[n] = form;
n++;
}
int access_mode;
int action;
NTSTATUS nt_status;
- pstring driverpath;
+ pstring driverpath;
DATA_BLOB null_pw;
files_struct *fsp = NULL;
BOOL bad_path;
return 0;
}
- /* connect to the print$ share under the same account as the user connected to the rpc pipe */
+ /*
+ * Connect to the print$ share under the same account as the user connected
+ * to the rpc pipe. Note we must still be root to do this.
+ */
+
/* Null password is ok - we are already an authenticated user... */
null_pw = data_blob(NULL, 0);
-
- become_root();
+ become_root();
conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
unbecome_root();
driverpath, major, minor));
}
- DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
- driverpath, cversion));
+ DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
+ driverpath, cversion));
close_file(fsp, True);
close_cnum(conn, user->vuid);
*perr = WERR_OK;
return cversion;
+
error_exit:
if(fsp)
close_file(fsp, True);
-
+
close_cnum(conn, user->vuid);
unbecome_user();
return -1;
/****************************************************************************
****************************************************************************/
static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
- struct current_user *user)
+ struct current_user *user)
{
fstring architecture;
fstring new_name;
* NT2K: cversion=3
*/
if ((driver->cversion = get_correct_cversion( architecture,
- driver->driverpath, user, &err)) == -1)
+ driver->driverpath, user, &err)) == -1)
return err;
return WERR_OK;
/****************************************************************************
****************************************************************************/
static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
- struct current_user *user)
+ struct current_user *user)
{
fstring architecture;
fstring new_name;
* NT2K: cversion=3
*/
if ((driver->version = get_correct_cversion(architecture,
- driver->driverpath, user, &err)) == -1)
+ driver->driverpath, user, &err)) == -1)
return err;
return WERR_OK;
DATA_BLOB null_pw;
connection_struct *conn;
NTSTATUS nt_status;
+ pstring inbuf;
+ pstring outbuf;
int ver = 0;
int i;
+ memset(inbuf, '\0', sizeof(inbuf));
+ memset(outbuf, '\0', sizeof(outbuf));
*perr = WERR_OK;
if (level==3)
get_short_archi(architecture, driver->environment);
- /* connect to the print$ share under the same account as the user connected to the rpc pipe */
- /* Null password is ok - we are already an authenticated user... */
+ /*
+ * Connect to the print$ share under the same account as the user connected to the rpc pipe.
+ * Note we must be root to do this.
+ */
+
+ become_root();
null_pw = data_blob(NULL, 0);
conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
+ unbecome_root();
if (conn == NULL) {
DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
* Save who we are - we are temporarily becoming the connection user.
*/
- push_sec_ctx();
-
if (!become_user(conn, conn->vuid)) {
DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
- pop_sec_ctx();
return False;
}
}
close_cnum(conn, user->vuid);
- pop_sec_ctx();
+ unbecome_user();
return ver == -1 ? False : True;
}
slprintf(directory, sizeof(directory)-1, "\\print$\\%s\\%d\\", architecture, driver->cversion);
- /* .inf files do not always list a file for each of the four standard files.
- * Don't prepend a path to a null filename, or client claims:
- * "The server on which the printer resides does not have a suitable
- * <printer driver name> printer driver installed. Click OK if you
- * wish to install the driver on your local machine."
- */
+ /* .inf files do not always list a file for each of the four standard files.
+ * Don't prepend a path to a null filename, or client claims:
+ * "The server on which the printer resides does not have a suitable
+ * <printer driver name> printer driver installed. Click OK if you
+ * wish to install the driver on your local machine."
+ */
if (strlen(driver->driverpath)) {
- fstrcpy(temp_name, driver->driverpath);
- slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
- }
+ fstrcpy(temp_name, driver->driverpath);
+ slprintf(driver->driverpath, sizeof(driver->driverpath)-1, "%s%s", directory, temp_name);
+ }
if (strlen(driver->datafile)) {
- fstrcpy(temp_name, driver->datafile);
- slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
- }
+ fstrcpy(temp_name, driver->datafile);
+ slprintf(driver->datafile, sizeof(driver->datafile)-1, "%s%s", directory, temp_name);
+ }
if (strlen(driver->configfile)) {
- fstrcpy(temp_name, driver->configfile);
- slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
- }
+ fstrcpy(temp_name, driver->configfile);
+ slprintf(driver->configfile, sizeof(driver->configfile)-1, "%s%s", directory, temp_name);
+ }
if (strlen(driver->helpfile)) {
- fstrcpy(temp_name, driver->helpfile);
- slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
- }
+ fstrcpy(temp_name, driver->helpfile);
+ slprintf(driver->helpfile, sizeof(driver->helpfile)-1, "%s%s", directory, temp_name);
+ }
if (driver->dependentfiles) {
for (i=0; *driver->dependentfiles[i]; i++) {
- fstrcpy(temp_name, driver->dependentfiles[i]);
- slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
+ fstrcpy(temp_name, driver->dependentfiles[i]);
+ slprintf(driver->dependentfiles[i], sizeof(driver->dependentfiles[i])-1, "%s%s", directory, temp_name);
}
}
if (len != buflen) {
char *tb;
-
+
tb = (char *)Realloc(buf, len);
if (!tb) {
DEBUG(0,("add_a_printer_driver_3: failed to enlarge buffer\n!"));
i=0;
while (len < dbuf.dsize) {
fstring *tddfs;
-
+
tddfs = (fstring *)Realloc(driver.dependentfiles,
sizeof(fstring)*(i+2));
if (tddfs == NULL) {
SAFE_FREE(dbuf.dptr);
if (len != dbuf.dsize) {
- SAFE_FREE(driver.dependentfiles);
+ SAFE_FREE(driver.dependentfiles);
return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
}
kbuf.dptr = key;
kbuf.dsize = strlen(key)+1;
- if (!tdb_exists(tdb_drivers, kbuf)) return False;
+ if (!tdb_exists(tdb_drivers, kbuf))
+ return False;
ZERO_STRUCT(info3);
get_a_printer_driver_3(&info3, model, "Windows 4.0", 0);
- DEBUGADD(10,("info3->name [%s]\n", info3->name));
- DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
- DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
- DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
- DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
+ DEBUGADD(10,("info3->name [%s]\n", info3->name));
+ DEBUGADD(10,("info3->datafile [%s]\n", info3->datafile));
+ DEBUGADD(10,("info3->helpfile [%s]\n", info3->helpfile));
+ DEBUGADD(10,("info3->monitorname [%s]\n", info3->monitorname));
+ DEBUGADD(10,("info3->defaultdatatype [%s]\n", info3->defaultdatatype));
for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
- DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
- }
- DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
- DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
- DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
+ DEBUGADD(10,("info3->dependentfiles [%s]\n", info3->dependentfiles[i]));
+ }
+ DEBUGADD(10,("info3->environment [%s]\n", info3->environment));
+ DEBUGADD(10,("info3->driverpath [%s]\n", info3->driverpath));
+ DEBUGADD(10,("info3->configfile [%s]\n", info3->configfile));
/*pstrcat(line, info3->name); pstrcat(line, ":");*/
- trim_string(info3->configfile, "\\print$\\WIN40\\0\\", 0);
- pstrcat(line, info3->configfile);
- pstrcat(line, ":");
+ trim_string(info3->driverpath, "\\print$\\WIN40\\0\\", 0);
+ pstrcat(line, info3->driverpath);
+ pstrcat(line, ":");
trim_string(info3->datafile, "\\print$\\WIN40\\0\\", 0);
pstrcat(line, info3->datafile);
- pstrcat(line, ":");
+ pstrcat(line, ":");
trim_string(info3->helpfile, "\\print$\\WIN40\\0\\", 0);
pstrcat(line, info3->helpfile);
- pstrcat(line, ":");
+ pstrcat(line, ":");
trim_string(info3->monitorname, "\\print$\\WIN40\\0\\", 0);
pstrcat(line, info3->monitorname);
- pstrcat(line, ":");
+ pstrcat(line, ":");
pstrcat(line, "RAW"); /*info3->defaultdatatype);*/
- pstrcat(line, ":");
+ pstrcat(line, ":");
- for (i=0; info3->dependentfiles &&
- *info3->dependentfiles[i]; i++) {
- if (i) pstrcat(line, ","); /* don't end in a "," */
+ for (i=0; info3->dependentfiles && *info3->dependentfiles[i]; i++) {
+ if (i)
+ pstrcat(line, ","); /* don't end in a "," */
trim_string(info3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
pstrcat(line, info3->dependentfiles[i]);
}
}
/****************************************************************************
-debugging function, dump at level 6 the struct in the logs
+ Debugging function, dump at level 6 the struct in the logs.
****************************************************************************/
+
static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
{
uint32 result;
break;
}
default:
- DEBUGADD(1,("Level not implemented\n"));
+ DEBUGADD(106,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
result=1;
break;
}
/****************************************************************************
-delete a printer - this just deletes the printer info file, any open
-handles are not affected
+ Delete a printer - this just deletes the printer info file, any open
+ handles are not affected.
****************************************************************************/
+
uint32 del_a_printer(char *sharename)
{
pstring key;
if (buflen != len) {
char *tb;
-
+
tb = (char *)Realloc(buf, len);
if (!tb) {
DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
- SAFE_FREE(param->data);
+ SAFE_FREE(param->data);
SAFE_FREE(*param_ptr);
}
NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename)
{
-/*
- * should I init this ones ???
- nt_devmode->devicename
-*/
char adevice[32];
NT_DEVICEMODE *nt_devmode = (NT_DEVICEMODE *)malloc(sizeof(NT_DEVICEMODE));
DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
- SAFE_FREE(nt_devmode->private);
+ SAFE_FREE(nt_devmode->private);
SAFE_FREE(*devmode_ptr);
}
fstrcpy(info.printprocessor, "winprint");
fstrcpy(info.datatype, "RAW");
- info.attributes = PRINTER_ATTRIBUTE_SHARED \
- | PRINTER_ATTRIBUTE_LOCAL \
- | PRINTER_ATTRIBUTE_RAW_ONLY \
- | PRINTER_ATTRIBUTE_QUEUED ; /* attributes */
+ info.attributes = PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK; /* attributes */
info.starttime = 0; /* Minutes since 12:00am GMT */
info.untiltime = 0; /* Minutes since 12:00am GMT */
info.priority = 1;
info.default_priority = 1;
- info.setuptime = (uint32)time(NULL) - 86400; /* minus 1 day */
+ info.setuptime = (uint32)time(NULL);
/*
* I changed this as I think it is better to have a generic
* DEVMODE than to crash Win2k explorer.exe --jerry
* See the HP Deskjet 990c Win2k drivers for an example.
+ *
+ * However the default devmode appears to cause problems
+ * with the HP CLJ 8500 PCL driver. Hence the addition of
+ * the "default devmode" parameter --jerry 22/01/2002
*/
-#if 0 /* JRA - NO NOT CHANGE ! */
- info.devmode = NULL;
-#else
- /*
- * We should not return a default devicemode, as this causes
- * Win2K to not send the correct one on PCL drivers. It needs to
- * see a null devicemode so it can then overwrite the devicemode
- * on OpenPrinterEx. Yes this *is* insane :-). JRA.
- */
- if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
- goto fail;
-#endif
+ if (lp_default_devmode(snum)) {
+ if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL)
+ goto fail;
+ }
+ else {
+ info.devmode = NULL;
+ }
/* This will get the current RPC talloc context, but we should be
passing this as a parameter... fixme... JRA ! */
return WERR_OK;
fail:
-
if (info.devmode)
free_nt_devicemode(&info.devmode);
return WERR_ACCESS_DENIED;
info.parameters);
/* Samba has to have shared raw drivers. */
- info.attributes |= (PRINTER_ATTRIBUTE_SHARED|PRINTER_ATTRIBUTE_RAW_ONLY);
+ info.attributes |= (PRINTER_ATTRIBUTE_SHARED | PRINTER_ATTRIBUTE_NETWORK);
/* Restore the stripped strings. */
slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
fstrcpy(info.printername, printername);
len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
-#if 1
+
/*
* Some client drivers freak out if there is a NULL devmode
* (probably the driver is not checking before accessing
* the devmode pointer) --jerry
+ *
+ * See comments in get_a_printer_2_default()
*/
- if (!info.devmode)
+
+ if (lp_default_devmode(lp_servicenumber(sharename)) && !info.devmode)
{
DEBUG(8,("get_a_printer_2: Constructing a default device mode for [%s]\n",
printername));
info.devmode = construct_nt_devicemode(printername);
}
-#endif
+
len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
/* This will get the current RPC talloc context, but we should be
break;
}
default:
- DEBUGADD(1,("Level not implemented\n"));
+ DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
result=1;
break;
}
void get_printer_subst_params(int snum, fstring *printername, fstring *sharename, fstring *portname)
{
NT_PRINTER_INFO_LEVEL *printer = NULL;
-
+
**printername = **sharename = **portname = '\0';
if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
free_a_printer(&printer, 2);
}
+/****************************************************************************
+ Update the changeid time.
+ This is SO NASTY as some drivers need this to change, others need it
+ static. This value will change every second, and I must hope that this
+ is enough..... DON'T CHANGE THIS CODE WITHOUT A TEST MATRIX THE SIZE OF
+ UTAH ! JRA.
+****************************************************************************/
+
+static uint32 rev_changeid(void)
+{
+ struct timeval tv;
+
+ get_process_uptime(&tv);
+
+#if 1 /* JERRY */
+ /* Return changeid as msec since spooler restart */
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+#else
+ /*
+ * This setting seems to work well but is too untested
+ * to replace the above calculation. Left in for experiementation
+ * of the reader --jerry (Tue Mar 12 09:15:05 CST 2002)
+ */
+ return tv.tv_sec * 10 + tv.tv_usec / 100000;
+#endif
+}
+
/*
* The function below are the high level ones.
* only those ones must be called from the spoolss code.
{
/*
* Update the changestamp. Emperical tests show that the
- * ChangeID is always updated,but c_setprinter is only
- * incremented on a SetPrinter() call.
+ * ChangeID is always updated,but c_setprinter is
+ * global spooler variable (not per printer).
*/
- time_t time_unix = time(NULL);
-
/* ChangeID **must** be increasing over the lifetime
- of client's spoolss service in order for the
+ of client's spoolss service in order for the
client's cache to show updates */
- printer.info_2->changeid = time_unix * 100;
+ printer.info_2->changeid = rev_changeid();
/*
* Because one day someone will ask:
return result;
}
-/****************************************************************************
- Add a printer. This is called from ADDPRINTER(EX) and also SETPRINTER.
- We split this out from mod_a_printer as it updates the id's and timestamps.
-****************************************************************************/
-
-WERROR add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
-{
- WERROR result;
-
- dump_a_printer(printer, level);
-
- switch (level)
- {
- case 2:
- {
- /*
- * Update the changestamp. See comments in mod_a_printer()
- * --jerry
- */
-
- time_t time_unix = time(NULL);
-
- printer.info_2->changeid = time_unix * 100;
- printer.info_2->c_setprinter++;
-
- result=update_a_printer_2(printer.info_2);
- break;
- }
- default:
- result=WERR_UNKNOWN_LEVEL;
- break;
- }
-
- return result;
-}
-
/****************************************************************************
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;
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);
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..
ZERO_STRUCT(info.devmode->devicename);
fstrcpy(info.devmode->devicename, info_ptr->printername);
+
+ /*
+ * NT/2k does not change out the entire DeviceMode of a printer
+ * when changing the driver. Only the driverextra, private, &
+ * driverversion fields. --jerry (Thu Mar 14 08:58:43 CST 2002)
+ */
+
+#if 0 /* JERRY */
+
/*
* Bind the saved DEVMODE to the new the printer.
*/
free_nt_devicemode(&info_ptr->devmode);
info_ptr->devmode = info.devmode;
+#else
+ /* copy the entire devmode if we currently don't have one */
- DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
- info_ptr->printername, info_ptr->drivername));
+ if (!info_ptr->devmode) {
+ DEBUG(10,("set_driver_init_2: Current Devmode is NULL. Copying entire Device Mode\n"));
+ info_ptr->devmode = info.devmode;
+ }
+ else {
+ /* only set the necessary fields */
- /*
- * 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);
+ DEBUG(10,("set_driver_init_2: Setting driverversion [0x%x] and private data [0x%x]\n",
+ info.devmode->driverversion, info.devmode->driverextra));
+
+ info_ptr->devmode->driverversion = info.devmode->driverversion;
+
+ SAFE_FREE(info_ptr->devmode->private);
+ info_ptr->devmode->private = NULL;
+
+ if (info.devmode->driverversion)
+ info_ptr->devmode->private = memdup(info.devmode->private, info.devmode->driverversion);
+
+ free_nt_devicemode(&info.devmode);
}
+#endif
+
+ DEBUG(10,("set_driver_init_2: Set printer [%s] init DEVMODE for driver [%s]\n",
+ info_ptr->printername, info_ptr->drivername));
/*
* Add the printer data 'specifics' to the new printer
return result;
}
+/****************************************************************************
+ Delete driver init data stored for a specified driver
+****************************************************************************/
+
+BOOL del_driver_init(char *drivername)
+{
+ pstring key;
+ TDB_DATA kbuf;
+
+ if (!drivername || !*drivername) {
+ DEBUG(3,("del_driver_init: No drivername specified!\n"));
+ return False;
+ }
+
+ slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
+
+ kbuf.dptr = key;
+ kbuf.dsize = strlen(key)+1;
+
+ DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
+
+ return (tdb_delete(tdb_drivers, kbuf) == 0);
+}
+
/****************************************************************************
Pack up the DEVMODE and specifics for a printer into a 'driver init' entry
in the tdb. Note: this is different from the driver entry and the printer
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;
if (buflen != len) {
char *tb;
-
+
tb = (char *)Realloc(buf, len);
if (!tb) {
DEBUG(0, ("update_driver_init_2: failed to enlarge buffer!\n"));
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;
NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
/*
- * Set devmode on printer info, so entire printer initialization can be
- * saved to tdb.
+ * When the DEVMODE is already set on the printer, don't try to unpack it.
*/
- if ((ctx = talloc_init()) == NULL)
- return WERR_NOMEM;
- if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
- status = WERR_NOMEM;
- goto done;
- }
+ if (!printer->info_2->devmode && param->data_len) {
+ /*
+ * Set devmode on printer info, so entire printer initialization can be
+ * saved to tdb.
+ */
+
+ if ((ctx = talloc_init()) == NULL)
+ return WERR_NOMEM;
+
+ if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
+ status = WERR_NOMEM;
+ goto done;
+ }
- ZERO_STRUCTP(nt_devmode);
+ ZERO_STRUCTP(nt_devmode);
- /*
- * The DEVMODE is held in the 'data' component of the param in raw binary.
- * Convert it to to a devmode structure
- */
- if (!convert_driver_init(param, ctx, nt_devmode)) {
- DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
- status = WERR_INVALID_PARAM;
- goto done;
+ /*
+ * The DEVMODE is held in the 'data' component of the param in raw binary.
+ * Convert it to to a devmode structure
+ */
+ if (!convert_driver_init(param, ctx, nt_devmode)) {
+ DEBUG(10,("save_driver_init_2: error converting DEVMODE\n"));
+ status = WERR_INVALID_PARAM;
+ goto done;
+ }
+
+ printer->info_2->devmode = nt_devmode;
}
/*
* a 'driver init' element in the tdb
*
*/
- printer->info_2->devmode = nt_devmode;
+
if (update_driver_init(*printer, 2)!=0) {
DEBUG(10,("save_driver_init_2: error updating DEVMODE\n"));
status = WERR_NOMEM;
DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
printer->info_2->printername));
}
+
+#if 0 /* JERRY */
+ srv_spoolss_sendnotify(p, handle);
+#endif
done:
talloc_destroy(ctx);
break;
}
- DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, werror_str(result)));
+ DEBUG(10,("get_a_printer: [%s] level %u returning %s\n", sharename, (unsigned int)level, dos_errstr(result)));
return result;
}
SEC_DESC *psd = NULL;
DOM_SID owner_sid;
size_t sd_size;
- enum SID_NAME_USE name_type;
/* Create an ACE where Everyone is allowed to print */
/* Make the security descriptor owned by the Administrators group
on the PDC of the domain. */
- if (winbind_lookup_name(lp_workgroup(), &owner_sid, &name_type)) {
+ if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
} else {
- uint32 owner_rid;
- /* Backup plan - make printer owned by admins or root.
- This should emulate a lanman printer as security
- settings can't be changed. */
+ /* Backup plan - make printer owned by admins.
+ This should emulate a lanman printer as security
+ settings can't be changed. */
- sid_peek_rid(&owner_sid, &owner_rid);
-
- if (owner_rid != BUILTIN_ALIAS_RID_PRINT_OPS &&
- owner_rid != BUILTIN_ALIAS_RID_ADMINS &&
- owner_rid != DOMAIN_USER_RID_ADMIN &&
- !lookup_name("root", &owner_sid, &name_type)) {
- sid_copy(&owner_sid, &global_sid_World);
- }
+ sid_copy(&owner_sid, get_global_sam_sid());
+ sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
}
init_sec_access(&sa, PRINTER_ACE_FULL_CONTROL);
}
if (!psd) {
- DEBUG(0,("construct_default_printer_sdb: Failed to make SEC_DESC.\n"));
+ DEBUG(0,("construct_default_printer_sd: Failed to make SEC_DESC.\n"));
return NULL;
}
return False;
}
- /* Save default security descriptor for later */
+ /* Save default security descriptor for later */
- prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
- sizeof(SEC_DESC_BUF), ctx, MARSHALL);
+ prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
+ sizeof(SEC_DESC_BUF), ctx, MARSHALL);
- if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1))
- tdb_prs_store(tdb_printers, key, &ps);
+ if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1))
+ tdb_prs_store(tdb_printers, key, &ps);
- prs_mem_free(&ps);
+ prs_mem_free(&ps);
return True;
}
if (sid_equal((*secdesc_ctr)->sec->owner_sid, &global_sid_World)) {
DOM_SID owner_sid;
- enum SID_NAME_USE name_type;
/* Change sd owner to workgroup administrator */
- if (winbind_lookup_name(lp_workgroup(), &owner_sid,
- &name_type)) {
+ if (secrets_fetch_domain_sid(lp_workgroup(), &owner_sid)) {
SEC_DESC_BUF *new_secdesc_ctr = NULL;
SEC_DESC *psd = NULL;
size_t size;
return ok;
}
+#if 0 /* JERRY - not used */
/****************************************************************************
Attempt to write a default device.
*****************************************************************************/
* Finally write back to the tdb.
*/
- result = add_a_printer(*printer, 2);
+ result = mod_a_printer(*printer, 2);
done:
free_a_printer(&printer, 2);
return result;
}
+#endif /* JERRY */