/*
- * 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.
#include "includes.h"
-extern int DEBUGLEVEL;
-extern pstring global_myname;
extern DOM_SID global_sid_World;
static TDB_CONTEXT *tdb_forms; /* used for forms 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
+#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;
}
}
- safe_free(dbuf.dptr);
+ SAFE_FREE(dbuf.dptr);
}
return True;
}
/****************************************************************************
-open the NT printing tdb
+ Open the NT printing tdb.
****************************************************************************/
+
BOOL nt_printing_init(void)
{
static pid_t local_pid;
if (tdb_drivers && tdb_printers && tdb_forms && local_pid == sys_getpid())
return True;
- tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, USE_TDB_MMAP_FLAG, O_RDWR|O_CREAT, 0600);
+ tdb_drivers = tdb_open_log(lock_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
if (!tdb_drivers) {
DEBUG(0,("nt_printing_init: Failed to open nt drivers database %s (%s)\n",
lock_path("ntdrivers.tdb"), strerror(errno) ));
return False;
}
- tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, USE_TDB_MMAP_FLAG, O_RDWR|O_CREAT, 0600);
+ tdb_printers = tdb_open_log(lock_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
if (!tdb_printers) {
DEBUG(0,("nt_printing_init: Failed to open nt printers database %s (%s)\n",
lock_path("ntprinters.tdb"), strerror(errno) ));
return False;
}
- tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, USE_TDB_MMAP_FLAG, O_RDWR|O_CREAT, 0600);
+ tdb_forms = tdb_open_log(lock_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
if (!tdb_forms) {
DEBUG(0,("nt_printing_init: Failed to open nt forms database %s (%s)\n",
lock_path("ntforms.tdb"), strerror(errno) ));
/* 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_func)tdb_delete, 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));
ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddd",
&i, &form.flag, &form.width, &form.length, &form.left,
&form.top, &form.right, &form.bottom);
- safe_free(dbuf.dptr);
+ SAFE_FREE(dbuf.dptr);
if (ret != dbuf.dsize) continue;
tl = Realloc(*list, sizeof(nt_forms_struct)*(n+1));
DEBUG(0,("get_ntforms: Realloc fail.\n"));
return 0;
}
- *list = tl;
+ *list = tl;
(*list)[n] = form;
n++;
}
/****************************************************************************
delete a named form struct
****************************************************************************/
-BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, uint32 *ret)
+BOOL delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
{
pstring key;
TDB_DATA kbuf;
int n=0;
fstring form_name;
- *ret = 0;
+ *ret = WERR_OK;
unistr2_to_ascii(form_name, del_name, sizeof(form_name)-1);
if (n == *count) {
DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
- *ret = ERRinvalidparam;
+ *ret = WERR_INVALID_PARAM;
return False;
}
kbuf.dsize = strlen(key)+1;
kbuf.dptr = key;
if (tdb_delete(tdb_forms, kbuf) != 0) {
- *ret = ERRnomem;
+ *ret = WERR_NOMEM;
return False;
}
}
/****************************************************************************
-Version information in Microsoft files is held in a VS_VERSION_INFO structure.
-There are two case to be covered here: PE (Portable Executable) and NE (New
-Executable) files. Both files support the same INFO structure, but PE files
-store the signature in unicode, and NE files store it as !unicode.
+ Version information in Microsoft files is held in a VS_VERSION_INFO structure.
+ There are two case to be covered here: PE (Portable Executable) and NE (New
+ Executable) files. Both files support the same INFO structure, but PE files
+ store the signature in unicode, and NE files store it as !unicode.
+ returns -1 on error, 1 on version info found, and 0 on no version info found.
****************************************************************************/
-static BOOL get_file_version(files_struct *fsp, char *fname,uint32 *major,
- uint32 *minor)
+
+static int get_file_version(files_struct *fsp, char *fname,uint32 *major, uint32 *minor)
{
int i;
char *buf;
/* get the section table */
num_sections = SVAL(buf,PE_HEADER_NUMBER_OF_SECTIONS);
section_table_bytes = num_sections * PE_HEADER_SECT_HEADER_SIZE;
- free(buf);
+ SAFE_FREE(buf);
if ((buf=malloc(section_table_bytes)) == NULL) {
DEBUG(0,("get_file_version: PE file [%s] section table malloc failed bytes = %d\n",
fname, section_table_bytes));
int section_pos = IVAL(buf,sec_offset+PE_HEADER_SECT_PTR_DATA_OFFSET);
int section_bytes = IVAL(buf,sec_offset+PE_HEADER_SECT_SIZE_DATA_OFFSET);
- free(buf);
+ SAFE_FREE(buf);
if ((buf=malloc(section_bytes)) == NULL) {
DEBUG(0,("get_file_version: PE file [%s] version malloc failed bytes = %d\n",
fname, section_bytes));
fname, *major, *minor,
(*major>>16)&0xffff, *major&0xffff,
(*minor>>16)&0xffff, *minor&0xffff));
- free(buf);
- return True;
+ SAFE_FREE(buf);
+ return 1;
}
}
}
/* Version info not found, fall back to origin date/time */
DEBUG(10,("get_file_version: PE file [%s] has no version info\n", fname));
- free(buf);
- return False;
+ SAFE_FREE(buf);
+ return 0;
} else if (SVAL(buf,NE_HEADER_SIGNATURE_OFFSET) == NE_HEADER_SIGNATURE) {
if (CVAL(buf,NE_HEADER_TARGET_OS_OFFSET) != NE_HEADER_TARGOS_WIN ) {
}
/* Allocate a bit more space to speed up things */
- free(buf);
+ SAFE_FREE(buf);
if ((buf=malloc(VS_NE_BUF_SIZE)) == NULL) {
DEBUG(0,("get_file_version: NE file [%s] malloc failed bytes = %d\n",
fname, PE_HEADER_SIZE));
fname, *major, *minor,
(*major>>16)&0xffff, *major&0xffff,
(*minor>>16)&0xffff, *minor&0xffff));
- free(buf);
- return True;
+ SAFE_FREE(buf);
+ return 1;
}
}
}
/* Version info not found, fall back to origin date/time */
DEBUG(0,("get_file_version: NE file [%s] Version info not found\n", fname));
- free(buf);
- return False;
+ SAFE_FREE(buf);
+ return 0;
} else
/* Assume this isn't an error... the file just looks sort of like a PE/NE file */
fname, IVAL(buf,PE_HEADER_SIGNATURE_OFFSET)));
no_version_info:
- free(buf);
- return False;
+ SAFE_FREE(buf);
+ return 0;
error_exit:
- free(buf);
+ SAFE_FREE(buf);
return -1;
}
Determine the correct cVersion associated with an architecture and driver
****************************************************************************/
static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
- struct current_user *user, uint32 *perr)
+ struct current_user *user, WERROR *perr)
{
int cversion;
int access_mode;
int action;
- int ecode;
- pstring driverpath;
- fstring user_name;
- fstring null_pw;
+ NTSTATUS nt_status;
+ pstring driverpath;
+ DATA_BLOB null_pw;
files_struct *fsp = NULL;
BOOL bad_path;
SMB_STRUCT_STAT st;
- struct passwd *pass;
connection_struct *conn;
ZERO_STRUCT(st);
+ *perr = WERR_INVALID_PARAM;
+
/* If architecture is Windows 95/98/ME, the version is always 0. */
if (strcmp(architecture, "WIN40") == 0) {
DEBUG(10,("get_correct_cversion: Driver is Win9x, cversion = 0\n"));
+ *perr = WERR_OK;
return 0;
}
- become_root();
- pass = sys_getpwuid(user->uid);
- if(pass == NULL) {
- DEBUG(0,("get_correct_cversion: Unable to get passwd entry for uid %u\n",
- (unsigned int)user->uid ));
- unbecome_root();
- *perr = ERRnoaccess;
- return -1;
- }
- unbecome_root();
-
- /* connect to the print$ share under the same account as the user connected
- * to the rpc pipe */
- fstrcpy(user_name, pass->pw_name );
- DEBUG(10,("get_correct_cversion: uid %d -> user %s\n", (int)user->uid, user_name));
+ /*
+ * 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 = '\0';
- conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
+ null_pw = data_blob(NULL, 0);
+ become_root();
+ conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
+ unbecome_root();
if (conn == NULL) {
DEBUG(0,("get_correct_cversion: Unable to connect\n"));
- *perr = (uint32)ecode;
+ *perr = ntstatus_to_werror(nt_status);
return -1;
}
- /* Save who we are - we are temporarily becoming the connection user. */
- push_sec_ctx();
-
+ /* We are temporarily becoming the connection user. */
if (!become_user(conn, conn->vuid)) {
- DEBUG(0,("get_correct_cversion: Can't become user %s\n", user_name ));
- *perr = ERRnoaccess;
- pop_sec_ctx();
+ DEBUG(0,("get_correct_cversion: Can't become user!\n"));
+ *perr = WERR_ACCESS_DENIED;
return -1;
}
if (!fsp) {
DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
driverpath, errno));
- *perr = ERRnoaccess;
+ *perr = WERR_ACCESS_DENIED;
goto error_exit;
}
else {
close_file(fsp, True);
close_cnum(conn, user->vuid);
- pop_sec_ctx();
+ unbecome_user();
+ *perr = WERR_OK;
return cversion;
- error_exit:
- if(fsp)
- close_file(fsp, True);
+ error_exit:
- close_cnum(conn, user->vuid);
- pop_sec_ctx();
- return -1;
+ if(fsp)
+ close_file(fsp, True);
+
+ close_cnum(conn, user->vuid);
+ unbecome_user();
+ return -1;
}
/****************************************************************************
****************************************************************************/
-static uint32 clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
+static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
struct current_user *user)
{
fstring architecture;
fstring new_name;
char *p;
int i;
- uint32 err;
+ WERROR err;
/* clean up the driver name.
* we can get .\driver.dll
driver->driverpath, user, &err)) == -1)
return err;
- return NT_STATUS_OK;
+ return WERR_OK;
}
/****************************************************************************
****************************************************************************/
-static uint32 clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
+static WERROR clean_up_driver_struct_level_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver,
struct current_user *user)
{
fstring architecture;
fstring new_name;
char *p;
int i;
- uint32 err;
+ WERROR err;
/* clean up the driver name.
* we can get .\driver.dll
driver->driverpath, user, &err)) == -1)
return err;
- return NT_STATUS_OK;
+ return WERR_OK;
}
/****************************************************************************
****************************************************************************/
-uint32 clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
+WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
uint32 level, struct current_user *user)
{
switch (level) {
return clean_up_driver_struct_level_6(driver, user);
}
default:
- return ERRinvalidparam;
+ return WERR_INVALID_PARAM;
}
}
/****************************************************************************
****************************************************************************/
-BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level, struct current_user *user, uint32 *perr)
+BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
+ struct current_user *user, WERROR *perr)
{
NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
pstring new_dir;
pstring old_name;
pstring new_name;
- fstring user_name;
- fstring null_pw;
+ DATA_BLOB null_pw;
connection_struct *conn;
+ NTSTATUS nt_status;
pstring inbuf;
pstring outbuf;
- struct passwd *pass;
- int ecode;
int ver = 0;
int i;
- *perr = 0;
memset(inbuf, '\0', sizeof(inbuf));
memset(outbuf, '\0', sizeof(outbuf));
+ *perr = WERR_OK;
if (level==3)
driver=driver_abstract.info_3;
get_short_archi(architecture, driver->environment);
+ /*
+ * 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();
- pass = sys_getpwuid(user->uid);
- if(pass == NULL) {
- DEBUG(0,("move_driver_to_download_area: Unable to get passwd entry for uid %u\n",
- (unsigned int)user->uid ));
- unbecome_root();
- return False;
- }
+ null_pw = data_blob(NULL, 0);
+ conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
unbecome_root();
- /* connect to the print$ share under the same account as the user connected to the rpc pipe */
- fstrcpy(user_name, pass->pw_name );
- DEBUG(10,("move_driver_to_download_area: uid %d -> user %s\n", (int)user->uid, user_name));
-
- /* Null password is ok - we are already an authenticated user... */
- *null_pw = '\0';
- conn = make_connection("print$", user_name, null_pw, 0, "A:", user->vuid, &ecode);
-
if (conn == NULL) {
DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
- *perr = (uint32)ecode;
+ *perr = ntstatus_to_werror(nt_status);
return False;
}
* 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 %s\n", user_name ));
- pop_sec_ctx();
+ DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
return False;
}
*/
DEBUG(5,("Creating first directory\n"));
slprintf(new_dir, sizeof(new_dir)-1, "%s/%d", architecture, driver->cversion);
- mkdir_internal(conn, inbuf, outbuf, new_dir);
+ mkdir_internal(conn, new_dir);
/* For each driver file, archi\filexxx.yyy, if there is a duplicate file
* listed for this driver which has already been moved, skip it (note:
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->driverpath);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->driverpath);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
+ NTSTATUS status;
+ status = rename_internals(conn, new_name, old_name, True);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
- *perr = (uint32)SVAL(outbuf,smb_err);
- unlink_internals(conn, inbuf, outbuf, 0, new_name);
+ *perr = ntstatus_to_werror(status);
+ unlink_internals(conn, 0, new_name);
ver = -1;
}
}
else
- unlink_internals(conn, inbuf, outbuf, 0, new_name);
+ unlink_internals(conn, 0, new_name);
}
if (driver->datafile && strlen(driver->datafile)) {
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->datafile);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->datafile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
+ NTSTATUS status;
+ status = rename_internals(conn, new_name, old_name, True);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
- *perr = (uint32)SVAL(outbuf,smb_err);
- unlink_internals(conn, inbuf, outbuf, 0, new_name);
+ *perr = ntstatus_to_werror(status);
+ unlink_internals(conn, 0, new_name);
ver = -1;
}
}
else
- unlink_internals(conn, inbuf, outbuf, 0, new_name);
+ unlink_internals(conn, 0, new_name);
}
}
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->configfile);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->configfile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
+ NTSTATUS status;
+ status = rename_internals(conn, new_name, old_name, True);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
- *perr = (uint32)SVAL(outbuf,smb_err);
- unlink_internals(conn, inbuf, outbuf, 0, new_name);
+ *perr = ntstatus_to_werror(status);
+ unlink_internals(conn, 0, new_name);
ver = -1;
}
}
else
- unlink_internals(conn, inbuf, outbuf, 0, new_name);
+ unlink_internals(conn, 0, new_name);
}
}
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->helpfile);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->helpfile);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
+ NTSTATUS status;
+ status = rename_internals(conn, new_name, old_name, True);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
- *perr = (uint32)SVAL(outbuf,smb_err);
- unlink_internals(conn, inbuf, outbuf, 0, new_name);
+ *perr = ntstatus_to_werror(status);
+ unlink_internals(conn, 0, new_name);
ver = -1;
}
}
else
- unlink_internals(conn, inbuf, outbuf, 0, new_name);
+ unlink_internals(conn, 0, new_name);
}
}
slprintf(new_name, sizeof(new_name)-1, "%s/%s", architecture, driver->dependentfiles[i]);
slprintf(old_name, sizeof(old_name)-1, "%s/%s", new_dir, driver->dependentfiles[i]);
if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- if (rename_internals(conn, inbuf, outbuf, new_name, old_name, True) != 0) {
+ NTSTATUS status;
+ status = rename_internals(conn, new_name, old_name, True);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
new_name, old_name));
- *perr = (uint32)SVAL(outbuf,smb_err);
- unlink_internals(conn, inbuf, outbuf, 0, new_name);
+ *perr = ntstatus_to_werror(status);
+ unlink_internals(conn, 0, new_name);
ver = -1;
}
}
else
- unlink_internals(conn, inbuf, outbuf, 0, new_name);
+ unlink_internals(conn, 0, new_name);
}
NextDriver: ;
}
}
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!"));
if (ret)
DEBUG(0,("add_a_printer_driver_3: Adding driver with key %s failed.\n", key ));
- safe_free(buf);
+ SAFE_FREE(buf);
return ret;
}
/****************************************************************************
****************************************************************************/
-static uint32 get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
+static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
{
NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
fstrcpy(info.helpfile, "");
if ((info.dependentfiles=(fstring *)malloc(2*sizeof(fstring))) == NULL)
- return ERRnomem;
+ return WERR_NOMEM;
memset(info.dependentfiles, '\0', 2*sizeof(fstring));
fstrcpy(info.dependentfiles[0], "");
*info_ptr = memdup(&info, sizeof(info));
- return 0;
+ return WERR_OK;
}
/****************************************************************************
#if 0
if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
#else
- if (!dbuf.dptr) return 5;
+ if (!dbuf.dptr) return WERR_ACCESS_DENIED;
#endif
len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
&driver.cversion,
i=0;
while (len < dbuf.dsize) {
fstring *tddfs;
-
+
tddfs = (fstring *)Realloc(driver.dependentfiles,
sizeof(fstring)*(i+2));
if (tddfs == NULL) {
if (driver.dependentfiles != NULL)
fstrcpy(driver.dependentfiles[i], "");
- safe_free(dbuf.dptr);
+ SAFE_FREE(dbuf.dptr);
if (len != dbuf.dsize) {
- if (driver.dependentfiles != NULL)
- 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]);
}
- free(info3);
+ SAFE_FREE(info3);
return True;
}
/****************************************************************************
-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;
}
/* FIXME!!! Reorder so this forward declaration is not necessary --jerry */
-static uint32 get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
+static WERROR get_a_printer_2(NT_PRINTER_INFO_LEVEL_2 **, fstring);
static void free_nt_printer_info_level_2(NT_PRINTER_INFO_LEVEL_2 **);
/****************************************************************************
****************************************************************************/
-static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
+static WERROR update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info)
{
pstring key;
char *buf;
- int buflen, len, ret;
+ int buflen, len;
+ WERROR ret;
TDB_DATA kbuf, dbuf;
/*
if (buflen != len) {
char *tb;
-
+
tb = (char *)Realloc(buf, len);
if (!tb) {
DEBUG(0,("update_a_printer_2: failed to enlarge buffer!\n"));
- ret = -1;
+ ret = WERR_NOMEM;
goto done;
}
else buf = tb;
dbuf.dptr = buf;
dbuf.dsize = len;
- ret = tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
+ ret = (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) == 0? WERR_OK : WERR_NOMEM);
done:
- if (ret == -1)
+ if (!W_ERROR_IS_OK(ret))
DEBUG(8, ("error updating printer to tdb on disk\n"));
- safe_free(buf);
+ SAFE_FREE(buf);
DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n",
info->sharename, info->drivername, info->portname, len));
(strlen(current->value)==strlen(param->value)) ) {
DEBUG(109,("deleting first value\n"));
info_2->specific=current->next;
- safe_free(current->data);
- safe_free(current);
+ SAFE_FREE(current->data);
+ SAFE_FREE(current);
DEBUG(109,("deleted first value\n"));
return (True);
}
strlen(current->value)==strlen(param->value) ) {
DEBUG(109,("deleting current value\n"));
previous->next=current->next;
- safe_free(current->data);
- safe_free(current);
+ SAFE_FREE(current->data);
+ SAFE_FREE(current);
DEBUG(109,("deleted current value\n"));
return(True);
}
DEBUG(106,("free_nt_printer_param: deleting param [%s]\n", param->value));
- if(param->data)
- safe_free(param->data);
-
- safe_free(param);
- *param_ptr = NULL;
+ 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));
nt_devmode->paperlength = 0;
nt_devmode->paperwidth = 0;
nt_devmode->scale = 0x64;
- nt_devmode->copies = 01;
+ nt_devmode->copies = 1;
nt_devmode->defaultsource = BIN_FORMSOURCE;
nt_devmode->printquality = RES_HIGH; /* 0x0258 */
nt_devmode->color = COLOR_MONOCHROME;
new_nt_devicemode->private = NULL;
if (nt_devicemode->private != NULL) {
if ((new_nt_devicemode->private = memdup(nt_devicemode->private, nt_devicemode->driverextra)) == NULL) {
- safe_free(new_nt_devicemode);
+ SAFE_FREE(new_nt_devicemode);
DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
return NULL;
}
DEBUG(106,("free_nt_devicemode: deleting DEVMODE\n"));
- if(nt_devmode->private)
- safe_free(nt_devmode->private);
-
- safe_free(nt_devmode);
- *devmode_ptr = NULL;
+ SAFE_FREE(nt_devmode->private);
+ SAFE_FREE(*devmode_ptr);
}
/****************************************************************************
free_nt_printer_param(&tofree);
}
- safe_free(*info_ptr);
- *info_ptr = NULL;
+ SAFE_FREE(*info_ptr);
}
/****************************************************************************
get a default printer info 2 struct
****************************************************************************/
-static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
+static WERROR get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstring sharename)
{
- extern pstring global_myname;
int snum;
NT_PRINTER_INFO_LEVEL_2 info;
snum = lp_servicenumber(sharename);
- slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", global_myname);
+ slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
slprintf(info.printername, sizeof(info.printername)-1, "\\\\%s\\%s",
- global_myname, sharename);
+ get_called_name(), sharename);
fstrcpy(info.sharename, sharename);
fstrcpy(info.portname, SAMBA_PRINTER_PORT_NAME);
fstrcpy(info.drivername, lp_printerdriver(snum));
-#if 0 /* JERRY */
- if (!*info.drivername)
- fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
-#else
/* by setting the driver name to an empty string, a local NT admin
can now run the **local** APW to install a local printer driver
for a Samba shared printer in 2.2. Without this, drivers **must** be
installed on the Samba server for NT clients --jerry */
+#if 0 /* JERRY --do not uncomment-- */
if (!*info.drivername)
- fstrcpy(info.drivername, "");
+ fstrcpy(info.drivername, "NO DRIVER AVAILABLE FOR THIS PRINTER");
#endif
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.default_priority = 1;
info.setuptime = (uint32)time(NULL);
-#if 1 /* 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.
+ * 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 ((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 ! */
goto fail;
}
- return (0);
+ return WERR_OK;
fail:
-
if (info.devmode)
free_nt_devicemode(&info.devmode);
- return 2;
+ return WERR_ACCESS_DENIED;
}
/****************************************************************************
{
pstring key;
NT_PRINTER_INFO_LEVEL_2 info;
- int len = 0;
+ int len = 0;
TDB_DATA kbuf, dbuf;
fstring printername;
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", global_myname);
- slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", global_myname,
+ slprintf(info.servername, sizeof(info.servername)-1, "\\\\%s", get_called_name());
+ slprintf(printername, sizeof(printername)-1, "\\\\%s\\%s", get_called_name(),
info.printername);
fstrcpy(info.printername, printername);
len += unpack_devicemode(&info.devmode,dbuf.dptr+len, dbuf.dsize-len);
+
+ /*
+ * 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 (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);
+ }
+
len += unpack_specifics(&info.specific,dbuf.dptr+len, dbuf.dsize-len);
/* This will get the current RPC talloc context, but we should be
if (get_remote_arch() == RA_OS2)
map_to_os2_driver(info.drivername);
- safe_free(dbuf.dptr);
+ SAFE_FREE(dbuf.dptr);
*info_ptr=memdup(&info, sizeof(info));
DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
break;
}
default:
- DEBUGADD(1,("Level not implemented\n"));
+ DEBUGADD(106,("dump_a_printer: Level %u not implemented\n", (unsigned int)level ));
result=1;
break;
}
**printername = **sharename = **portname = '\0';
- if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
+ if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
return;
fstrcpy(*printername, printer->info_2->printername);
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.
Modify a printer. This is called from SETPRINTERDATA/DELETEPRINTERDATA.
****************************************************************************/
-uint32 mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
+WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
{
- uint32 result;
+ WERROR result;
dump_a_printer(printer, level);
{
case 2:
{
- printer.info_2->c_setprinter++;
- result=update_a_printer_2(printer.info_2);
- break;
- }
- default:
- result=1;
- break;
- }
-
- return result;
-}
+ /*
+ * Update the changestamp. Emperical tests show that the
+ * ChangeID is always updated,but c_setprinter is
+ * global spooler variable (not per printer).
+ */
-/****************************************************************************
- 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.
-****************************************************************************/
+ /* ChangeID **must** be increasing over the lifetime
+ of client's spoolss service in order for the
+ client's cache to show updates */
+
+ printer.info_2->changeid = rev_changeid();
-uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
-{
- uint32 result;
-
- dump_a_printer(printer, level);
-
- switch (level)
- {
- case 2:
- {
/*
- * Update the changestamp.
- * Note we must *not* do this in mod_a_printer().
+ * Because one day someone will ask:
+ * NT->NT An admin connection to a remote
+ * printer show changes imeediately in
+ * the properities dialog
+ *
+ * A non-admin connection will only show the
+ * changes after viewing the properites page
+ * 2 times. Seems to be related to a
+ * race condition in the client between the spooler
+ * updating the local cache and the Explorer.exe GUI
+ * actually displaying the properties.
+ *
+ * This is fixed in Win2k. admin/non-admin
+ * connections both display changes immediately.
+ *
+ * 14/12/01 --jerry
*/
- NTTIME time_nt;
- time_t time_unix = time(NULL);
- unix_to_nt_time(&time_nt, time_unix);
- if (printer.info_2->changeid==time_nt.low)
- printer.info_2->changeid++;
- else
- printer.info_2->changeid=time_nt.low;
-
- printer.info_2->c_setprinter++;
result=update_a_printer_2(printer.info_2);
break;
}
default:
- result=1;
+ result=WERR_UNKNOWN_LEVEL;
break;
}
/****************************************************************************
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
*/
len += unpack_specifics(&info_ptr->specific,dbuf.dptr+len, dbuf.dsize-len);
- safe_free(dbuf.dptr);
+ SAFE_FREE(dbuf.dptr);
return True;
}
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"));
if (ret == -1)
DEBUG(8, ("update_driver_init_2: error updating printer init to tdb on disk\n"));
- safe_free(buf);
+ SAFE_FREE(buf);
DEBUG(10,("update_driver_init_2: Saved printer [%s] init DEVMODE & specifics for driver [%s]\n",
info->sharename, info->drivername));
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;
about it and you will realize why. JRR 010720
****************************************************************************/
-static uint32 save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
+static WERROR save_driver_init_2(NT_PRINTER_INFO_LEVEL *printer, NT_PRINTER_PARAM *param)
{
- uint32 status = ERRsuccess;
+ WERROR status = WERR_OK;
TALLOC_CTX *ctx = NULL;
NT_DEVICEMODE *nt_devmode = NULL;
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 ERRnomem;
- if ((nt_devmode = (NT_DEVICEMODE*)malloc(sizeof(NT_DEVICEMODE))) == NULL) {
- status = ERRnomem;
- 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 = ERRinvalidparam;
- 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 = ERRnomem;
+ status = WERR_NOMEM;
goto done;
}
* printer to match it. This allows initialization of the current printer
* as well as the driver.
*/
- if (mod_a_printer(*printer, 2)!=0) {
+ status = mod_a_printer(*printer, 2);
+ if (!W_ERROR_IS_OK(status)) {
DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
printer->info_2->printername));
- status = ERRinvalidparam;
}
+
+#if 0 /* JERRY */
+ srv_spoolss_sendnotify(p, handle);
+#endif
done:
talloc_destroy(ctx);
if (nt_devmode)
- safe_free(nt_devmode->private);
- safe_free(nt_devmode);
+ SAFE_FREE(nt_devmode->private);
+ SAFE_FREE(nt_devmode);
printer->info_2->devmode = tmp_devmode;
return status;
Update the driver init info (DEVMODE and specifics) for a printer
****************************************************************************/
-uint32 save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
+WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, NT_PRINTER_PARAM *param)
{
- NTSTATUS status = ERRsuccess;
+ WERROR status = WERR_OK;
switch (level)
{
break;
}
default:
- status=ERRunknownlevel;
+ status=WERR_UNKNOWN_LEVEL;
break;
}
{
if ((printer = (NT_PRINTER_INFO_LEVEL *)malloc(sizeof(NT_PRINTER_INFO_LEVEL))) == NULL) {
DEBUG(0,("get_a_printer: malloc fail.\n"));
- return 1;
+ return WERR_NOMEM;
}
ZERO_STRUCTP(printer);
result=get_a_printer_2(&printer->info_2, sharename);
- if (result == 0) {
+ if (W_ERROR_IS_OK(result)) {
dump_a_printer(*printer, level);
*pp_printer = printer;
} else {
- safe_free(printer);
+ SAFE_FREE(printer);
}
break;
}
default:
- result=W_ERROR(1);
+ result=WERR_UNKNOWN_LEVEL;
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;
}
break;
}
- safe_free(printer);
- *pp_printer = NULL;
+ SAFE_FREE(*pp_printer);
return result;
}
break;
}
- if (result == 0)
+ if (W_ERROR_IS_OK(result))
dump_a_printer_driver(*driver, level);
return result;
}
if (driver.info_3 != NULL)
{
info3=driver.info_3;
- safe_free(info3->dependentfiles);
+ SAFE_FREE(info3->dependentfiles);
ZERO_STRUCTP(info3);
- safe_free(info3);
+ SAFE_FREE(info3);
result=0;
}
else
if (driver.info_6 != NULL)
{
info6=driver.info_6;
- safe_free(info6->dependentfiles);
- safe_free(info6->previousnames);
+ SAFE_FREE(info6->dependentfiles);
+ SAFE_FREE(info6->previousnames);
ZERO_STRUCTP(info6);
- safe_free(info6);
+ SAFE_FREE(info6);
result=0;
}
else
info.datatype,
info.parameters);
- safe_free(dbuf.dptr);
+ SAFE_FREE(dbuf.dptr);
if (ret == -1) {
DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
Remove a printer driver from the TDB. This assumes that the the driver was
previously looked up.
***************************************************************************/
-NTSTATUS delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
+WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
{
pstring key;
fstring arch;
if (tdb_delete(tdb_drivers, kbuf) == -1) {
DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
- return NT_STATUS_ACCESS_VIOLATION;
+ return WERR_ACCESS_DENIED;
}
DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
i->name));
- return NT_STATUS_OK;
+ return WERR_OK;
}
/****************************************************************************
****************************************************************************/
slprintf(key, sizeof(key)-1, "SECDESC/%s", printername);
if (tdb_prs_store(tdb_printers, key, &ps)==0) {
- status = 0;
+ status = WERR_OK;
} else {
DEBUG(1,("Failed to store secdesc for %s\n", printername));
status = WERR_BADFUNC;
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);
return False;
}
+ /* Save default security descriptor for later */
+
+ 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);
+
+ 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;
for (i = 0; i < the_acl->num_aces; i++) {
fstring sid_str;
- sid_to_string(sid_str, &the_acl->ace[i].sid);
+ sid_to_string(sid_str, &the_acl->ace[i].trustee);
DEBUG(10, ("%s %d %d 0x%08x\n", sid_str,
the_acl->ace[i].type, the_acl->ace[i].flags,
BOOL print_access_check(struct current_user *user, int snum, int access_type)
{
SEC_DESC_BUF *secdesc = NULL;
- uint32 access_granted, status;
+ uint32 access_granted;
+ NTSTATUS status;
BOOL result;
char *pname;
TALLOC_CTX *mem_ctx = NULL;
/* If user is NULL then use the current_user structure */
- if (!user) user = ¤t_user;
+ if (!user)
+ user = ¤t_user;
/* Always allow root or printer admins to do anything */
map_printer_permissions(secdesc->sec);
- result = se_access_check(secdesc->sec, user, access_type,
+ result = se_access_check(secdesc->sec, user->nt_user_token, access_type,
&access_granted, &status);
DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
struct tm *t;
uint32 mins;
- if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
+ if (!W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))))
return False;
if (printer->info_2->starttime == 0 && printer->info_2->untiltime == 0)
return ok;
}
+#if 0 /* JERRY - not used */
/****************************************************************************
Attempt to write a default device.
*****************************************************************************/
-uint32 printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
+WERROR printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default)
{
NT_PRINTER_INFO_LEVEL *printer = NULL;
-
- uint32 result = 0;
+ WERROR result;
/*
* Don't bother if no default devicemode was sent.
*/
if (printer_default->devmode_cont.devmode == NULL)
- return 0;
+ return WERR_OK;
- if (get_a_printer(&printer, 2, lp_servicename(snum))!=0)
- return ERRnoaccess;
+ result = get_a_printer(&printer, 2, lp_servicename(snum));
+ if (!W_ERROR_IS_OK(result)) return result;
/*
* Just ignore it if we already have a devmode.
if ( (printer_default->access_required & PRINTER_ACCESS_ADMINISTER) !=
PRINTER_ACCESS_ADMINISTER) {
DEBUG(5,("printer_write_default_dev: invalid request access to update: %x\n", printer_default->access_required));
- result = ERRnoaccess;
+ result = WERR_ACCESS_DENIED;
goto done;
}
if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n",
lp_servicename(snum) ));
- result = ERRnoaccess;
+ result = WERR_ACCESS_DENIED;
/*result = NT_STATUS_NO_PROBLEMO;*/
goto done;
}
if (!convert_devicemode(printer->info_2->printername,
printer_default->devmode_cont.devmode,
&printer->info_2->devmode)) {
- result = ERRnomem;
+ result = WERR_NOMEM;
goto done;
}
* Finally write back to the tdb.
*/
- if (add_a_printer(*printer, 2)!=0) {
- result = ERRnoaccess;
- goto done;
- }
+ result = mod_a_printer(*printer, 2);
done:
free_a_printer(&printer, 2);
return result;
}
+#endif /* JERRY */