summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/include/proto.h7
-rwxr-xr-xsource3/include/rpc_spoolss.h7
-rw-r--r--source3/lib/error.c75
-rw-r--r--source3/printing/nt_printing.c103
-rw-r--r--source3/printing/printing.c30
-rw-r--r--source3/rpc_server/srv_lsa.c4
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c20
-rw-r--r--source3/smbd/lanman.c28
9 files changed, 213 insertions, 63 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 4e9475ea94..018086b40b 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -108,7 +108,7 @@ LIB_OBJ = lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \
lib/util_unistr.o lib/util_file.o \
lib/util.o lib/util_sock.o lib/util_sec.o smbd/ssl.o \
lib/talloc.o lib/hash.o lib/substitute.o lib/fsusage.o \
- lib/ms_fnmatch.o lib/select.o \
+ lib/ms_fnmatch.o lib/select.o lib/error.o \
$(TDB_OBJ)
UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 38393e3de8..9d239d38fd 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -93,6 +93,10 @@ SMB_OFF_T dos_file_size(char *file_name);
int dos_ChDir(char *path);
char *dos_GetWd(char *path);
+/*The following definitions come from lib/error.c */
+
+uint32 map_nt_error_from_unix(int unix_error);
+
/*The following definitions come from lib/fault.c */
void fault_setup(void (*fn)(void *));
@@ -1709,8 +1713,7 @@ BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
fstring value, uint8 **data, uint32 *type, uint32 *len);
uint32 nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr);
BOOL nt_printing_getsec(char *printername, SEC_DESC_BUF **secdesc_ctr);
-BOOL print_access_check(struct current_user *user, int snum,
- uint32 required_access);
+BOOL print_access_check(struct current_user *user, int snum, int access_type);
BOOL print_time_access_check(int snum);
#endif
diff --git a/source3/include/rpc_spoolss.h b/source3/include/rpc_spoolss.h
index a77ce55063..eb521a5b94 100755
--- a/source3/include/rpc_spoolss.h
+++ b/source3/include/rpc_spoolss.h
@@ -145,13 +145,18 @@
#define PRINTER_STATUS_POWER_SAVE 0x01000000
-/* Printer permissions ACE settings */
+/* Printer permissions ACE settings. NT4 uses generic and standard access
+ rights whereas NT5 converts them all to object specific access rights. */
#define PRINTER_ACE_FULL_CONTROL GENERIC_ALL_ACCESS
#define PRINTER_ACE_MANAGE_DOCUMENTS READ_CONTROL_ACCESS
#define PRINTER_ACE_PRINT \
(GENERIC_READ_ACCESS | GENERIC_WRITE_ACCESS | GENERIC_EXECUTE_ACCESS)
+#define PRINTER_ACE_NT5_FULL_CONTROL 0x000f000c
+#define PRINTER_ACE_NT5_PRINT 0x00020000
+#define PRINTER_ACE_NT5_MANAGE_DOCUMENTS 0x00020008
+
#define SERVER_ACCESS_ADMINISTER 0x00000001
#define SERVER_ACCESS_ENUMERATE 0x00000002
#define PRINTER_ACCESS_ADMINISTER 0x00000004
diff --git a/source3/lib/error.c b/source3/lib/error.c
new file mode 100644
index 0000000000..880eba5949
--- /dev/null
+++ b/source3/lib/error.c
@@ -0,0 +1,75 @@
+/*
+ * Unix SMB/Netbios implementation.
+ * Version 1.9
+ * Unix/DOS/NT error code conversions
+ * Copyright (C) Tim Potter 2000
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+/* Mapping between Unix, DOS and NT error numbers */
+
+struct {
+ int unix_error;
+ int dos_error;
+ uint32 nt_error;
+} unix_dos_nt_errmap[] = {
+ { EPERM, ERRnoaccess, NT_STATUS_ACCESS_DENIED },
+ { EACCES, ERRnoaccess, NT_STATUS_ACCESS_DENIED },
+ { ENOENT, ERRbadfile, NT_STATUS_NO_SUCH_FILE },
+ { ENOTDIR, ERRbadpath, NT_STATUS_NOT_A_DIRECTORY },
+ { EIO, ERRgeneral, NT_STATUS_IO_DEVICE_ERROR },
+ { EBADF, ERRsrverror, NT_STATUS_INVALID_HANDLE },
+ { EINVAL, ERRsrverror, NT_STATUS_INVALID_HANDLE },
+ { EEXIST, ERRfilexists, NT_STATUS_ACCESS_DENIED},
+ { ENFILE, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES },
+ { EMFILE, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES },
+ { ENOSPC, ERRdiskfull, NT_STATUS_DISK_FULL },
+#ifdef EDQUOT
+ { EDQUOT, ERRdiskfull, NT_STATUS_DISK_FULL },
+#endif
+#ifdef ENOTEMPTY
+ { ENOTEMPTY, ERRnoaccess, NT_STATUS_DIRECTORY_NOT_EMPTY },
+#endif
+#ifdef EXDEV
+ { EXDEV, ERRdiffdevice, NT_STATUS_NOT_SAME_DEVICE },
+#endif
+ { EROFS, ERRnowrite, NT_STATUS_ACCESS_DENIED },
+
+ { 0, 0, 0 }
+};
+
+/* Map an NT error code from a Unix error code */
+
+uint32 map_nt_error_from_unix(int unix_error)
+{
+ int i = 0;
+
+ /* Look through list */
+
+ while(unix_dos_nt_errmap[i].unix_error != 0) {
+ if (unix_dos_nt_errmap[i].unix_error == unix_error) {
+ return unix_dos_nt_errmap[i].nt_error;
+ }
+
+ i++;
+ }
+
+ /* Default return */
+
+ return NT_STATUS_ACCESS_DENIED;
+}
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index 05ab71d178..0ad50a2277 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -2203,30 +2203,47 @@ jfm: I should use this comment for the text file to explain
*/
/****************************************************************************
- Check a user has permissions to perform the given operation
+ Check a user has permissions to perform the given operation. We use some
+ constants defined in include/rpc_spoolss.h that look relevant to check
+ the various actions we perform when checking printer access.
+
+ PRINTER_ACCESS_ADMINISTER:
+ print_queue_pause, print_queue_resume, update_printer_sec,
+ update_printer, spoolss_addprinterex_level_2,
+ _spoolss_setprinterdata
+
+ PRINTER_ACCESS_USE:
+ print_job_start
+
+ JOB_ACCESS_ADMINISTER:
+ print_job_delete, print_job_pause, print_job_resume,
+ print_queue_purge
- if user is NULL then use the current_user structure
****************************************************************************/
-BOOL print_access_check(struct current_user *user, int snum,
- uint32 required_access)
+BOOL print_access_check(struct current_user *user, int snum, int access_type)
{
SEC_DESC_BUF *secdesc = NULL;
- uint32 access_granted, status;
+ uint32 access_granted, status, required_access = 0;
BOOL result;
char *pname;
int i;
extern struct current_user current_user;
+ /* If user is NULL then use the current_user structure */
+
if (!user) user = &current_user;
- /* always allow root or printer admins to do anything */
- if (user->uid==0 ||
+ /* Always allow root or printer admins to do anything */
+
+ if (user->uid == 0 ||
user_in_list(uidtoname(user->uid), lp_printer_admin(snum))) {
return True;
}
/* Get printer name */
+
pname = PRINTERNAME(snum);
+
if (!pname || !*pname)
pname = SERVICE(snum);
@@ -2236,8 +2253,34 @@ BOOL print_access_check(struct current_user *user, int snum,
}
/* Get printer security descriptor */
+
nt_printing_getsec(pname, &secdesc);
+ /* Check against NT4 ACE mask values. From observation these
+ values are:
+
+ Access Type ACE Mask Constant
+ -------------------------------------
+ Full Control 0x10000000 PRINTER_ACE_FULL_CONTROL
+ Print 0xe0000000 PRINTER_ACE_PRINT
+ Manage Documents 0x00020000 PRINTER_ACE_MANAGE_DOCUMENTS
+ */
+
+ switch (access_type) {
+ case PRINTER_ACCESS_USE:
+ required_access = PRINTER_ACE_PRINT;
+ break;
+ case PRINTER_ACCESS_ADMINISTER:
+ required_access = PRINTER_ACE_MANAGE_DOCUMENTS |
+ PRINTER_ACE_PRINT;
+ break;
+ case JOB_ACCESS_ADMINISTER:
+ required_access = PRINTER_ACE_MANAGE_DOCUMENTS;
+ default:
+ DEBUG(0, ("invalid value passed to print_access_check()\n"));
+ return False;
+ }
+
/* The ACE for Full Control in a printer security descriptor
doesn't seem to map properly to the access checking model. For
it to work properly it should be the logical OR of all the other
@@ -2249,16 +2292,6 @@ BOOL print_access_check(struct current_user *user, int snum,
performing the access check. I'm sure there is a better way to
do this! */
- /* You forgot to also change the *required access* from PRINTER_ACE_FULL_CONTROL
- to PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT before doing the check.
- This took me 3 hours to find !!!!! JRA.
- */
-
- if (required_access & PRINTER_ACE_FULL_CONTROL) {
- required_access |= (PRINTER_ACE_MANAGE_DOCUMENTS | PRINTER_ACE_PRINT);
- required_access &= ~PRINTER_ACE_FULL_CONTROL;
- }
-
if (secdesc && secdesc->sec && secdesc->sec->dacl &&
secdesc->sec->dacl->ace) {
for(i = 0; i < secdesc->sec->dacl->num_aces; i++) {
@@ -2271,14 +2304,46 @@ BOOL print_access_check(struct current_user *user, int snum,
}
}
- /* Check access */
+ if ((result = se_access_check(secdesc->sec, user, required_access,
+ &access_granted, &status))) {
+ goto done;
+ }
+
+ /* Check against NT5 ACE mask values. From observation these
+ values are:
+
+ Access Type ACE Mask Constant
+ -------------------------------------
+ Full Control 0x000f000c PRINTER_ACE_NT5_FULL_CONTROL
+ Print 0x00020008 PRINTER_ACE_NT5_PRINT
+ Manage Documents 0x00020000 PRINTER_ACE_NT5_MANAGE_DOCUMENTS
+
+ NT5 likes to rewrite the security descriptor and change the ACE
+ masks from NT4 format to NT5 format making them unreadable by
+ NT4 clients. */
+
+ switch (access_type) {
+ case PRINTER_ACCESS_USE:
+ required_access = PRINTER_ACE_NT5_PRINT;
+ break;
+ case PRINTER_ACCESS_ADMINISTER:
+ required_access = PRINTER_ACE_NT5_FULL_CONTROL;
+ break;
+ case JOB_ACCESS_ADMINISTER:
+ required_access = PRINTER_ACE_NT5_MANAGE_DOCUMENTS;
+ break;
+ }
result = se_access_check(secdesc->sec, user, required_access,
&access_granted, &status);
+ /* Check access */
+
+ done:
DEBUG(4, ("access check was %s\n", result ? "SUCCESS" : "FAILURE"));
-
+
/* Free mallocated memory */
+
free_sec_desc_buf(&secdesc);
if (!result)
diff --git a/source3/printing/printing.c b/source3/printing/printing.c
index cf3748ed16..406cbf2c80 100644
--- a/source3/printing/printing.c
+++ b/source3/printing/printing.c
@@ -507,7 +507,7 @@ BOOL print_job_delete(struct current_user *user, int jobid)
owns their job. */
if (!owner &&
- !print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
+ !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
DEBUG(3, ("delete denied by security descriptor\n"));
return False;
}
@@ -542,7 +542,7 @@ BOOL print_job_pause(struct current_user *user, int jobid)
owner = is_owner(user->uid, jobid);
if (!owner &&
- !print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
+ !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
DEBUG(3, ("pause denied by security descriptor\n"));
return False;
}
@@ -579,7 +579,7 @@ BOOL print_job_resume(struct current_user *user, int jobid)
owner = is_owner(user->uid, jobid);
if (!is_owner(user->uid, jobid) &&
- !print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
+ !print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
DEBUG(3, ("resume denied by security descriptor\n"));
return False;
}
@@ -624,9 +624,9 @@ int print_job_start(struct current_user *user, int snum, char *jobname)
errno = 0;
- if (!print_access_check(user, snum, PRINTER_ACE_PRINT)) {
+ if (!print_access_check(user, snum, PRINTER_ACCESS_USE)) {
DEBUG(3, ("job start denied by security descriptor\n"));
- return False;
+ return -1;
}
path = lp_pathname(snum);
@@ -665,6 +665,7 @@ int print_job_start(struct current_user *user, int snum, char *jobname)
/* lock the database */
tdb_writelock(tdb);
+ next_jobnum:
next_jobid = tdb_fetch_int(tdb, "INFO/nextjob");
if (next_jobid == -1) next_jobid = 1;
@@ -684,17 +685,20 @@ int print_job_start(struct current_user *user, int snum, char *jobname)
we unlink first to cope with old spool files and also to beat
a symlink security hole - it allows us to use O_EXCL
+ There may be old spool files owned by other users lying around.
*/
slprintf(pjob.filename, sizeof(pjob.filename), "%s/%s%d",
path, PRINT_SPOOL_PREFIX, jobid);
if (unlink(pjob.filename) == -1 && errno != ENOENT) {
- goto fail;
+ goto next_jobnum;
}
pjob.fd = sys_open(pjob.filename,O_WRONLY|O_CREAT|O_EXCL,0600);
if (pjob.fd == -1) goto fail;
print_job_store(jobid, &pjob);
+ tdb_writeunlock(tdb);
+
/*
* If the printer is marked as postscript output a leading
* file identifier to ensure the file is treated as a raw
@@ -706,7 +710,6 @@ int print_job_start(struct current_user *user, int snum, char *jobname)
print_job_write(jobid, "%!\n",3);
}
- tdb_writeunlock(tdb);
return jobid;
fail:
@@ -896,7 +899,7 @@ BOOL print_queue_pause(struct current_user *user, int snum, int *errcode)
if (!user) return False;
- if (!print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
+ if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
*errcode = ERROR_ACCESS_DENIED;
return False;
}
@@ -917,7 +920,7 @@ BOOL print_queue_resume(struct current_user *user, int snum, int *errcode)
{
int ret;
- if (!print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
+ if (!print_access_check(user, snum, PRINTER_ACCESS_ADMINISTER)) {
*errcode = ERROR_ACCESS_DENIED;
return False;
}
@@ -940,14 +943,11 @@ BOOL print_queue_purge(struct current_user *user, int snum, int *errcode)
print_status_struct status;
int njobs, i;
- if (!print_access_check(user, snum, PRINTER_ACE_MANAGE_DOCUMENTS)) {
- *errcode = ERROR_ACCESS_DENIED;
- return False;
- }
-
njobs = print_queue_status(snum, &queue, &status);
for (i=0;i<njobs;i++) {
- print_job_delete1(queue[i].job);
+ if (print_access_check(user, snum, JOB_ACCESS_ADMINISTER)) {
+ print_job_delete1(queue[i].job);
+ }
}
print_cache_flush(snum);
diff --git a/source3/rpc_server/srv_lsa.c b/source3/rpc_server/srv_lsa.c
index f37bb249ba..a7abc614e3 100644
--- a/source3/rpc_server/srv_lsa.c
+++ b/source3/rpc_server/srv_lsa.c
@@ -219,7 +219,7 @@ static void init_lsa_rid2s(DOM_R_REF *ref, DOM_RID2 *rid2,
pstring full_name;
fstring dom_name;
fstring user;
- uint8 sid_name_use = SID_NAME_UNKNOWN;
+ enum SID_NAME_USE sid_name_use = SID_NAME_UNKNOWN;
pstrcpy(full_name, dos_unistr2_to_str(&name[i]));
@@ -298,7 +298,7 @@ static void init_lsa_trans_names(DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *trn,
uint32 rid = 0xffffffff;
int dom_idx = -1;
fstring name, dom_name;
- uint8 sid_name_use = 0;
+ enum SID_NAME_USE sid_name_use = 0;
/* Lookup sid from winbindd */
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index 0938b37ab3..1f19be1188 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -22,7 +22,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-
#include "includes.h"
extern int DEBUGLEVEL;
@@ -2936,10 +2935,11 @@ uint32 _spoolss_startdocprinter(POLICY_HND *handle, uint32 level,
Printer->jobid = print_job_start(&user, snum, jobname);
- /* need to map error codes properly - for now give out of
- memory as I don't know the correct codes (tridge) */
+ /* An error occured in print_job_start() so return an appropriate
+ NT error code. */
+
if (Printer->jobid == -1) {
- return ERROR_NOT_ENOUGH_MEMORY;
+ return map_nt_error_from_unix(errno);
}
Printer->document_started=True;
@@ -3082,7 +3082,7 @@ static uint32 update_printer_sec(POLICY_HND *handle, uint32 level,
descriptor. By experimentation with two NT machines, the user
requires Full Access to the printer to change security
information. */
- if (!print_access_check(&user, snum, PRINTER_ACE_FULL_CONTROL)) {
+ if (!print_access_check(&user, snum, PRINTER_ACCESS_ADMINISTER)) {
result = ERROR_ACCESS_DENIED;
goto done;
}
@@ -3172,13 +3172,13 @@ static BOOL add_printer_hook(NT_PRINTER_INFO_LEVEL *printer)
numlines = 0;
qlines = file_lines_load(tmp_file, &numlines);
DEBUGADD(10,("Lines returned = [%d]\n", numlines));
- DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
unlink(tmp_file);
if(numlines) {
// Set the portname to what the script says the portname should be
strncpy(printer->info_2->portname, qlines[0], sizeof(printer->info_2->portname));
+ DEBUGADD(6,("Line[0] = [%s]\n", qlines[0]));
// Send SIGHUP to process group... is there a better way?
kill(0, SIGHUP);
@@ -3226,7 +3226,7 @@ static uint32 update_printer(POLICY_HND *handle, uint32 level,
goto done;
}
- if (!print_access_check(NULL, snum, PRINTER_ACE_FULL_CONTROL)) {
+ if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
DEBUG(3, ("printer property change denied by security "
"descriptor\n"));
result = ERROR_ACCESS_DENIED;
@@ -4028,7 +4028,6 @@ static uint32 enumports_level_1(NEW_BUFFER *buffer, uint32 offered, uint32 *need
numlines = 0;
qlines = file_lines_load(tmp_file, &numlines);
DEBUGADD(10,("Lines returned = [%d]\n", numlines));
- DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
unlink(tmp_file);
@@ -4127,7 +4126,6 @@ static uint32 enumports_level_2(NEW_BUFFER *buffer, uint32 offered, uint32 *need
numlines = 0;
qlines = file_lines_load(tmp_file, &numlines);
DEBUGADD(10,("Lines returned = [%d]\n", numlines));
- DEBUGADD(10,("Line[0] = [%s]\n", qlines[0]));
DEBUGADD(10,("Unlinking port file [%s]\n", tmp_file));
unlink(tmp_file);
@@ -4247,7 +4245,7 @@ static uint32 spoolss_addprinterex_level_2( const UNISTR2 *uni_srv_name,
}
/* you must be a printer admin to add a new printer */
- if (!print_access_check(NULL, snum, PRINTER_ACE_FULL_CONTROL)) {
+ if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
free_a_printer(&printer,2);
return ERROR_ACCESS_DENIED;
}
@@ -4564,7 +4562,7 @@ uint32 _spoolss_setprinterdata( POLICY_HND *handle,
if (!get_printer_snum(handle, &snum))
return ERROR_INVALID_HANDLE;
- if (!print_access_check(NULL, snum, PRINTER_ACE_FULL_CONTROL)) {
+ if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) {
DEBUG(3, ("security descriptor change denied by existing "
"security descriptor\n"));
return ERROR_ACCESS_DENIED;
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
index 6595163ba9..54bfa3155b 100644
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -540,7 +540,7 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),
strerror(errno)));
desc->errcode=NERR_notsupported;
- return;
+ goto done;
}
/* lookup the long printer driver name in the file description */
@@ -651,14 +651,16 @@ static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
SERVICE(snum),count));
desc->errcode=NERR_Success;
- file_lines_free(lines);
- return;
+ goto done;
}
err:
DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
desc->errcode=NERR_notsupported;
+
+ done:
+ safe_free(info);
file_lines_free(lines);
}
@@ -741,7 +743,7 @@ static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
/* This function returns the number of files for a given driver */
static int get_printerdrivernumber(int snum)
{
- int i;
+ int i, result = 0;
BOOL ok = False;
pstring tok;
char *p;
@@ -777,7 +779,7 @@ static int get_printerdrivernumber(int snum)
if (!lines)
{
DEBUG(3,("Can't open %s - %s\n", lp_driverfile(snum),strerror(errno)));
- return 0;
+ goto done;
}
/* lookup the long printer driver name in the file description */
@@ -800,22 +802,24 @@ static int get_printerdrivernumber(int snum)
while (*p && i) {
if (*p++ == ':') i--;
}
- if (!*p || i)
- goto err;
+ if (!*p || i) {
+ DEBUG(3,("Can't determine number of printer driver files\n"));
+ goto done;
+ }
/* count the number of files */
while (next_token(&p,tok,",",sizeof(tok)))
i++;
- file_lines_free(lines);
- return(i);
+ result = i;
}
- err:
+ done:
- DEBUG(3,("Can't determine number of printer driver files\n"));
+ safe_free(info);
file_lines_free(lines);
- return (0);
+
+ return result;
}
static BOOL api_DosPrintQGetInfo(connection_struct *conn,