#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 */
{"PRC Envelope #10 Rotated",0x1,0x6fd10,0x4f1a0,0x0,0x0,0x6fd10,0x4f1a0}
};
-struct table_node {
- const char *long_archi;
- const char *short_archi;
- int version;
-};
-
-#define SPL_ARCH_WIN40 "WIN40"
-#define SPL_ARCH_W32X86 "W32X86"
-#define SPL_ARCH_W32MIPS "W32MIPS"
-#define SPL_ARCH_W32ALPHA "W32ALPHA"
-#define SPL_ARCH_W32PPC "W32PPC"
-#define SPL_ARCH_IA64 "IA64"
-#define SPL_ARCH_X64 "x64"
-
-static const struct table_node archi_table[]= {
+static const struct print_architecture_table_node archi_table[]= {
{"Windows 4.0", SPL_ARCH_WIN40, 0 },
{"Windows NT x86", SPL_ARCH_W32X86, 2 },
static bool upgrade_to_version_3(void)
{
TDB_DATA kbuf, newkey, dbuf;
-
+
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), free(kbuf.dptr), kbuf=newkey) {
return False;
}
}
-
+
if (strncmp((const char *)kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) == 0) {
DEBUG(0,("upgrade_to_version_3:moving printer\n"));
if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
return False;
}
}
-
+
if (strncmp((const char *)kbuf.dptr, SECDESC_PREFIX, strlen(SECDESC_PREFIX)) == 0) {
DEBUG(0,("upgrade_to_version_3:moving secdesc\n"));
if (tdb_store(tdb_printers, kbuf, dbuf, TDB_REPLACE) != 0) {
return False;
}
}
-
+
SAFE_FREE(dbuf.dptr);
}
}
/*******************************************************************
- Fix an issue with security descriptors. Printer sec_desc must
- use more than the generic bits that were previously used
+ Fix an issue with security descriptors. Printer sec_desc must
+ use more than the generic bits that were previously used
in <= 3.0.14a. They must also have a owner and group SID assigned.
- Otherwise, any printers than have been migrated to a Windows
+ Otherwise, any printers than have been migrated to a Windows
host using printmig.exe will not be accessible.
*******************************************************************/
static int sec_desc_upg_fn( TDB_CONTEXT *the_tdb, TDB_DATA key,
TDB_DATA data, void *state )
{
- prs_struct ps;
+ NTSTATUS status;
SEC_DESC_BUF *sd_orig = NULL;
SEC_DESC_BUF *sd_new, *sd_store;
SEC_DESC *sec, *new_sec;
/* upgrade the security descriptor */
- ZERO_STRUCT( ps );
-
- prs_init_empty( &ps, ctx, UNMARSHALL );
- prs_give_memory( &ps, (char *)data.dptr, data.dsize, False );
-
- if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_orig, &ps, 1 ) ) {
+ status = unmarshall_sec_desc_buf(ctx, data.dptr, data.dsize, &sd_orig);
+ if (!NT_STATUS_IS_OK(status)) {
/* delete bad entries */
DEBUG(0,("sec_desc_upg_fn: Failed to parse original sec_desc for %si. Deleting....\n",
(const char *)key.dptr ));
tdb_delete( tdb_printers, key );
- prs_mem_free( &ps );
return 0;
}
if (!sd_orig) {
- prs_mem_free( &ps );
return 0;
}
sec = sd_orig->sd;
-
+
/* is this even valid? */
-
+
if ( !sec->dacl ) {
- prs_mem_free( &ps );
return 0;
}
-
+
/* update access masks */
-
+
for ( i=0; i<sec->dacl->num_aces; i++ ) {
switch ( sec->dacl->aces[i].access_mask ) {
case (GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS):
sec->dacl->aces[i].access_mask = PRINTER_ACE_PRINT;
break;
-
+
case GENERIC_ALL_ACCESS:
sec->dacl->aces[i].access_mask = PRINTER_ACE_FULL_CONTROL;
break;
-
+
case READ_CONTROL_ACCESS:
sec->dacl->aces[i].access_mask = PRINTER_ACE_MANAGE_DOCUMENTS;
-
+
default: /* no change */
break;
}
&global_sid_Builtin_Administrators,
NULL, NULL, &size_new_sec );
if (!new_sec) {
- prs_mem_free( &ps );
return 0;
}
sd_new = make_sec_desc_buf( ctx, size_new_sec, new_sec );
if (!sd_new) {
- prs_mem_free( &ps );
return 0;
}
if ( !(sd_store = sec_desc_merge( ctx, sd_new, sd_orig )) ) {
DEBUG(0,("sec_desc_upg_fn: Failed to update sec_desc for %s\n", key.dptr ));
- prs_mem_free( &ps );
return 0;
}
-
- prs_mem_free( &ps );
/* store it back */
-
- sd_size = ndr_size_security_descriptor(sd_store->sd, 0)
+
+ sd_size = ndr_size_security_descriptor(sd_store->sd, NULL, 0)
+ sizeof(SEC_DESC_BUF);
- if ( !prs_init(&ps, sd_size, ctx, MARSHALL) ) {
- DEBUG(0,("sec_desc_upg_fn: Failed to allocate prs memory for %s\n", key.dptr ));
- return 0;
- }
- if ( !sec_io_desc_buf( "sec_desc_upg_fn", &sd_store, &ps, 1 ) ) {
+ status = marshall_sec_desc_buf(ctx, sd_store, &data.dptr, &data.dsize);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("sec_desc_upg_fn: Failed to parse new sec_desc for %s\n", key.dptr ));
- prs_mem_free( &ps );
return 0;
}
- data.dptr = (uint8 *)prs_data_p( &ps );
- data.dsize = sd_size;
-
result = tdb_store( tdb_printers, key, data, TDB_REPLACE );
- prs_mem_free( &ps );
-
/* 0 to continue and non-zero to stop traversal */
return (result == -1);
DEBUG(0,("upgrade_to_version_4: upgrading printer security descriptors\n"));
- if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
+ if ( !(ctx = talloc_init( "upgrade_to_version_4" )) )
return False;
result = tdb_traverse( tdb_printers, sec_desc_upg_fn, ctx );
}
/*******************************************************************
- Fix an issue with security descriptors. Printer sec_desc must
- use more than the generic bits that were previously used
+ Fix an issue with security descriptors. Printer sec_desc must
+ use more than the generic bits that were previously used
in <= 3.0.14a. They must also have a owner and group SID assigned.
- Otherwise, any printers than have been migrated to a Windows
+ Otherwise, any printers than have been migrated to a Windows
host using printmig.exe will not be accessible.
*******************************************************************/
/* delete the original record and store under the normalized key */
if ( tdb_delete( the_tdb, key ) != 0 ) {
- DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
+ DEBUG(0,("normalize_printers_fn: tdb_delete for [%s] failed!\n",
key.dptr));
return 1;
}
DEBUG(0,("upgrade_to_version_5: normalizing printer keys\n"));
- if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
+ if ( !(ctx = talloc_init( "upgrade_to_version_5" )) )
return False;
result = tdb_traverse( tdb_printers, normalize_printers_fn, NULL );
if ( tdb_drivers && tdb_printers && tdb_forms )
return True;
-
+
if (tdb_drivers)
tdb_close(tdb_drivers);
tdb_drivers = tdb_open_log(state_path("ntdrivers.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
state_path("ntdrivers.tdb"), strerror(errno) ));
return False;
}
-
+
if (tdb_printers)
tdb_close(tdb_printers);
tdb_printers = tdb_open_log(state_path("ntprinters.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
state_path("ntprinters.tdb"), strerror(errno) ));
return False;
}
-
+
if (tdb_forms)
tdb_close(tdb_forms);
tdb_forms = tdb_open_log(state_path("ntforms.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
state_path("ntforms.tdb"), strerror(errno) ));
return False;
}
-
+
/* handle a Samba upgrade */
-
+
vers_id = tdb_fetch_int32(tdb_drivers, vstring);
if (vers_id == -1) {
DEBUG(10, ("Fresh database\n"));
if ( vers_id != NTDRIVERS_DATABASE_VERSION_5 ) {
- if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
+ if ((vers_id == NTDRIVERS_DATABASE_VERSION_1) || (IREV(vers_id) == NTDRIVERS_DATABASE_VERSION_1)) {
if (!upgrade_to_version_3())
return False;
tdb_store_int32(tdb_drivers, vstring, NTDRIVERS_DATABASE_VERSION_3);
vers_id = NTDRIVERS_DATABASE_VERSION_3;
- }
-
+ }
+
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. */
return False;
}
}
-
+
update_c_setprinter(True);
/*
reset_all_printerdata);
/* of course, none of the message callbacks matter if you don't
- tell messages.c that you interested in receiving PRINT_GENERAL
+ tell messages.c that you interested in receiving PRINT_GENERAL
msgs. This is done in claim_connection() */
Function to allow filename parsing "the old way".
********************************************************************/
-static char *driver_unix_convert(connection_struct *conn,
- const char *old_name,
- SMB_STRUCT_STAT *pst)
+static NTSTATUS driver_unix_convert(connection_struct *conn,
+ const char *old_name,
+ struct smb_filename **smb_fname)
{
+ NTSTATUS status;
TALLOC_CTX *ctx = talloc_tos();
char *name = talloc_strdup(ctx, old_name);
- char *new_name = NULL;
if (!name) {
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
unix_format(name);
name = unix_clean_name(ctx, name);
if (!name) {
- return NULL;
+ return NT_STATUS_NO_MEMORY;
}
trim_string(name,"/","/");
- unix_convert(ctx,conn, name, false, &new_name, NULL, pst);
- return new_name;
+
+ status = unix_convert(ctx, conn, name, smb_fname, 0);
+ if (!NT_STATUS_IS_OK(status)) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return NT_STATUS_OK;
}
/*******************************************************************
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
{
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
*/
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;
}
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;
}
if (!*list) {
return 0;
}
- return sizeof(default_forms) / sizeof(default_forms[0]);
+ return ARRAY_SIZE(default_forms);
}
/****************************************************************************
get a builtin form struct
****************************************************************************/
-bool get_a_builtin_ntform(UNISTR2 *uni_formname,nt_forms_struct *form)
+bool get_a_builtin_ntform_by_string(const char *form_name, nt_forms_struct *form)
{
- int i,count;
- fstring form_name;
- unistr2_to_ascii(form_name, uni_formname, sizeof(form_name));
+ int i;
DEBUGADD(6,("Looking for builtin form %s \n", form_name));
- count = sizeof(default_forms) / sizeof(default_forms[0]);
- for (i=0;i<count;i++) {
+ for (i=0; i<ARRAY_SIZE(default_forms); i++) {
if (strequal(form_name,default_forms[i].name)) {
DEBUGADD(6,("Found builtin form %s \n", form_name));
memcpy(form,&default_forms[i],sizeof(*form));
- break;
+ return true;
}
}
- return (i !=count);
+ return false;
}
/****************************************************************************
for (kbuf = tdb_firstkey(tdb_forms);
kbuf.dptr;
- newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
+ newkey = tdb_nextkey(tdb_forms, kbuf), free(kbuf.dptr), kbuf=newkey)
{
- if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
+ if (strncmp((const char *)kbuf.dptr, FORMS_PREFIX, strlen(FORMS_PREFIX)) != 0)
continue;
-
+
dbuf = tdb_fetch(tdb_forms, kbuf);
- if (!dbuf.dptr)
+ if (!dbuf.dptr)
continue;
fstrcpy(form.name, (const char *)kbuf.dptr+strlen(FORMS_PREFIX));
&i, &form.flag, &form.width, &form.length, &form.left,
&form.top, &form.right, &form.bottom);
SAFE_FREE(dbuf.dptr);
- if (ret != dbuf.dsize)
+ if (ret != dbuf.dsize)
continue;
*list = SMB_REALLOC_ARRAY(*list, nt_forms_struct, n+1);
(*list)[n] = form;
n++;
}
-
+
return n;
}
/****************************************************************************
add a form struct at the end of the list
****************************************************************************/
-bool add_a_form(nt_forms_struct **list, const FORM *form, int *count)
+bool add_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int *count)
{
int n=0;
bool update;
- fstring form_name;
/*
* NT tries to add forms even when
*/
update=False;
-
- unistr2_to_ascii(form_name, &form->name, sizeof(form_name));
+
for (n=0; n<*count; n++) {
- if ( strequal((*list)[n].name, form_name) ) {
+ if ( strequal((*list)[n].name, form->form_name) ) {
update=True;
break;
}
DEBUG(0,("add_a_form: failed to enlarge forms list!\n"));
return False;
}
- unistr2_to_ascii((*list)[n].name, &form->name, sizeof((*list)[n].name));
+ fstrcpy((*list)[n].name, form->form_name);
(*count)++;
}
-
- (*list)[n].flag=form->flags;
- (*list)[n].width=form->size_x;
- (*list)[n].length=form->size_y;
- (*list)[n].left=form->left;
- (*list)[n].top=form->top;
- (*list)[n].right=form->right;
- (*list)[n].bottom=form->bottom;
- DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
- update ? "updated" : "added", form_name));
+ (*list)[n].flag = form->flags;
+ (*list)[n].width = form->size.width;
+ (*list)[n].length = form->size.height;
+ (*list)[n].left = form->area.left;
+ (*list)[n].top = form->area.top;
+ (*list)[n].right = form->area.right;
+ (*list)[n].bottom = form->area.bottom;
+
+ DEBUG(6,("add_a_form: Successfully %s form [%s]\n",
+ update ? "updated" : "added", form->form_name));
return True;
}
Delete a named form struct.
****************************************************************************/
-bool delete_a_form(nt_forms_struct **list, UNISTR2 *del_name, int *count, WERROR *ret)
+bool delete_a_form(nt_forms_struct **list, const char *del_name, int *count, WERROR *ret)
{
char *key = NULL;
int n=0;
- fstring form_name;
*ret = WERR_OK;
- unistr2_to_ascii(form_name, del_name, sizeof(form_name));
-
for (n=0; n<*count; n++) {
- if (!strncmp((*list)[n].name, form_name, strlen(form_name))) {
- DEBUG(103, ("delete_a_form, [%s] in list\n", form_name));
+ if (!strncmp((*list)[n].name, del_name, strlen(del_name))) {
+ DEBUG(103, ("delete_a_form, [%s] in list\n", del_name));
break;
}
}
if (n == *count) {
- DEBUG(10,("delete_a_form, [%s] not found\n", form_name));
+ DEBUG(10,("delete_a_form, [%s] not found\n", del_name));
*ret = WERR_INVALID_PARAM;
return False;
}
Update a form struct.
****************************************************************************/
-void update_a_form(nt_forms_struct **list, const FORM *form, int count)
+void update_a_form(nt_forms_struct **list, struct spoolss_AddFormInfo1 *form, int count)
{
int n=0;
- fstring form_name;
- unistr2_to_ascii(form_name, &(form->name), sizeof(form_name));
- DEBUG(106, ("[%s]\n", form_name));
+ DEBUG(106, ("[%s]\n", form->form_name));
for (n=0; n<count; n++) {
DEBUGADD(106, ("n [%d]:[%s]\n", n, (*list)[n].name));
- if (!strncmp((*list)[n].name, form_name, strlen(form_name)))
+ if (!strncmp((*list)[n].name, form->form_name, strlen(form->form_name)))
break;
}
if (n==count) return;
- (*list)[n].flag=form->flags;
- (*list)[n].width=form->size_x;
- (*list)[n].length=form->size_y;
- (*list)[n].left=form->left;
- (*list)[n].top=form->top;
- (*list)[n].right=form->right;
- (*list)[n].bottom=form->bottom;
+ (*list)[n].flag = form->flags;
+ (*list)[n].width = form->size.width;
+ (*list)[n].length = form->size.height;
+ (*list)[n].left = form->area.left;
+ (*list)[n].top = form->area.top;
+ (*list)[n].right = form->area.right;
+ (*list)[n].bottom = form->area.bottom;
}
/****************************************************************************
static int file_version_is_newer(connection_struct *conn, fstring new_file, fstring old_file)
{
bool use_version = true;
- char *filepath = NULL;
uint32 new_major;
uint32 new_minor;
uint32 old_minor;
time_t old_create_time;
+ struct smb_filename *smb_fname = NULL;
files_struct *fsp = NULL;
SMB_STRUCT_STAT st;
- SMB_STRUCT_STAT stat_buf;
NTSTATUS status;
+ int ret;
SET_STAT_INVALID(st);
- SET_STAT_INVALID(stat_buf);
new_create_time = (time_t)0;
old_create_time = (time_t)0;
/* Get file version info (if available) for previous file (if it exists) */
- filepath = driver_unix_convert(conn,old_file,&stat_buf);
- if (!filepath) {
+ status = driver_unix_convert(conn, old_file, &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
goto error_exit;
}
- status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
- FILE_GENERIC_READ,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- INTERNAL_OPEN_ONLY,
- NULL, &fsp);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ NULL, /* req */
+ 0, /* root_dir_fid */
+ smb_fname, /* fname */
+ FILE_GENERIC_READ, /* access_mask */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
+ FILE_OPEN, /* create_disposition*/
+ 0, /* create_options */
+ FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+ INTERNAL_OPEN_ONLY, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ NULL); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
/* Old file not found, so by definition new file is in fact newer */
- DEBUG(10,("file_version_is_newer: Can't open old file [%s], errno = %d\n",
- filepath, errno));
- return 1;
+ DEBUG(10,("file_version_is_newer: Can't open old file [%s], "
+ "errno = %d\n", smb_fname_str_dbg(smb_fname),
+ errno));
+ ret = 1;
+ goto done;
} else {
- int ret = get_file_version(fsp, old_file, &old_major, &old_minor);
+ ret = get_file_version(fsp, old_file, &old_major, &old_minor);
if (ret == -1) {
goto error_exit;
}
if (SMB_VFS_FSTAT(fsp, &st) == -1) {
goto error_exit;
}
- old_create_time = st.st_mtime;
- DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", old_create_time));
+ old_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
+ DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
+ (long)old_create_time));
}
}
close_file(NULL, fsp, NORMAL_CLOSE);
fsp = NULL;
/* Get file version info (if available) for new file */
- filepath = driver_unix_convert(conn,new_file,&stat_buf);
- if (!filepath) {
+ status = driver_unix_convert(conn, new_file, &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
goto error_exit;
}
- status = open_file_ntcreate(conn, NULL, filepath, &stat_buf,
- FILE_GENERIC_READ,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- INTERNAL_OPEN_ONLY,
- NULL, &fsp);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ NULL, /* req */
+ 0, /* root_dir_fid */
+ smb_fname, /* fname */
+ FILE_GENERIC_READ, /* access_mask */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
+ FILE_OPEN, /* create_disposition*/
+ 0, /* create_options */
+ FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+ INTERNAL_OPEN_ONLY, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ NULL); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
/* New file not found, this shouldn't occur if the caller did its job */
- DEBUG(3,("file_version_is_newer: Can't open new file [%s], errno = %d\n",
- filepath, errno));
+ DEBUG(3,("file_version_is_newer: Can't open new file [%s], "
+ "errno = %d\n", smb_fname_str_dbg(smb_fname), errno));
goto error_exit;
} else {
- int ret = get_file_version(fsp, new_file, &new_major, &new_minor);
+ ret = get_file_version(fsp, new_file, &new_major, &new_minor);
if (ret == -1) {
goto error_exit;
}
if (SMB_VFS_FSTAT(fsp, &st) == -1) {
goto error_exit;
}
- new_create_time = st.st_mtime;
- DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n", new_create_time));
+ new_create_time = convert_timespec_to_time_t(st.st_ex_mtime);
+ DEBUGADD(6,("file_version_is_newer: mod time = %ld sec\n",
+ (long)new_create_time));
}
}
close_file(NULL, fsp, NORMAL_CLOSE);
(new_major == old_major && new_minor > old_minor)) {
DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
- return 1;
+ ret = 1;
+ goto done;
}
else {
DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
- return 0;
+ ret = 0;
+ goto done;
}
} else {
/* Compare modification time/dates and choose the newest time/date */
if (new_create_time > old_create_time) {
DEBUG(6,("file_version_is_newer: Replacing [%s] with [%s]\n", old_file, new_file));
- return 1;
+ ret = 1;
+ goto done;
}
else {
DEBUG(6,("file_version_is_newer: Leaving [%s] unchanged\n", old_file));
- return 0;
+ ret = 0;
+ goto done;
}
}
- error_exit:
- if(fsp)
- close_file(NULL, fsp, NORMAL_CLOSE);
- return -1;
+ error_exit:
+ if(fsp)
+ close_file(NULL, fsp, NORMAL_CLOSE);
+ ret = -1;
+ done:
+ TALLOC_FREE(smb_fname);
+ return ret;
}
/****************************************************************************
Determine the correct cVersion associated with an architecture and driver
****************************************************************************/
-static uint32 get_correct_cversion(const char *architecture, fstring driverpath_in,
- struct current_user *user, WERROR *perr)
+static uint32 get_correct_cversion(struct pipes_struct *p,
+ const char *architecture,
+ fstring driverpath_in,
+ WERROR *perr)
{
int cversion;
NTSTATUS nt_status;
- char *driverpath = NULL;
- DATA_BLOB null_pw;
- fstring res_type;
+ struct smb_filename *smb_fname = NULL;
+ char *driverpath = NULL;
files_struct *fsp = NULL;
- SMB_STRUCT_STAT st;
- connection_struct *conn;
+ connection_struct *conn = NULL;
NTSTATUS status;
-
- SET_STAT_INVALID(st);
+ char *oldcwd;
+ fstring printdollar;
+ int printdollar_snum;
*perr = WERR_INVALID_PARAM;
return 3;
}
- /*
- * 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.
- */
+ fstrcpy(printdollar, "print$");
- /* Null password is ok - we are already an authenticated user... */
- null_pw = data_blob_null;
- fstrcpy(res_type, "A:");
- become_root();
- conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
- unbecome_root();
-
- if (conn == NULL) {
- DEBUG(0,("get_correct_cversion: Unable to connect\n"));
- *perr = ntstatus_to_werror(nt_status);
+ printdollar_snum = find_service(printdollar);
+ if (printdollar_snum == -1) {
+ *perr = WERR_NO_SUCH_SHARE;
return -1;
}
- /* We are temporarily becoming the connection user. */
- if (!become_user(conn, user->vuid)) {
- DEBUG(0,("get_correct_cversion: Can't become user!\n"));
- *perr = WERR_ACCESS_DENIED;
+ nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
+ lp_pathname(printdollar_snum),
+ p->server_info, &oldcwd);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0,("get_correct_cversion: create_conn_struct "
+ "returned %s\n", nt_errstr(nt_status)));
+ *perr = ntstatus_to_werror(nt_status);
return -1;
}
goto error_exit;
}
- driverpath = driver_unix_convert(conn,driverpath,&st);
- if (!driverpath) {
- *perr = WERR_NOMEM;
+ nt_status = driver_unix_convert(conn, driverpath, &smb_fname);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ *perr = ntstatus_to_werror(nt_status);
goto error_exit;
}
- if (!vfs_file_exist(conn, driverpath, &st)) {
+ nt_status = vfs_file_exist(conn, smb_fname);
+ if (!NT_STATUS_IS_OK(nt_status)) {
*perr = WERR_BADFILE;
goto error_exit;
}
- status = open_file_ntcreate(conn, NULL, driverpath, &st,
- FILE_GENERIC_READ,
- FILE_SHARE_READ|FILE_SHARE_WRITE,
- FILE_OPEN,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- INTERNAL_OPEN_ONLY,
- NULL, &fsp);
+ status = SMB_VFS_CREATE_FILE(
+ conn, /* conn */
+ NULL, /* req */
+ 0, /* root_dir_fid */
+ smb_fname, /* fname */
+ FILE_GENERIC_READ, /* access_mask */
+ FILE_SHARE_READ | FILE_SHARE_WRITE, /* share_access */
+ FILE_OPEN, /* create_disposition*/
+ 0, /* create_options */
+ FILE_ATTRIBUTE_NORMAL, /* file_attributes */
+ INTERNAL_OPEN_ONLY, /* oplock_request */
+ 0, /* allocation_size */
+ NULL, /* sd */
+ NULL, /* ea_list */
+ &fsp, /* result */
+ NULL); /* pinfo */
if (!NT_STATUS_IS_OK(status)) {
- DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = %d\n",
- driverpath, errno));
+ DEBUG(3,("get_correct_cversion: Can't open file [%s], errno = "
+ "%d\n", smb_fname_str_dbg(smb_fname), errno));
*perr = WERR_ACCESS_DENIED;
goto error_exit;
} else {
uint32 major;
uint32 minor;
- int ret = get_file_version(fsp, driverpath, &major, &minor);
+ int ret;
+
+ ret = get_file_version(fsp, smb_fname->base_name, &major, &minor);
if (ret == -1) goto error_exit;
if (!ret) {
- DEBUG(6,("get_correct_cversion: Version info not found [%s]\n", driverpath));
+ DEBUG(6,("get_correct_cversion: Version info not "
+ "found [%s]\n",
+ smb_fname_str_dbg(smb_fname)));
goto error_exit;
}
/*
* This is a Microsoft'ism. See references in MSDN to VER_FILEVERSION
- * for more details. Version in this case is not just the version of the
+ * for more details. Version in this case is not just the version of the
* file, but the version in the sense of kernal mode (2) vs. user mode
- * (3) drivers. Other bits of the version fields are the version info.
+ * (3) drivers. Other bits of the version fields are the version info.
* JRR 010716
*/
cversion = major & 0x0000ffff;
case 2: /* WinNT drivers */
case 3: /* Win2K drivers */
break;
-
+
default:
- DEBUG(6,("get_correct_cversion: cversion invalid [%s] cversion = %d\n",
- driverpath, cversion));
+ DEBUG(6,("get_correct_cversion: cversion "
+ "invalid [%s] cversion = %d\n",
+ smb_fname_str_dbg(smb_fname),
+ cversion));
goto error_exit;
}
- DEBUG(10,("get_correct_cversion: Version info found [%s] major = 0x%x minor = 0x%x\n",
- driverpath, major, minor));
+ DEBUG(10,("get_correct_cversion: Version info found [%s] major"
+ " = 0x%x minor = 0x%x\n",
+ smb_fname_str_dbg(smb_fname), major, minor));
}
DEBUG(10,("get_correct_cversion: Driver file [%s] cversion = %d\n",
- driverpath, cversion));
-
- close_file(NULL, fsp, NORMAL_CLOSE);
- close_cnum(conn, user->vuid);
- unbecome_user();
- *perr = WERR_OK;
- return cversion;
-
+ smb_fname_str_dbg(smb_fname), cversion));
- error_exit:
+ goto done;
- if(fsp)
+ error_exit:
+ cversion = -1;
+ done:
+ TALLOC_FREE(smb_fname);
+ if (fsp != NULL) {
close_file(NULL, fsp, NORMAL_CLOSE);
-
- close_cnum(conn, user->vuid);
- unbecome_user();
- return -1;
+ }
+ if (conn != NULL) {
+ vfs_ChDir(conn, oldcwd);
+ conn_free(conn);
+ }
+ if (cversion != -1) {
+ *perr = WERR_OK;
+ }
+ return cversion;
}
/****************************************************************************
****************************************************************************/
-static WERROR clean_up_driver_struct_level_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver,
- struct current_user *user)
+static WERROR clean_up_driver_struct_level_3(struct pipes_struct *rpc_pipe,
+ NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver)
{
const char *architecture;
fstring new_name;
if (!architecture) {
return WERR_UNKNOWN_PRINTER_DRIVER;
}
-
+
/* jfm:7/16/2000 the client always sends the cversion=0.
* The server should check which version the driver is by reading
* the PE header of driver->driverpath.
* NT 4: cversion=2
* NT2K: cversion=3
*/
- if ((driver->cversion = get_correct_cversion( architecture, driver->driverpath, user, &err)) == -1)
+ if ((driver->cversion = get_correct_cversion(rpc_pipe, architecture,
+ driver->driverpath,
+ &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)
+static WERROR clean_up_driver_struct_level_6(struct pipes_struct *rpc_pipe,
+ NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
{
const char *architecture;
fstring new_name;
* NT2K: cversion=3
*/
- if ((driver->version = get_correct_cversion(architecture, driver->driverpath, user, &err)) == -1)
+ if ((driver->version = get_correct_cversion(rpc_pipe, architecture,
+ driver->driverpath,
+ &err)) == -1)
return err;
return WERR_OK;
/****************************************************************************
****************************************************************************/
-WERROR clean_up_driver_struct(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
- uint32 level, struct current_user *user)
+WERROR clean_up_driver_struct(struct pipes_struct *rpc_pipe,
+ NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
+ uint32 level)
{
switch (level) {
case 3:
{
NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
driver=driver_abstract.info_3;
- return clean_up_driver_struct_level_3(driver, user);
+ return clean_up_driver_struct_level_3(rpc_pipe,
+ driver);
}
case 6:
{
NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver;
driver=driver_abstract.info_6;
- return clean_up_driver_struct_level_6(driver, user);
+ return clean_up_driver_struct_level_6(rpc_pipe,
+ driver);
}
default:
return WERR_INVALID_PARAM;
/****************************************************************************
****************************************************************************/
-WERROR move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract, uint32 level,
- struct current_user *user, WERROR *perr)
+
+static WERROR move_driver_file_to_download_area(TALLOC_CTX *mem_ctx,
+ connection_struct *conn,
+ const char *driver_file,
+ const char *short_architecture,
+ uint32_t driver_version,
+ uint32_t version)
+{
+ struct smb_filename *smb_fname_old = NULL;
+ struct smb_filename *smb_fname_new = NULL;
+ char *old_name = NULL;
+ char *new_name = NULL;
+ NTSTATUS status;
+ WERROR ret;
+
+ old_name = talloc_asprintf(mem_ctx, "%s/%s",
+ short_architecture, driver_file);
+ W_ERROR_HAVE_NO_MEMORY(old_name);
+
+ new_name = talloc_asprintf(mem_ctx, "%s/%d/%s",
+ short_architecture, driver_version, driver_file);
+ if (new_name == NULL) {
+ TALLOC_FREE(old_name);
+ return WERR_NOMEM;
+ }
+
+ if (version != -1 && (version = file_version_is_newer(conn, old_name, new_name)) > 0) {
+
+ status = driver_unix_convert(conn, old_name, &smb_fname_old);
+ if (!NT_STATUS_IS_OK(status)) {
+ ret = WERR_NOMEM;
+ goto out;
+ }
+
+ /* Setup a synthetic smb_filename struct */
+ smb_fname_new = TALLOC_ZERO_P(mem_ctx, struct smb_filename);
+ if (!smb_fname_new) {
+ ret = WERR_NOMEM;
+ goto out;
+ }
+
+ smb_fname_new->base_name = new_name;
+
+ DEBUG(10,("move_driver_file_to_download_area: copying '%s' to "
+ "'%s'\n", smb_fname_old->base_name,
+ smb_fname_new->base_name));
+
+ status = copy_file(mem_ctx, conn, smb_fname_old, smb_fname_new,
+ OPENX_FILE_EXISTS_TRUNCATE |
+ OPENX_FILE_CREATE_IF_NOT_EXIST,
+ 0, false);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("move_driver_file_to_download_area: Unable "
+ "to rename [%s] to [%s]: %s\n",
+ smb_fname_old->base_name, new_name,
+ nt_errstr(status)));
+ ret = WERR_ACCESS_DENIED;
+ goto out;
+ }
+ }
+
+ ret = WERR_OK;
+ out:
+ TALLOC_FREE(smb_fname_old);
+ TALLOC_FREE(smb_fname_new);
+ return ret;
+}
+
+WERROR move_driver_to_download_area(struct pipes_struct *p,
+ NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
+ uint32 level, WERROR *perr)
{
NT_PRINTER_DRIVER_INFO_LEVEL_3 *driver;
NT_PRINTER_DRIVER_INFO_LEVEL_3 converted_driver;
- const char *architecture;
+ const char *short_architecture;
+ struct smb_filename *smb_dname = NULL;
char *new_dir = NULL;
- char *old_name = NULL;
- char *new_name = NULL;
- DATA_BLOB null_pw;
- connection_struct *conn;
+ connection_struct *conn = NULL;
NTSTATUS nt_status;
- fstring res_type;
- SMB_STRUCT_STAT st;
int i;
TALLOC_CTX *ctx = talloc_tos();
int ver = 0;
+ char *oldcwd;
+ fstring printdollar;
+ int printdollar_snum;
*perr = WERR_OK;
- if (level==3)
- driver=driver_abstract.info_3;
- else if (level==6) {
+ switch (level) {
+ case 3:
+ driver = driver_abstract.info_3;
+ break;
+ case 6:
convert_level_6_to_level3(&converted_driver, driver_abstract.info_6);
driver = &converted_driver;
- } else {
+ break;
+ default:
DEBUG(0,("move_driver_to_download_area: Unknown info level (%u)\n", (unsigned int)level ));
return WERR_UNKNOWN_LEVEL;
}
- architecture = get_short_archi(driver->environment);
- if (!architecture) {
+ short_architecture = get_short_archi(driver->environment);
+ if (!short_architecture) {
return WERR_UNKNOWN_PRINTER_DRIVER;
}
- /*
- * 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.
- */
-
- null_pw = data_blob_null;
- fstrcpy(res_type, "A:");
- become_root();
- conn = make_connection_with_chdir("print$", null_pw, res_type, user->vuid, &nt_status);
- unbecome_root();
+ fstrcpy(printdollar, "print$");
- if (conn == NULL) {
- DEBUG(0,("move_driver_to_download_area: Unable to connect\n"));
- *perr = ntstatus_to_werror(nt_status);
+ printdollar_snum = find_service(printdollar);
+ if (printdollar_snum == -1) {
+ *perr = WERR_NO_SUCH_SHARE;
return WERR_NO_SUCH_SHARE;
}
- /*
- * Save who we are - we are temporarily becoming the connection user.
- */
-
- if (!become_user(conn, conn->vuid)) {
- DEBUG(0,("move_driver_to_download_area: Can't become user!\n"));
- return WERR_ACCESS_DENIED;
+ nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
+ lp_pathname(printdollar_snum),
+ p->server_info, &oldcwd);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0,("move_driver_to_download_area: create_conn_struct "
+ "returned %s\n", nt_errstr(nt_status)));
+ *perr = ntstatus_to_werror(nt_status);
+ return *perr;
}
- /* WE ARE NOW RUNNING AS USER conn->vuid !!!!! */
-
- /*
- * make the directories version and version\driver_name
- * under the architecture directory.
- */
- DEBUG(5,("Creating first directory\n"));
new_dir = talloc_asprintf(ctx,
"%s/%d",
- architecture,
+ short_architecture,
driver->cversion);
if (!new_dir) {
*perr = WERR_NOMEM;
goto err_exit;
}
- new_dir = driver_unix_convert(conn,new_dir,&st);
- if (!new_dir) {
+ nt_status = driver_unix_convert(conn, new_dir, &smb_dname);
+ if (!NT_STATUS_IS_OK(nt_status)) {
*perr = WERR_NOMEM;
goto err_exit;
}
- create_directory(conn, NULL, new_dir);
+ DEBUG(5,("Creating first directory: %s\n", smb_dname->base_name));
+
+ create_directory(conn, NULL, smb_dname);
/* 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:
DEBUG(5,("Moving files now !\n"));
if (driver->driverpath && strlen(driver->driverpath)) {
- new_name = talloc_asprintf(ctx,
- "%s/%s",
- architecture,
- driver->driverpath);
- if (!new_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- old_name = talloc_asprintf(ctx,
- "%s/%s",
- new_dir,
- driver->driverpath);
- if (!old_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- new_name = driver_unix_convert(conn,new_name,&st);
- if (!new_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
- OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
- DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
- new_name, old_name));
- *perr = WERR_ACCESS_DENIED;
+ *perr = move_driver_file_to_download_area(ctx,
+ conn,
+ driver->driverpath,
+ short_architecture,
+ driver->cversion,
+ ver);
+ if (!W_ERROR_IS_OK(*perr)) {
+ if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
ver = -1;
}
+ goto err_exit;
}
}
if (driver->datafile && strlen(driver->datafile)) {
if (!strequal(driver->datafile, driver->driverpath)) {
- new_name = talloc_asprintf(ctx,
- "%s/%s",
- architecture,
- driver->datafile);
- if (!new_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- old_name = talloc_asprintf(ctx,
- "%s/%s",
- new_dir,
- driver->datafile);
- if (!old_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- new_name = driver_unix_convert(conn,new_name,&st);
- if (!new_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
- OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
- DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
- new_name, old_name));
- *perr = WERR_ACCESS_DENIED;
+
+ *perr = move_driver_file_to_download_area(ctx,
+ conn,
+ driver->datafile,
+ short_architecture,
+ driver->cversion,
+ ver);
+ if (!W_ERROR_IS_OK(*perr)) {
+ if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
ver = -1;
}
+ goto err_exit;
}
}
}
if (driver->configfile && strlen(driver->configfile)) {
if (!strequal(driver->configfile, driver->driverpath) &&
- !strequal(driver->configfile, driver->datafile)) {
- new_name = talloc_asprintf(ctx,
- "%s/%s",
- architecture,
- driver->configfile);
- if (!new_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- old_name = talloc_asprintf(ctx,
- "%s/%s",
- new_dir,
- driver->configfile);
- if (!old_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- new_name = driver_unix_convert(conn,new_name,&st);
- if (!new_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
- OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
- DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
- new_name, old_name));
- *perr = WERR_ACCESS_DENIED;
+ !strequal(driver->configfile, driver->datafile)) {
+
+ *perr = move_driver_file_to_download_area(ctx,
+ conn,
+ driver->configfile,
+ short_architecture,
+ driver->cversion,
+ ver);
+ if (!W_ERROR_IS_OK(*perr)) {
+ if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
ver = -1;
}
+ goto err_exit;
}
}
}
if (driver->helpfile && strlen(driver->helpfile)) {
if (!strequal(driver->helpfile, driver->driverpath) &&
- !strequal(driver->helpfile, driver->datafile) &&
- !strequal(driver->helpfile, driver->configfile)) {
- new_name = talloc_asprintf(ctx,
- "%s/%s",
- architecture,
- driver->helpfile);
- if (!new_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- old_name = talloc_asprintf(ctx,
- "%s/%s",
- new_dir,
- driver->helpfile);
- if (!old_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- new_name = driver_unix_convert(conn,new_name,&st);
- if (!new_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name, OPENX_FILE_EXISTS_TRUNCATE|
- OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
- DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
- new_name, old_name));
- *perr = WERR_ACCESS_DENIED;
+ !strequal(driver->helpfile, driver->datafile) &&
+ !strequal(driver->helpfile, driver->configfile)) {
+
+ *perr = move_driver_file_to_download_area(ctx,
+ conn,
+ driver->helpfile,
+ short_architecture,
+ driver->cversion,
+ ver);
+ if (!W_ERROR_IS_OK(*perr)) {
+ if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
ver = -1;
}
+ goto err_exit;
}
}
}
if (driver->dependentfiles) {
for (i=0; *driver->dependentfiles[i]; i++) {
if (!strequal(driver->dependentfiles[i], driver->driverpath) &&
- !strequal(driver->dependentfiles[i], driver->datafile) &&
- !strequal(driver->dependentfiles[i], driver->configfile) &&
- !strequal(driver->dependentfiles[i], driver->helpfile)) {
+ !strequal(driver->dependentfiles[i], driver->datafile) &&
+ !strequal(driver->dependentfiles[i], driver->configfile) &&
+ !strequal(driver->dependentfiles[i], driver->helpfile)) {
int j;
for (j=0; j < i; j++) {
if (strequal(driver->dependentfiles[i], driver->dependentfiles[j])) {
}
}
- new_name = talloc_asprintf(ctx,
- "%s/%s",
- architecture,
- driver->dependentfiles[i]);
- if (!new_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- old_name = talloc_asprintf(ctx,
- "%s/%s",
- new_dir,
- driver->dependentfiles[i]);
- if (!old_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- if (ver != -1 && (ver=file_version_is_newer(conn, new_name, old_name)) > 0) {
- new_name = driver_unix_convert(conn,new_name,&st);
- if (!new_name) {
- *perr = WERR_NOMEM;
- goto err_exit;
- }
- if ( !NT_STATUS_IS_OK(copy_file(ctx,conn, new_name, old_name,
- OPENX_FILE_EXISTS_TRUNCATE|
- OPENX_FILE_CREATE_IF_NOT_EXIST, 0, False))) {
- DEBUG(0,("move_driver_to_download_area: Unable to rename [%s] to [%s]\n",
- new_name, old_name));
- *perr = WERR_ACCESS_DENIED;
+ *perr = move_driver_file_to_download_area(ctx,
+ conn,
+ driver->dependentfiles[i],
+ short_architecture,
+ driver->cversion,
+ ver);
+ if (!W_ERROR_IS_OK(*perr)) {
+ if (W_ERROR_EQUAL(*perr, WERR_ACCESS_DENIED)) {
ver = -1;
}
+ goto err_exit;
}
}
NextDriver: ;
}
err_exit:
+ TALLOC_FREE(smb_dname);
- close_cnum(conn, user->vuid);
- unbecome_user();
+ if (conn != NULL) {
+ vfs_ChDir(conn, oldcwd);
+ conn_free(conn);
+ }
if (W_ERROR_EQUAL(*perr, WERR_OK)) {
return WERR_OK;
return (uint32)-1;
}
- /* .inf files do not always list a file for each of the four standard files.
+ /* .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
+ * "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(info.name, driver);
fstrcpy(info.defaultdatatype, "RAW");
-
+
fstrcpy(info.driverpath, "");
fstrcpy(info.datafile, "");
fstrcpy(info.configfile, "");
SAFE_FREE(info.dependentfiles);
return WERR_NOMEM;
}
-
+
return WERR_OK;
}
/****************************************************************************
****************************************************************************/
-static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, const char *arch, uint32 version)
+static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
+ const char *drivername, const char *arch,
+ uint32_t version)
{
NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
TDB_DATA dbuf;
uint32 result;
NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3;
int i;
-
+
DEBUG(20,("Dumping printer driver at level [%d]\n", level));
-
+
switch (level)
{
case 3:
result=5;
else {
info3=driver.info_3;
-
+
DEBUGADD(20,("version:[%d]\n", info3->cversion));
DEBUGADD(20,("name:[%s]\n", info3->name));
DEBUGADD(20,("environment:[%s]\n", info3->environment));
DEBUGADD(20,("helpfile:[%s]\n", info3->helpfile));
DEBUGADD(20,("monitorname:[%s]\n", info3->monitorname));
DEBUGADD(20,("defaultdatatype:[%s]\n", info3->defaultdatatype));
-
+
for (i=0; info3->dependentfiles &&
*info3->dependentfiles[i]; i++) {
DEBUGADD(20,("dependentfile:[%s]\n",
result=1;
break;
}
-
+
return result;
}
nt_devmode->ttoption,
nt_devmode->collate,
nt_devmode->logpixels,
-
+
nt_devmode->fields,
nt_devmode->bitsperpel,
nt_devmode->pelswidth,
{
int len = 0;
int i, j;
- REGISTRY_VALUE *val;
- REGVAL_CTR *val_ctr;
+ struct regval_blob *val;
+ struct regval_ctr *val_ctr;
char *path = NULL;
int num_values;
close_all_print_db();
- if (geteuid() == 0) {
+ if (geteuid() == sec_initial_uid()) {
if (asprintf(&printdb_path, "%s%s.tdb",
- lock_path("printing/"),
+ cache_path("printing/"),
sharename) < 0) {
return (uint32)-1;
}
int retlen;
WERROR ret;
TDB_DATA kbuf, dbuf;
-
+
/*
* in addprinter: no servername and the printer is the name
* in setprinter: servername is \\server
ZERO_STRUCTP(nt_devmode);
slprintf(adevice, sizeof(adevice), "%s", default_devicename);
- fstrcpy(nt_devmode->devicename, adevice);
-
+ fstrcpy(nt_devmode->devicename, adevice);
+
fstrcpy(nt_devmode->formname, "Letter");
- nt_devmode->specversion = 0x0401;
+ nt_devmode->specversion = DMSPEC_NT4_AND_ABOVE;
nt_devmode->driverversion = 0x0400;
nt_devmode->size = 0x00DC;
nt_devmode->driverextra = 0x0000;
- nt_devmode->fields = FORMNAME | TTOPTION | PRINTQUALITY |
- DEFAULTSOURCE | COPIES | SCALE |
- PAPERSIZE | ORIENTATION;
- nt_devmode->orientation = 1;
- nt_devmode->papersize = PAPER_LETTER;
+ nt_devmode->fields = DEVMODE_FORMNAME |
+ DEVMODE_TTOPTION |
+ DEVMODE_PRINTQUALITY |
+ DEVMODE_DEFAULTSOURCE |
+ DEVMODE_COPIES |
+ DEVMODE_SCALE |
+ DEVMODE_PAPERSIZE |
+ DEVMODE_ORIENTATION;
+ nt_devmode->orientation = DMORIENT_PORTRAIT;
+ nt_devmode->papersize = DMPAPER_LETTER;
nt_devmode->paperlength = 0;
nt_devmode->paperwidth = 0;
nt_devmode->scale = 0x64;
nt_devmode->copies = 1;
- nt_devmode->defaultsource = BIN_FORMSOURCE;
- nt_devmode->printquality = RES_HIGH; /* 0x0258 */
- nt_devmode->color = COLOR_MONOCHROME;
- nt_devmode->duplex = DUP_SIMPLEX;
+ nt_devmode->defaultsource = DMBIN_FORMSOURCE;
+ nt_devmode->printquality = DMRES_HIGH; /* 0x0258 */
+ nt_devmode->color = DMRES_MONOCHROME;
+ nt_devmode->duplex = DMDUP_SIMPLEX;
nt_devmode->yresolution = 0;
- nt_devmode->ttoption = TT_SUBDEV;
- nt_devmode->collate = COLLATE_FALSE;
+ nt_devmode->ttoption = DMTT_SUBDEV;
+ nt_devmode->collate = DMCOLLATE_FALSE;
nt_devmode->icmmethod = 0;
nt_devmode->icmintent = 0;
nt_devmode->mediatype = 0;
nt_devmode->reserved2 = 0;
nt_devmode->panningwidth = 0;
nt_devmode->panningheight = 0;
-
+
nt_devmode->nt_dev_private = NULL;
return nt_devmode;
}
-/****************************************************************************
- Deepcopy an NT devicemode.
-****************************************************************************/
-
-NT_DEVICEMODE *dup_nt_devicemode(NT_DEVICEMODE *nt_devicemode)
-{
- NT_DEVICEMODE *new_nt_devicemode = NULL;
-
- if ( !nt_devicemode )
- return NULL;
-
- if ((new_nt_devicemode = (NT_DEVICEMODE *)memdup(nt_devicemode, sizeof(NT_DEVICEMODE))) == NULL) {
- DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
- return NULL;
- }
-
- new_nt_devicemode->nt_dev_private = NULL;
- if (nt_devicemode->nt_dev_private != NULL) {
- if ((new_nt_devicemode->nt_dev_private = (uint8 *)memdup(nt_devicemode->nt_dev_private, nt_devicemode->driverextra)) == NULL) {
- SAFE_FREE(new_nt_devicemode);
- DEBUG(0,("dup_nt_devicemode: malloc fail.\n"));
- return NULL;
- }
- }
-
- return new_nt_devicemode;
-}
-
/****************************************************************************
Clean up and deallocate a (maybe partially) allocated NT_DEVICEMODE.
****************************************************************************/
int len = 0;
int extra_len = 0;
NT_DEVICEMODE devmode;
-
+
ZERO_STRUCT(devmode);
len += tdb_unpack(buf+len, buflen-len, "p", nt_devmode);
&devmode.ttoption,
&devmode.collate,
&devmode.logpixels,
-
+
&devmode.fields,
&devmode.bitsperpel,
&devmode.pelswidth,
&devmode.panningwidth,
&devmode.panningheight,
&devmode.nt_dev_private);
-
+
if (devmode.nt_dev_private) {
/* the len in tdb_unpack is an int value and
* devmode.driverextra is only a short
*/
len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.nt_dev_private);
devmode.driverextra=(uint16)extra_len;
-
+
/* check to catch an invalid TDB entry so we don't segfault */
if (devmode.driverextra == 0) {
devmode.nt_dev_private = NULL;
/****************************************************************************
Allocate and initialize a new slot.
***************************************************************************/
-
+
int add_new_printer_key( NT_PRINTER_DATA *data, const char *name )
{
NT_PRINTER_KEY *d;
int key_index;
-
+
if ( !name || !data )
return -1;
/* allocate another slot in the NT_PRINTER_KEY array */
-
+
if ( !(d = TALLOC_REALLOC_ARRAY( data, data->keys, NT_PRINTER_KEY, data->num_keys+1)) ) {
DEBUG(0,("add_new_printer_key: Realloc() failed!\n"));
return -1;
}
data->keys = d;
-
+
key_index = data->num_keys;
-
+
/* initialze new key */
-
+
data->keys[key_index].name = talloc_strdup( data, name );
-
- if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, REGVAL_CTR )) )
+
+ if ( !(data->keys[key_index].values = TALLOC_ZERO_P( data, struct regval_ctr )) )
return -1;
-
+
data->num_keys++;
DEBUG(10,("add_new_printer_key: Inserted new data key [%s]\n", name ));
-
+
return key_index;
}
int delete_printer_key( NT_PRINTER_DATA *data, const char *name )
{
int i;
-
+
for ( i=0; i<data->num_keys; i++ ) {
if ( strequal( data->keys[i].name, name ) ) {
-
+
/* cleanup memory */
-
+
TALLOC_FREE( data->keys[i].name );
TALLOC_FREE( data->keys[i].values );
-
+
/* if not the end of the array, move remaining elements down one slot */
-
+
data->num_keys--;
if ( data->num_keys && (i < data->num_keys) )
memmove( &data->keys[i], &data->keys[i+1], sizeof(NT_PRINTER_KEY)*(data->num_keys-i) );
-
+
break;
}
}
-
+
return data->num_keys;
}
/****************************************************************************
search for a registry key name in the existing printer data
***************************************************************************/
-
+
int lookup_printerkey( NT_PRINTER_DATA *data, const char *name )
{
int key_index = -1;
int i;
-
+
if ( !data || !name )
return -1;
DEBUG(12,("lookup_printerkey: Looking for [%s]\n", name));
/* loop over all existing keys */
-
+
for ( i=0; i<data->num_keys; i++ ) {
if ( strequal(data->keys[i].name, name) ) {
DEBUG(12,("lookup_printerkey: Found [%s]!\n", name));
key_index = i;
break;
-
+
}
}
-
+
return key_index;
}
char *p;
fstring *subkeys_ptr = NULL;
fstring subkeyname;
-
+
*subkeys = NULL;
if ( !data )
if ( strlen(key) == 0 ) {
for ( i=0; i<data->num_keys; i++ ) {
-
+
/* found a match, so allocate space and copy the name */
-
+
if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
- DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
+ DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
num_subkeys+1));
return -1;
}
-
+
fstrcpy( subkeys_ptr[num_subkeys], data->keys[i].name );
num_subkeys++;
}
goto done;
}
-
+
/* asking for the subkeys of some key */
/* subkey paths are stored in the key name using '\' as the delimiter */
for ( i=0; i<data->num_keys; i++ ) {
if ( StrnCaseCmp(data->keys[i].name, key, strlen(key)) == 0 ) {
-
+
/* if we found the exact key, then break */
key_len = strlen( key );
if ( strlen(data->keys[i].name) == key_len )
break;
-
+
/* get subkey path */
p = data->keys[i].name + key_len;
fstrcpy( subkeyname, p );
if ( (p = strchr( subkeyname, '\\' )) )
*p = '\0';
-
+
/* don't add a key more than once */
-
+
for ( j=0; j<num_subkeys; j++ ) {
if ( strequal( subkeys_ptr[j], subkeyname ) )
break;
}
-
+
if ( j != num_subkeys )
continue;
/* found a match, so allocate space and copy the name */
-
+
if ( !(subkeys_ptr = SMB_REALLOC_ARRAY( subkeys_ptr, fstring, num_subkeys+2)) ) {
- DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
+ DEBUG(0,("get_printer_subkeys: Realloc failed for [%d] entries!\n",
num_subkeys+1));
return 0;
}
-
+
fstrcpy( subkeys_ptr[num_subkeys], subkeyname );
num_subkeys++;
}
-
+
}
-
+
/* return error if the key was not found */
-
+
if ( i == data->num_keys ) {
SAFE_FREE(subkeys_ptr);
return -1;
}
-
+
done:
/* tag off the end */
-
+
if (num_subkeys)
fstrcpy(subkeys_ptr[num_subkeys], "" );
-
+
*subkeys = subkeys_ptr;
return num_subkeys;
}
#ifdef HAVE_ADS
-static void map_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
+static void map_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
const char *sz)
{
smb_ucs2_t conv_str[1024];
regval_ctr_delvalue(ctr, val_name);
str_size = push_ucs2(NULL, conv_str, sz, sizeof(conv_str),
STR_TERMINATE | STR_NOALIGN);
- regval_ctr_addvalue(ctr, val_name, REG_SZ,
+ regval_ctr_addvalue(ctr, val_name, REG_SZ,
(char *) conv_str, str_size);
}
-static void map_dword_into_ctr(REGVAL_CTR *ctr, const char *val_name,
+static void map_dword_into_ctr(struct regval_ctr *ctr, const char *val_name,
uint32 dword)
{
regval_ctr_delvalue(ctr, val_name);
(char *) &dword, sizeof(dword));
}
-static void map_bool_into_ctr(REGVAL_CTR *ctr, const char *val_name,
+static void map_bool_into_ctr(struct regval_ctr *ctr, const char *val_name,
bool b)
{
uint8 bin_bool = (b ? 1 : 0);
regval_ctr_delvalue(ctr, val_name);
- regval_ctr_addvalue(ctr, val_name, REG_BINARY,
+ regval_ctr_addvalue(ctr, val_name, REG_BINARY,
(char *) &bin_bool, sizeof(bin_bool));
}
-static void map_single_multi_sz_into_ctr(REGVAL_CTR *ctr, const char *val_name,
+static void map_single_multi_sz_into_ctr(struct regval_ctr *ctr, const char *val_name,
const char *multi_sz)
{
smb_ucs2_t *conv_strs = NULL;
/* Change to byte units. */
str_size *= sizeof(smb_ucs2_t);
- push_ucs2(NULL, conv_strs, multi_sz, str_size,
+ push_ucs2(NULL, conv_strs, multi_sz, str_size,
STR_TERMINATE | STR_NOALIGN);
regval_ctr_delvalue(ctr, val_name);
- regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
- (char *) conv_strs, str_size);
+ regval_ctr_addvalue(ctr, val_name, REG_MULTI_SZ,
+ (char *) conv_strs, str_size);
SAFE_FREE(conv_strs);
}
static bool map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)
{
- REGVAL_CTR *ctr = NULL;
+ struct regval_ctr *ctr = NULL;
fstring longname;
const char *dnssuffix;
char *allocated_string = NULL;
map_sz_into_ctr(ctr, SPOOL_REG_SERVERNAME, longname);
- asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename);
+ if (asprintf(&allocated_string, "\\\\%s\\%s", longname, info2->sharename) == -1) {
+ return false;
+ }
map_sz_into_ctr(ctr, SPOOL_REG_UNCNAME, allocated_string);
SAFE_FREE(allocated_string);
map_dword_into_ctr(ctr, SPOOL_REG_PRIORITY, info2->priority);
map_bool_into_ctr(ctr, SPOOL_REG_PRINTKEEPPRINTEDJOBS,
- (info2->attributes &
+ (info2->attributes &
PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS));
switch (info2->attributes & 0x3) {
/*****************************************************************
****************************************************************/
-static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
+static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2,
struct GUID guid)
{
int i;
- REGVAL_CTR *ctr=NULL;
+ struct regval_ctr *ctr=NULL;
UNISTR2 unistr_guid;
/* find the DsSpooler key */
/* We used to store this as a REG_BINARY but that causes
Vista to whine */
- ZERO_STRUCT( unistr_guid );
-
+ ZERO_STRUCT( unistr_guid );
+
init_unistr2( &unistr_guid, GUID_string(talloc_tos(), &guid),
UNI_STR_TERMINATE );
- regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
- (char *)unistr_guid.buffer,
+ regval_ctr_addvalue(ctr, "objectGUID", REG_SZ,
+ (char *)unistr_guid.buffer,
unistr_guid.uni_max_len*2);
-
+
}
static WERROR nt_printer_publish_ads(ADS_STRUCT *ads,
WERROR win_rc = WERR_OK;
size_t converted_size;
+ /* build the ads mods */
+ ctx = talloc_init("nt_printer_publish_ads");
+ if (ctx == NULL) {
+ return WERR_NOMEM;
+ }
+
DEBUG(5, ("publishing printer %s\n", printer->info_2->printername));
/* figure out where to publish */
srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
if (!srv_dn_utf8) {
- ads_destroy(&ads);
+ TALLOC_FREE(ctx);
return WERR_SERVER_UNAVAILABLE;
}
ads_msgfree(ads, res);
srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
if (!srv_cn_utf8) {
+ TALLOC_FREE(ctx);
ldap_memfree(srv_dn_utf8);
- ads_destroy(&ads);
return WERR_SERVER_UNAVAILABLE;
}
/* Now convert to CH_UNIX. */
- if (!pull_utf8_allocate(&srv_dn, srv_dn_utf8, &converted_size)) {
+ if (!pull_utf8_talloc(ctx, &srv_dn, srv_dn_utf8, &converted_size)) {
+ TALLOC_FREE(ctx);
ldap_memfree(srv_dn_utf8);
ldap_memfree(srv_cn_utf8);
- ads_destroy(&ads);
return WERR_SERVER_UNAVAILABLE;
}
- if (!pull_utf8_allocate(&srv_cn_0, srv_cn_utf8[0], &converted_size)) {
+ if (!pull_utf8_talloc(ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size)) {
+ TALLOC_FREE(ctx);
ldap_memfree(srv_dn_utf8);
ldap_memfree(srv_cn_utf8);
- ads_destroy(&ads);
- SAFE_FREE(srv_dn);
+ TALLOC_FREE(srv_dn);
return WERR_SERVER_UNAVAILABLE;
}
srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
if (!srv_cn_escaped) {
- SAFE_FREE(srv_cn_0);
- ldap_memfree(srv_dn_utf8);
- ads_destroy(&ads);
+ TALLOC_FREE(ctx);
return WERR_SERVER_UNAVAILABLE;
}
sharename_escaped = escape_rdn_val_string_alloc(printer->info_2->sharename);
if (!sharename_escaped) {
SAFE_FREE(srv_cn_escaped);
- SAFE_FREE(srv_cn_0);
- ldap_memfree(srv_dn_utf8);
- ads_destroy(&ads);
+ TALLOC_FREE(ctx);
return WERR_SERVER_UNAVAILABLE;
}
+ prt_dn = talloc_asprintf(ctx, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
- asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn_escaped, sharename_escaped, srv_dn);
-
- SAFE_FREE(srv_dn);
- SAFE_FREE(srv_cn_0);
SAFE_FREE(srv_cn_escaped);
SAFE_FREE(sharename_escaped);
- /* build the ads mods */
- ctx = talloc_init("nt_printer_publish_ads");
- if (ctx == NULL) {
- SAFE_FREE(prt_dn);
- return WERR_NOMEM;
- }
-
mods = ads_init_mods(ctx);
if (mods == NULL) {
SAFE_FREE(prt_dn);
- talloc_destroy(ctx);
+ TALLOC_FREE(ctx);
return WERR_NOMEM;
}
get_local_printer_publishing_data(ctx, &mods, printer->info_2->data);
- ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
+ ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,
printer->info_2->sharename);
/* publish it */
if (!ADS_ERR_OK(ads_rc))
DEBUG(3, ("error publishing %s: %s\n", printer->info_2->sharename, ads_errstr(ads_rc)));
-
- talloc_destroy(ctx);
/* retreive the guid and store it locally */
if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) {
ads_msgfree(ads, res);
store_printer_guid(printer->info_2, guid);
win_rc = mod_a_printer(printer, 2);
- }
+ }
+ TALLOC_FREE(ctx);
- SAFE_FREE(prt_dn);
return win_rc;
}
NT_PRINTER_INFO_LEVEL *printer)
{
ADS_STATUS ads_rc;
- LDAPMessage *res;
+ LDAPMessage *res = NULL;
char *prt_dn = NULL;
DEBUG(5, ("unpublishing printer %s\n", printer->info_2->printername));
/* remove the printer from the directory */
- ads_rc = ads_find_printer_on_server(ads, &res,
+ ads_rc = ads_find_printer_on_server(ads, &res,
printer->info_2->sharename, global_myname());
- if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) {
- prt_dn = ads_get_dn(ads, res);
+ if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
+ prt_dn = ads_get_dn(ads, talloc_tos(), res);
if (!prt_dn) {
ads_msgfree(ads, res);
return WERR_NOMEM;
}
ads_rc = ads_del_dn(ads, prt_dn);
- ads_memfree(ads, prt_dn);
+ TALLOC_FREE(prt_dn);
}
- ads_msgfree(ads, res);
+ if (res) {
+ ads_msgfree(ads, res);
+ }
return WERR_OK;
}
goto done;
switch (action) {
- case SPOOL_DS_PUBLISH:
- case SPOOL_DS_UPDATE:
+ case DSPRINT_PUBLISH:
+ case DSPRINT_UPDATE:
/* set the DsSpooler info and attributes */
if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) {
win_rc = WERR_NOMEM;
printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
break;
- case SPOOL_DS_UNPUBLISH:
+ case DSPRINT_UNPUBLISH:
printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED;
break;
default:
ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
NULL, NULL);
- /* ads_connect() will find the DC for us */
+ /* ads_connect() will find the DC for us */
ads_rc = ads_connect(ads);
if (!ADS_ERR_OK(ads_rc)) {
DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
}
switch (action) {
- case SPOOL_DS_PUBLISH:
- case SPOOL_DS_UPDATE:
+ case DSPRINT_PUBLISH:
+ case DSPRINT_UPDATE:
win_rc = nt_printer_publish_ads(ads, printer);
break;
- case SPOOL_DS_UNPUBLISH:
+ case DSPRINT_UNPUBLISH:
win_rc = nt_printer_unpublish_ads(ads, printer);
break;
}
ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
NULL, NULL);
- /* ads_connect() will find the DC for us */
+ /* ads_connect() will find the DC for us */
ads_rc = ads_connect(ads);
if (!ADS_ERR_OK(ads_rc)) {
DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc)));
return WERR_OK;
}
-bool is_printer_published(Printer_entry *print_hnd, int snum,
+bool is_printer_published(Printer_entry *print_hnd, int snum,
struct GUID *guid)
{
NT_PRINTER_INFO_LEVEL *printer = NULL;
- REGVAL_CTR *ctr;
- REGISTRY_VALUE *guid_val;
+ struct regval_ctr *ctr;
+ struct regval_blob *guid_val;
WERROR win_rc;
int i;
bool ret = False;
!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) ||
((i = lookup_printerkey(printer->info_2->data, SPOOL_DSSPOOLER_KEY)) < 0) ||
!(ctr = printer->info_2->data->keys[i].values) ||
- !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
+ !(guid_val = regval_ctr_getvalue(ctr, "objectGUID")))
{
free_a_printer(&printer, 2);
return False;
/* fetching printer guids really ought to be a separate function. */
- if ( guid ) {
+ if ( guid ) {
fstring guid_str;
-
- /* We used to store the guid as REG_BINARY, then swapped
+
+ /* We used to store the guid as REG_BINARY, then swapped
to REG_SZ for Vista compatibility so check for both */
switch ( regval_type(guid_val) ){
- case REG_SZ:
- rpcstr_pull( guid_str, regval_data_p(guid_val),
+ case REG_SZ:
+ rpcstr_pull( guid_str, regval_data_p(guid_val),
sizeof(guid_str)-1, -1, STR_TERMINATE );
ret = NT_STATUS_IS_OK(GUID_from_string( guid_str, guid ));
- break;
+ break;
case REG_BINARY:
if ( regval_size(guid_val) != sizeof(struct GUID) ) {
ret = False;
break;
default:
DEBUG(0,("is_printer_published: GUID value stored as "
- "invaluid type (%d)\n", regval_type(guid_val) ));
+ "invaluid type (%d)\n", regval_type(guid_val) ));
break;
}
}
return WERR_OK;
}
-bool is_printer_published(Printer_entry *print_hnd, int snum,
+bool is_printer_published(Printer_entry *print_hnd, int snum,
struct GUID *guid)
{
return False;
/****************************************************************************
***************************************************************************/
-
+
WERROR delete_all_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key )
{
NT_PRINTER_DATA *data;
int i;
int removed_keys = 0;
int empty_slot;
-
+
data = p2->data;
empty_slot = data->num_keys;
if ( !key )
return WERR_INVALID_PARAM;
-
+
/* remove all keys */
if ( !strlen(key) ) {
-
+
TALLOC_FREE( data );
p2->data = NULL;
DEBUG(8,("delete_all_printer_data: Removed all Printer Data from printer [%s]\n",
p2->printername ));
-
+
return WERR_OK;
}
/* remove a specific key (and all subkeys) */
-
+
for ( i=0; i<data->num_keys; i++ ) {
if ( StrnCaseCmp( data->keys[i].name, key, strlen(key)) == 0 ) {
DEBUG(8,("delete_all_printer_data: Removed all Printer Data from key [%s]\n",
data->keys[i].name));
-
+
TALLOC_FREE( data->keys[i].name );
TALLOC_FREE( data->keys[i].values );
return WERR_INVALID_PARAM;
/* move everything down */
-
+
for ( i=empty_slot+1; i<data->num_keys; i++ ) {
if ( data->keys[i].name ) {
- memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
+ memcpy( &data->keys[empty_slot], &data->keys[i], sizeof(NT_PRINTER_KEY) );
ZERO_STRUCTP( &data->keys[i] );
empty_slot++;
removed_keys++;
}
/* update count */
-
+
data->num_keys -= removed_keys;
/* sanity check to see if anything is left */
/****************************************************************************
***************************************************************************/
-
+
WERROR delete_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
{
WERROR result = WERR_OK;
int key_index;
-
+
/* we must have names on non-zero length */
-
+
if ( !key || !*key|| !value || !*value )
return WERR_INVALID_NAME;
-
+
/* find the printer key first */
key_index = lookup_printerkey( p2->data, key );
if ( key_index == -1 )
return WERR_OK;
-
+
/* make sure the value exists so we can return the correct error code */
-
+
if ( !regval_ctr_getvalue( p2->data->keys[key_index].values, value ) )
return WERR_BADFILE;
-
+
regval_ctr_delvalue( p2->data->keys[key_index].values, value );
-
+
DEBUG(8,("delete_printer_data: Removed key => [%s], value => [%s]\n",
key, value ));
-
+
return result;
}
/****************************************************************************
***************************************************************************/
-
-WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
+
+WERROR add_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value,
uint32 type, uint8 *data, int real_len )
{
WERROR result = WERR_OK;
int key_index;
/* we must have names on non-zero length */
-
+
if ( !key || !*key|| !value || !*value )
return WERR_INVALID_NAME;
-
+
/* find the printer key first */
-
+
key_index = lookup_printerkey( p2->data, key );
if ( key_index == -1 )
key_index = add_new_printer_key( p2->data, key );
-
+
if ( key_index == -1 )
return WERR_NOMEM;
-
+
regval_ctr_addvalue( p2->data->keys[key_index].values, value,
type, (const char *)data, real_len );
-
+
DEBUG(8,("add_printer_data: Added key => [%s], value => [%s], type=> [%d], size => [%d]\n",
key, value, type, real_len ));
/****************************************************************************
***************************************************************************/
-REGISTRY_VALUE* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
+struct regval_blob* get_printer_data( NT_PRINTER_INFO_LEVEL_2 *p2, const char *key, const char *value )
{
int key_index;
char *str;
int size;
uint8 *data_p;
- REGISTRY_VALUE *regval_p;
+ struct regval_blob *regval_p;
int key_index;
/* add the "PrinterDriverData" key first for performance reasons */
memcpy( &guid, data_p, sizeof(struct GUID) );
init_unistr2( &unistr_guid,
- GUID_string(talloc_tos(), &guid),
+ GUID_string(talloc_tos(), &guid),
UNI_STR_TERMINATE );
- regval_ctr_addvalue( printer_data->keys[key_index].values,
+ regval_ctr_addvalue( printer_data->keys[key_index].values,
valuename, REG_SZ,
(const char *)unistr_guid.buffer,
unistr_guid.uni_str_len*2 );
} else {
/* add the value */
- regval_ctr_addvalue( printer_data->keys[key_index].values,
- valuename, type, (const char *)data_p,
+ regval_ctr_addvalue( printer_data->keys[key_index].values,
+ valuename, type, (const char *)data_p,
size );
}
int snum = lp_servicenumber(sharename);
slprintf(info->servername, sizeof(info->servername)-1, "\\\\%s", servername);
- slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
+ slprintf(info->printername, sizeof(info->printername)-1, "\\\\%s\\%s",
servername, sharename);
fstrcpy(info->sharename, sharename);
fstrcpy(info->portname, SAMBA_PRINTER_PORT_NAME);
/* 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
+ 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->datatype, "RAW");
#ifdef HAVE_CUPS
- if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
+ if (get_loc_com && (enum printing_types)lp_printing(snum) == PRINT_CUPS ) {
/* Pull the location and comment strings from cups if we don't
already have one */
if ( !strlen(info->location) || !strlen(info->comment) )
/*
* Some client drivers freak out if there is a NULL devmode
- * (probably the driver is not checking before accessing
+ * (probably the driver is not checking before accessing
* the devmode pointer) --jerry
*
* See comments in get_a_printer_2_default()
slprintf( adevice, sizeof(adevice), "%s", info->printername );
if (info->devmode) {
- fstrcpy(info->devmode->devicename, adevice);
+ fstrcpy(info->devmode->devicename, adevice);
}
if ( !(info->data = TALLOC_ZERO_P( info, NT_PRINTER_DATA )) ) {
DEBUG(9,("Unpacked printer [%s] name [%s] running driver [%s]\n",
sharename, info->printername, info->drivername));
- return WERR_OK;
+ return WERR_OK;
}
/****************************************************************************
{
uint32 result;
NT_PRINTER_INFO_LEVEL_2 *info2;
-
+
DEBUG(106,("Dumping printer at level [%d]\n", level));
-
+
switch (level) {
case 2:
{
else
{
info2=printer->info_2;
-
+
DEBUGADD(106,("attributes:[%d]\n", info2->attributes));
DEBUGADD(106,("priority:[%d]\n", info2->priority));
DEBUGADD(106,("default_priority:[%d]\n", info2->default_priority));
result=1;
break;
}
-
+
return result;
}
WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
{
WERROR result;
-
- dump_a_printer(printer, level);
-
+
+ dump_a_printer(printer, level);
+
switch (level) {
case 2:
{
/*
* Update the changestamp. Emperical tests show that the
- * ChangeID is always updated,but c_setprinter is
+ * ChangeID is always updated,but c_setprinter is
* global spooler variable (not per printer).
*/
* 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
Delete driver init data stored for a specified driver
****************************************************************************/
-bool del_driver_init(char *drivername)
+bool del_driver_init(const char *drivername)
{
char *key;
bool ret;
}
/****************************************************************************
- Pack up the DEVMODE and values for a printer into a 'driver init' entry
+ Pack up the DEVMODE and values for a printer into a 'driver init' entry
in the tdb. Note: this is different from the driver entry and the printer
entry. There should be a single driver init entry for each driver regardless
of whether it was installed from NT or 2K. Technically, they should be
static uint32 update_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
{
uint32 result;
-
- dump_a_printer(printer, level);
-
+
+ dump_a_printer(printer, level);
+
switch (level) {
case 2:
result = update_driver_init_2(printer->info_2);
result = 1;
break;
}
-
+
return result;
}
/****************************************************************************
- Convert the printer data value, a REG_BINARY array, into an initialization
+ Convert the printer data value, a REG_BINARY array, into an initialization
DEVMODE. Note: the array must be parsed as if it was a DEVMODE in an rpc...
got to keep the endians happy :).
****************************************************************************/
-static bool convert_driver_init( TALLOC_CTX *ctx, NT_DEVICEMODE *nt_devmode, uint8 *data, uint32 data_len )
+static bool convert_driver_init(TALLOC_CTX *mem_ctx, NT_DEVICEMODE *nt_devmode,
+ const uint8_t *data, uint32_t data_len)
{
- bool result = False;
- prs_struct ps;
- DEVICEMODE devmode;
+ struct spoolss_DeviceMode devmode;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
ZERO_STRUCT(devmode);
- prs_init_empty(&ps, ctx, UNMARSHALL);
- ps.data_p = (char *)data;
- ps.buffer_size = data_len;
+ blob = data_blob_const(data, data_len);
- if (spoolss_io_devmode("phantom DEVMODE", &ps, 0, &devmode))
- result = convert_devicemode("", &devmode, &nt_devmode);
- else
- DEBUG(10,("convert_driver_init: error parsing DEVMODE\n"));
+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &devmode,
+ (ndr_pull_flags_fn_t)ndr_pull_spoolss_DeviceMode);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(10,("convert_driver_init: error parsing spoolss_DeviceMode\n"));
+ return false;
+ }
- return result;
+ return convert_devicemode("", &devmode, &nt_devmode);
}
/****************************************************************************
The Win32 client side code requirement sucks! But until we can run arbitrary
Win32 printer driver code on any Unix that Samba runs on, we are stuck with it.
-
+
It would have been easier to use SetPrinter because all the UNMARSHALLING of
the DEVMODE is done there, but 2K/XP clients do not set the DEVMODE... think
about it and you will realize why. JRR 010720
TALLOC_CTX *ctx = NULL;
NT_DEVICEMODE *nt_devmode = NULL;
NT_DEVICEMODE *tmp_devmode = printer->info_2->devmode;
-
+
/*
* When the DEVMODE is already set on the printer, don't try to unpack it.
*/
DEBUG(8,("save_driver_init_2: Enter...\n"));
-
+
if ( !printer->info_2->devmode && data_len ) {
/*
* Set devmode on printer info, so entire printer initialization can be
status = WERR_NOMEM;
goto done;
}
-
+
ZERO_STRUCTP(nt_devmode);
/*
/*
* Pack up and add (or update) the DEVMODE and any current printer data to
* a 'driver init' element in the tdb
- *
+ *
*/
if ( update_driver_init(printer, 2) != 0 ) {
status = WERR_NOMEM;
goto done;
}
-
+
/*
- * If driver initialization info was successfully saved, set the current
- * printer to match it. This allows initialization of the current printer
+ * If driver initialization info was successfully saved, set the current
+ * printer to match it. This allows initialization of the current printer
* as well as the driver.
*/
status = mod_a_printer(printer, 2);
DEBUG(10,("save_driver_init_2: error setting DEVMODE on printer [%s]\n",
printer->info_2->printername));
}
-
+
done:
talloc_destroy(ctx);
free_nt_devicemode( &nt_devmode );
-
+
printer->info_2->devmode = tmp_devmode;
return status;
WERROR save_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level, uint8 *data, uint32 data_len)
{
WERROR status = WERR_OK;
-
+
switch (level) {
case 2:
status = save_driver_init_2( printer, data, data_len );
status = WERR_UNKNOWN_LEVEL;
break;
}
-
+
return status;
}
Get a NT_PRINTER_INFO_LEVEL struct. It returns malloced memory.
Previously the code had a memory allocation problem because it always
- used the TALLOC_CTX from the Printer_entry*. This context lasts
- as a long as the original handle is open. So if the client made a lot
+ used the TALLOC_CTX from the Printer_entry*. This context lasts
+ as a long as the original handle is open. So if the client made a lot
of getprinter[data]() calls, the memory usage would climb. Now we use
- a short lived TALLOC_CTX for printer_info_2 objects returned. We
+ a short lived TALLOC_CTX for printer_info_2 objects returned. We
still use the Printer_entry->ctx for maintaining the cache copy though
- since that object must live as long as the handle by definition.
+ since that object must live as long as the handle by definition.
--jerry
****************************************************************************/
-static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
+static WERROR get_a_printer_internal( Printer_entry *print_hnd, NT_PRINTER_INFO_LEVEL **pp_printer, uint32 level,
const char *sharename, bool get_loc_com)
{
WERROR result;
fstring servername;
-
+
DEBUG(10,("get_a_printer: [%s] level %u\n", sharename, (unsigned int)level));
if ( !(*pp_printer = TALLOC_ZERO_P(NULL, NT_PRINTER_INFO_LEVEL)) ) {
return WERR_NOMEM;
}
- if ( print_hnd )
+ if ( print_hnd )
fstrcpy( servername, print_hnd->servername );
else {
fstrcpy( servername, "%L" );
if ( !W_ERROR_IS_OK(result) ) {
TALLOC_FREE( *pp_printer );
- DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
+ DEBUG(10,("get_a_printer: [%s] level %u returning %s\n",
sharename, (unsigned int)level, win_errstr(result)));
return result;
}
dump_a_printer( *pp_printer, level);
-
+
break;
-
+
default:
TALLOC_FREE( *pp_printer );
return WERR_UNKNOWN_LEVEL;
}
-
+
return WERR_OK;
}
if ( !printer )
return 0;
-
+
switch (level) {
case 2:
- if ( printer->info_2 )
+ if ( printer->info_2 )
free_nt_printer_info_level_2(&printer->info_2);
break;
uint32 result;
DEBUG(104,("adding a printer at level [%d]\n", level));
dump_a_printer_driver(driver, level);
-
+
switch (level) {
case 3:
result=add_a_printer_driver_3(driver.info_3);
result=1;
break;
}
-
+
return result;
}
/****************************************************************************
****************************************************************************/
-WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
- fstring drivername, const char *architecture, uint32 version)
+WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32_t level,
+ const char *drivername, const char *architecture,
+ uint32_t version)
{
WERROR result;
-
+
switch (level) {
case 3:
/* Sometime we just want any version of the driver */
-
+
if ( version == DRIVER_ANY_VERSION ) {
/* look for Win2k first and then for NT4 */
- result = get_a_printer_driver_3(&driver->info_3, drivername,
+ result = get_a_printer_driver_3(&driver->info_3, drivername,
architecture, 3);
-
+
if ( !W_ERROR_IS_OK(result) ) {
- result = get_a_printer_driver_3( &driver->info_3,
+ result = get_a_printer_driver_3( &driver->info_3,
drivername, architecture, 2 );
}
} else {
- result = get_a_printer_driver_3(&driver->info_3, drivername,
- architecture, version);
+ result = get_a_printer_driver_3(&driver->info_3, drivername,
+ architecture, version);
}
break;
-
+
default:
result=W_ERROR(1);
break;
}
-
+
if (W_ERROR_IS_OK(result))
dump_a_printer_driver(*driver, level);
-
+
return result;
}
uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
{
uint32 result;
-
+
switch (level) {
case 3:
{
NT_PRINTER_INFO_LEVEL *printer = NULL;
bool in_use = False;
- if ( !info_3 )
+ if ( !info_3 )
return False;
DEBUG(10,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
-
+
/* loop through the printers.tdb and check for the drivername */
-
+
for (snum=0; snum<n_services && !in_use; snum++) {
if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
continue;
-
+
if ( !W_ERROR_IS_OK(get_a_printer(NULL, &printer, 2, lp_servicename(snum))) )
continue;
-
- if ( strequal(info_3->name, printer->info_2->drivername) )
+
+ if ( strequal(info_3->name, printer->info_2->drivername) )
in_use = True;
-
+
free_a_printer( &printer, 2 );
}
-
+
DEBUG(10,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
-
+
if ( in_use ) {
NT_PRINTER_DRIVER_INFO_LEVEL d;
WERROR werr;
-
+
DEBUG(5,("printer_driver_in_use: driver \"%s\" is currently in use\n", info_3->name));
-
- /* we can still remove the driver if there is one of
+
+ /* we can still remove the driver if there is one of
"Windows NT x86" version 2 or 3 left */
-
+
if ( !strequal( "Windows NT x86", info_3->environment ) ) {
- werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
+ werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", DRIVER_ANY_VERSION );
}
else {
switch ( info_3->cversion ) {
case 2:
werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 3 );
break;
- case 3:
+ case 3:
werr = get_a_printer_driver( &d, 3, info_3->name, "Windows NT x86", 2 );
break;
default:
- DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
+ DEBUG(0,("printer_driver_in_use: ERROR! unknown driver version (%d)\n",
info_3->cversion));
werr = WERR_UNKNOWN_PRINTER_DRIVER;
break;
}
/* now check the error code */
-
+
if ( W_ERROR_IS_OK(werr) ) {
/* it's ok to remove the driver, we have other architctures left */
in_use = False;
free_a_printer_driver( d, 3 );
}
}
-
+
/* report that the driver is not in use by default */
-
+
return in_use;
}
/**********************************************************************
Check to see if a ogiven file is in use by *info
*********************************************************************/
-
+
static bool drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info )
{
int i = 0;
if ( strequal(file, info->helpfile) )
return True;
-
+
/* see of there are any dependent files to examine */
-
+
if ( !info->dependentfiles )
return False;
-
+
while ( *info->dependentfiles[i] ) {
if ( strequal(file, info->dependentfiles[i]) )
return True;
i++;
}
-
+
return False;
}
/**********************************************************************
- Utility function to remove the dependent file pointed to by the
- input parameter from the list
+ Utility function to remove the dependent file pointed to by the
+ input parameter from the list
*********************************************************************/
static void trim_dependent_file( fstring files[], int idx )
{
-
+
/* bump everything down a slot */
while( *files[idx+1] ) {
fstrcpy( files[idx], files[idx+1] );
idx++;
}
-
+
*files[idx] = '\0';
- return;
+ return;
}
/**********************************************************************
- Check if any of the files used by src are also used by drv
+ Check if any of the files used by src are also used by drv
*********************************************************************/
-static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
+static bool trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src,
NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
{
bool in_use = False;
int i = 0;
-
+
if ( !src || !drv )
return False;
-
+
/* check each file. Remove it from the src structure if it overlaps */
-
+
if ( drv_file_in_use(src->driverpath, drv) ) {
in_use = True;
DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath));
fstrcpy( src->driverpath, "" );
}
-
+
if ( drv_file_in_use(src->datafile, drv) ) {
in_use = True;
DEBUG(10,("Removing datafile [%s] from list\n", src->datafile));
fstrcpy( src->datafile, "" );
}
-
+
if ( drv_file_in_use(src->configfile, drv) ) {
in_use = True;
DEBUG(10,("Removing configfile [%s] from list\n", src->configfile));
fstrcpy( src->configfile, "" );
}
-
+
if ( drv_file_in_use(src->helpfile, drv) ) {
in_use = True;
DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile));
fstrcpy( src->helpfile, "" );
}
-
+
/* are there any dependentfiles to examine? */
-
+
if ( !src->dependentfiles )
return in_use;
-
+
while ( *src->dependentfiles[i] ) {
if ( drv_file_in_use(src->dependentfiles[i], drv) ) {
in_use = True;
trim_dependent_file( src->dependentfiles, i );
} else
i++;
- }
-
+ }
+
return in_use;
}
/****************************************************************************
- Determine whether or not a particular driver files are currently being
- used by any other driver.
-
+ Determine whether or not a particular driver files are currently being
+ used by any other driver.
+
Return value is True if any files were in use by other drivers
and False otherwise.
-
+
Upon return, *info has been modified to only contain the driver files
which are not in use
if ( !info )
return False;
-
+
version = info->cversion;
-
+
/* loop over all driver versions */
-
+
DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
-
+
/* get the list of drivers */
-
+
list = NULL;
ndrivers = get_ntdrivers(&list, info->environment, version);
-
- DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
+
+ DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n",
ndrivers, info->environment, version));
/* check each driver for overlap in files */
-
+
for (i=0; i<ndrivers; i++) {
DEBUGADD(5,("\tdriver: [%s]\n", list[i]));
-
+
ZERO_STRUCT(driver);
-
+
if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], info->environment, version)) ) {
SAFE_FREE(list);
return True;
}
-
+
/* check if d2 uses any files from d1 */
/* only if this is a different driver than the one being deleted */
-
+
if ( !strequal(info->name, driver.info_3->name) ) {
if ( trim_overlap_drv_files(info, driver.info_3) ) {
/* mz: Do not instantly return -
return in_use;
}
+static NTSTATUS driver_unlink_internals(connection_struct *conn,
+ const char *name)
+{
+ struct smb_filename *smb_fname = NULL;
+ NTSTATUS status;
+
+ status = create_synthetic_smb_fname(talloc_tos(), name, NULL, NULL,
+ &smb_fname);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ status = unlink_internals(conn, NULL, 0, smb_fname, false);
+
+ TALLOC_FREE(smb_fname);
+ return status;
+}
+
/****************************************************************************
Actually delete the driver files. Make sure that
printer_driver_files_in_use() return False before calling
this.
****************************************************************************/
-static bool delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user )
+static bool delete_driver_files(struct pipes_struct *rpc_pipe,
+ NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3)
{
int i = 0;
char *s;
const char *file;
connection_struct *conn;
- DATA_BLOB null_pw;
NTSTATUS nt_status;
- fstring res_type;
- SMB_STRUCT_STAT st;
+ char *oldcwd;
+ fstring printdollar;
+ int printdollar_snum;
+ bool ret = false;
if ( !info_3 )
return False;
DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion));
- /*
- * 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.
- */
+ fstrcpy(printdollar, "print$");
- null_pw = data_blob_null;
- fstrcpy(res_type, "A:");
- become_root();
- conn = make_connection_with_chdir( "print$", null_pw, res_type, user->vuid, &nt_status );
- unbecome_root();
+ printdollar_snum = find_service(printdollar);
+ if (printdollar_snum == -1) {
+ return false;
+ }
- if ( !conn ) {
- DEBUG(0,("delete_driver_files: Unable to connect\n"));
- return False;
+ nt_status = create_conn_struct(talloc_tos(), &conn, printdollar_snum,
+ lp_pathname(printdollar_snum),
+ rpc_pipe->server_info, &oldcwd);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ DEBUG(0,("delete_driver_files: create_conn_struct "
+ "returned %s\n", nt_errstr(nt_status)));
+ return false;
}
if ( !CAN_WRITE(conn) ) {
DEBUG(3,("delete_driver_files: Cannot delete print driver when [print$] is read-only\n"));
- return False;
- }
-
- /* Save who we are - we are temporarily becoming the connection user. */
-
- if ( !become_user(conn, conn->vuid) ) {
- DEBUG(0,("delete_driver_files: Can't become user!\n"));
- return False;
+ goto fail;
}
/* now delete the files; must strip the '\print$' string from
if ( *info_3->driverpath ) {
if ( (s = strchr( &info_3->driverpath[1], '\\' )) != NULL ) {
file = s;
- driver_unix_convert(conn,file,&st);
DEBUG(10,("deleting driverfile [%s]\n", s));
- unlink_internals(conn, NULL, 0, file, False);
+ driver_unlink_internals(conn, file);
}
}
if ( *info_3->configfile ) {
if ( (s = strchr( &info_3->configfile[1], '\\' )) != NULL ) {
file = s;
- driver_unix_convert(conn,file,&st);
DEBUG(10,("deleting configfile [%s]\n", s));
- unlink_internals(conn, NULL, 0, file, False);
+ driver_unlink_internals(conn, file);
}
}
if ( *info_3->datafile ) {
if ( (s = strchr( &info_3->datafile[1], '\\' )) != NULL ) {
file = s;
- driver_unix_convert(conn,file,&st);
DEBUG(10,("deleting datafile [%s]\n", s));
- unlink_internals(conn, NULL, 0, file, False);
+ driver_unlink_internals(conn, file);
}
}
if ( *info_3->helpfile ) {
if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) {
file = s;
- driver_unix_convert(conn,file,&st);
DEBUG(10,("deleting helpfile [%s]\n", s));
- unlink_internals(conn, NULL, 0, file, False);
+ driver_unlink_internals(conn, file);
}
}
if ( (p = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) {
file = p;
- driver_unix_convert(conn,file,&st);
DEBUG(10,("deleting dependent file [%s]\n", file));
- unlink_internals(conn, NULL, 0, file, False);
+ driver_unlink_internals(conn, file);
}
i++;
}
}
- unbecome_user();
-
- return true;
+ goto done;
+ fail:
+ ret = false;
+ done:
+ if (conn != NULL) {
+ vfs_ChDir(conn, oldcwd);
+ conn_free(conn);
+ }
+ return ret;
}
/****************************************************************************
previously looked up.
***************************************************************************/
-WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user,
- uint32 version, bool delete_files )
+WERROR delete_printer_driver(struct pipes_struct *rpc_pipe,
+ NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3,
+ uint32 version, bool delete_files )
{
char *key = NULL;
const char *arch;
*/
if ( delete_files )
- delete_driver_files( info_3, user );
+ delete_driver_files(rpc_pipe, info_3);
DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key));
SAFE_FREE(key);
{
SEC_DESC_BUF *new_secdesc_ctr = NULL;
SEC_DESC_BUF *old_secdesc_ctr = NULL;
- prs_struct ps;
- bool prs_init_done = false;
TALLOC_CTX *mem_ctx = NULL;
TDB_DATA kbuf;
+ TDB_DATA dbuf;
+ DATA_BLOB blob;
WERROR status;
+ NTSTATUS nt_status;
mem_ctx = talloc_init("nt_printing_setsec");
if (mem_ctx == NULL)
/* Store the security descriptor in a tdb */
- if (!prs_init(&ps,
- (uint32)ndr_size_security_descriptor(new_secdesc_ctr->sd, 0)
- + sizeof(SEC_DESC_BUF), mem_ctx, MARSHALL) ) {
- status = WERR_NOMEM;
- goto out;
- }
-
-
- prs_init_done = true;
-
- if (!sec_io_desc_buf("nt_printing_setsec", &new_secdesc_ctr,
- &ps, 1)) {
- status = WERR_BADFUNC;
+ nt_status = marshall_sec_desc_buf(mem_ctx, new_secdesc_ctr,
+ &blob.data, &blob.length);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ status = ntstatus_to_werror(nt_status);
goto out;
}
kbuf = make_printers_secdesc_tdbkey(mem_ctx, sharename );
- if (tdb_prs_store(tdb_printers, kbuf, &ps)==0) {
+ dbuf.dptr = (unsigned char *)blob.data;
+ dbuf.dsize = blob.length;
+
+ if (tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE)==0) {
status = WERR_OK;
} else {
DEBUG(1,("Failed to store secdesc for %s\n", sharename));
}
/* Free malloc'ed memory */
+ talloc_free(blob.data);
out:
- if (prs_init_done) {
- prs_mem_free(&ps);
- }
if (mem_ctx)
talloc_destroy(mem_ctx);
return status;
sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
/* Add the domain admins group if we are a DC */
-
+
if ( IS_DC ) {
DOM_SID domadmins_sid;
-
+
sid_copy(&domadmins_sid, get_global_sam_sid());
sid_append_rid(&domadmins_sid, DOMAIN_GROUP_RID_ADMINS);
-
+
sa = PRINTER_ACE_FULL_CONTROL;
- init_sec_ace(&ace[i++], &domadmins_sid,
- SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
+ init_sec_ace(&ace[i++], &domadmins_sid,
+ SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
init_sec_ace(&ace[i++], &domadmins_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
sid_append_rid(&adm_sid, DOMAIN_USER_RID_ADMIN);
sa = PRINTER_ACE_FULL_CONTROL;
- init_sec_ace(&ace[i++], &adm_sid,
- SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
+ init_sec_ace(&ace[i++], &adm_sid,
+ SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
init_sec_ace(&ace[i++], &adm_sid, SEC_ACE_TYPE_ACCESS_ALLOWED,
sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
/* add BUILTIN\Administrators as FULL CONTROL */
sa = PRINTER_ACE_FULL_CONTROL;
- init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
- SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
+ init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
+ SEC_ACE_TYPE_ACCESS_ALLOWED, sa,
SEC_ACE_FLAG_OBJECT_INHERIT | SEC_ACE_FLAG_INHERIT_ONLY);
- init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
+ init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
SEC_ACE_TYPE_ACCESS_ALLOWED,
sa, SEC_ACE_FLAG_CONTAINER_INHERIT);
if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) != NULL) {
psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE,
- &global_sid_Builtin_Administrators,
+ &global_sid_Builtin_Administrators,
&global_sid_Builtin_Administrators,
NULL, psa, &sd_size);
}
bool nt_printing_getsec(TALLOC_CTX *ctx, const char *sharename, SEC_DESC_BUF **secdesc_ctr)
{
- prs_struct ps;
TDB_DATA kbuf;
+ TDB_DATA dbuf;
+ DATA_BLOB blob;
char *temp;
+ NTSTATUS status;
if (strlen(sharename) > 2 && (temp = strchr(sharename + 2, '\\'))) {
sharename = temp + 1;
}
- ZERO_STRUCT(ps);
-
/* Fetch security descriptor from tdb */
- kbuf = make_printers_secdesc_tdbkey(ctx, sharename );
-
- if (tdb_prs_fetch(tdb_printers, kbuf, &ps, ctx)!=0 ||
- !sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
-
- prs_mem_free(&ps);
-
- DEBUG(4,("using default secdesc for %s\n", sharename));
-
- if (!(*secdesc_ctr = construct_default_printer_sdb(ctx))) {
- return False;
- }
+ kbuf = make_printers_secdesc_tdbkey(ctx, sharename);
- /* Save default security descriptor for later */
+ dbuf = tdb_fetch(tdb_printers, kbuf);
+ if (dbuf.dptr) {
- if (!prs_init(&ps, (uint32)ndr_size_security_descriptor((*secdesc_ctr)->sd, 0) +
- sizeof(SEC_DESC_BUF), ctx, MARSHALL))
- return False;
+ status = unmarshall_sec_desc_buf(ctx, dbuf.dptr, dbuf.dsize,
+ secdesc_ctr);
+ SAFE_FREE(dbuf.dptr);
- if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1)) {
- tdb_prs_store(tdb_printers, kbuf, &ps);
+ if (NT_STATUS_IS_OK(status)) {
+ return true;
}
+ }
- prs_mem_free(&ps);
-
- return True;
+ *secdesc_ctr = construct_default_printer_sdb(ctx);
+ if (!*secdesc_ctr) {
+ return false;
}
- prs_mem_free(&ps);
+ status = marshall_sec_desc_buf(ctx, *secdesc_ctr,
+ &blob.data, &blob.length);
+ if (NT_STATUS_IS_OK(status)) {
+ dbuf.dptr = (unsigned char *)blob.data;
+ dbuf.dsize = blob.length;
+ tdb_trans_store(tdb_printers, kbuf, dbuf, TDB_REPLACE);
+ talloc_free(blob.data);
+ }
/* If security descriptor is owned by S-1-1-0 and winbindd is up,
this security descriptor has been created when winbindd was
SEC_ACL *the_acl = (*secdesc_ctr)->sd->dacl;
int i;
- DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
+ DEBUG(10, ("secdesc_ctr for %s has %d aces:\n",
sharename, the_acl->num_aces));
for (i = 0; i < the_acl->num_aces; i++) {
DEBUG(10, ("%s %d %d 0x%08x\n",
sid_string_dbg(&the_acl->aces[i].trustee),
- the_acl->aces[i].type, the_acl->aces[i].flags,
- the_acl->aces[i].access_mask));
+ the_acl->aces[i].type, the_acl->aces[i].flags,
+ the_acl->aces[i].access_mask));
}
}
A printer and a printer driver are 2 different things.
NT manages them separatelly, Samba does the same.
Why ? Simply because it's easier and it makes sense !
-
+
Now explanation: You have 3 printers behind your samba server,
2 of them are the same make and model (laser A and B). But laser B
has an 3000 sheet feeder and laser A doesn't such an option.
Your third printer is an old dot-matrix model for the accounting :-).
-
+
If the /usr/local/samba/lib directory (default dir), you will have
5 files to describe all of this.
-
+
3 files for the printers (1 by printer):
NTprinter_laser A
NTprinter_laser B
print_queue_purge
Try access control in the following order (for performance reasons):
- 1) root ans SE_PRINT_OPERATOR can do anything (easy check)
+ 1) root and SE_PRINT_OPERATOR can do anything (easy check)
2) check security descriptor (bit comparisons in memory)
3) "printer admins" (may result in numerous calls to winbind)
SEC_DESC_BUF *secdesc = NULL;
uint32 access_granted;
NTSTATUS status;
- bool result;
const char *pname;
TALLOC_CTX *mem_ctx = NULL;
SE_PRIV se_printop = SE_PRINT_OPERATOR;
-
+
/* If user is NULL then use the current_user structure */
/* Always allow root or SE_PRINT_OPERATROR to do anything */
- if (server_info->utok.uid == 0
+ if (server_info->utok.uid == sec_initial_uid()
|| user_has_privileges(server_info->ptok, &se_printop ) ) {
return True;
}
}
talloc_destroy(mem_ctx);
-
+
if (!NT_STATUS_IS_OK(status)) {
errno = EACCES;
}