From 2506c61ab3bd667d54c5e004cc80ce5e40643b5d Mon Sep 17 00:00:00 2001 From: David O'Neill Date: Mon, 29 Jan 2001 21:34:08 +0000 Subject: Changes from APPLIANCE_HEAD: source/include/proto.h - make proto source/printing/nt_printing.c source/rpc_server/srv_spoolss_nt.c - Fix for the overwriting of printerdata entries when WinNT and Win2k are modifying printer parameters on PCL printers. Turns out that Win2k creates a printer with a NULL devmode entry and then expects to set it on *OPEN* (yes this is insane). So we cannot return a "default" devmode for a printer - and we must allow an open to set it. source/tdb/tdb.c - Show freelist in an easier format. Show total free. - When storing a new record, allocate memory for the key + data before the tdb_allocate() as if the malloc fails a (sparse) hole is left in the tdb. source/tdb/tdbtool.c - Show freelist in an easier format. Show total free. source/tdb/Makefile - cleaned up Makefile dependancies source/smbd/lanman.c - Fix for Win9x corrupting it's own parameter string. source/printing/printfsp.c source/printing/printing.c source/rpc_server/srv_spoolss_nt.c source/smbd/close.c - Added normal close parameter into print_fsp_end() which treats an abnormal close as error condition and deletes the spool file. (This used to be commit 025f7a092ad258ff774e3f5e53737f8210cc8af6) --- source3/printing/nt_printing.c | 105 ++++++++++++++++++++++++++++++++--------- source3/printing/printfsp.c | 4 +- source3/printing/printing.c | 13 +++-- 3 files changed, 94 insertions(+), 28 deletions(-) (limited to 'source3/printing') diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index eb4b243f2e..ff24849f0b 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -1722,8 +1722,6 @@ static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) char *buf; int buflen, len, ret; TDB_DATA kbuf, dbuf; - NT_PRINTER_INFO_LEVEL_2 *old_printer = NULL; - NT_DEVICEMODE *devmode = NULL; /* * in addprinter: no servername and the printer is the name @@ -1779,20 +1777,7 @@ static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) info->datatype, info->parameters); - /* do not write a NULL devicemode if there was previously - a valid one. Windows 2000 likes to send setprinter calls - with NULL devicemodes (e.g. HP 4050 PCL6 driver) --jerry - - We need to get the previously saved information for - this printer if the devicemode is NULL */ - devmode = info->devmode; - if (!devmode && info->sharename) - { - get_a_printer_2(&old_printer, info->sharename); - if (old_printer) - devmode = old_printer->devmode; - } - len += pack_devicemode(devmode, buf+len, buflen-len); + len += pack_devicemode(info->devmode, buf+len, buflen-len); len += pack_specifics(info->specific, buf+len, buflen-len); @@ -1821,9 +1806,6 @@ static uint32 update_a_printer_2(NT_PRINTER_INFO_LEVEL_2 *info) DEBUG(8,("packed printer [%s] with driver [%s] portname=[%s] len=%d\n", info->sharename, info->drivername, info->portname, len)); - if (old_printer) - free_nt_printer_info_level_2(&old_printer); - return ret; } @@ -1977,8 +1959,7 @@ NT_DEVICEMODE *construct_nt_devicemode(const fstring default_devicename) nt_devmode->panningwidth = 0; nt_devmode->panningheight = 0; - nt_devmode->private=NULL; - + nt_devmode->private = NULL; return nt_devmode; } @@ -2110,7 +2091,7 @@ static int unpack_devicemode(NT_DEVICEMODE **nt_devmode, char *buf, int buflen) if (devmode.private) { /* the len in tdb_unpack is an int value and - * devmoce.driverextra is only a short + * devmode.driverextra is only a short */ len += tdb_unpack(buf+len, buflen-len, "B", &extra_len, &devmode.private); devmode.driverextra=(uint16)extra_len; @@ -2198,8 +2179,18 @@ static uint32 get_a_printer_2_default(NT_PRINTER_INFO_LEVEL_2 **info_ptr, fstrin info.default_priority = 1; info.setuptime = (uint32)time(NULL); +#if 1 /* JRA - NO NOT CHANGE ! */ + info.devmode = NULL; +#else + /* + * We should not return a default devicemode, as this causes + * Win2K to not send the correct one on PCL drivers. It needs to + * see a null devicemode so it can then overwrite the devicemode + * on OpenPrinterEx. Yes this *is* insane :-). JRA. + */ if ((info.devmode = construct_nt_devicemode(info.printername)) == NULL) goto fail; +#endif if (!nt_printing_getsec(sharename, &info.secdesc_buf)) goto fail; @@ -2421,9 +2412,13 @@ uint32 add_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level) NTTIME time_nt; time_t time_unix = time(NULL); unix_to_nt_time(&time_nt, time_unix); - printer.info_2->changeid=time_nt.low; + if (printer.info_2->changeid==time_nt.low) + printer.info_2->changeid++; + else + printer.info_2->changeid=time_nt.low; printer.info_2->c_setprinter++; + result=update_a_printer_2(printer.info_2); break; } @@ -3145,5 +3140,69 @@ BOOL print_time_access_check(int snum) return ok; } +/**************************************************************************** + Attempt to write a default device. +*****************************************************************************/ + +uint32 printer_write_default_dev(int snum, const PRINTER_DEFAULT *printer_default) +{ + NT_PRINTER_INFO_LEVEL *printer = NULL; + + uint32 result = 0; + + /* + * Don't bother if no default devicemode was sent. + */ + + if (printer_default->devmode_cont.devmode == NULL) + return 0; + + if (get_a_printer(&printer, 2, lp_servicename(snum))!=0) + return ERROR_ACCESS_DENIED; + + /* + * Just ignore it if we already have a devmode. + */ + + if (printer->info_2->devmode != NULL) + goto done; + + /* + * We don't have a devicemode and we're trying to write + * one. Check we have the access needed. + */ + + if (!print_access_check(NULL, snum, PRINTER_ACCESS_ADMINISTER)) { + DEBUG(5,("printer_write_default_dev: Access denied for printer %s\n", + lp_servicename(snum) )); + result = ERROR_ACCESS_DENIED; + goto done; + } + + /* + * Convert the on the wire devicemode format to the internal one. + */ + + if (!convert_devicemode(printer->info_2->printername, + printer_default->devmode_cont.devmode, + &printer->info_2->devmode)) { + result = ERROR_NOT_ENOUGH_MEMORY; + goto done; + } + + /* + * Finally write back to the tdb. + */ + + if (add_a_printer(*printer, 2)!=0) { + result = ERROR_ACCESS_DENIED; + goto done; + } + + done: + + free_a_printer(&printer, 2); + return result; +} #undef OLD_NTDOMAIN diff --git a/source3/printing/printfsp.c b/source3/printing/printfsp.c index 9b5a4877ee..f6ab69fd93 100644 --- a/source3/printing/printfsp.c +++ b/source3/printing/printfsp.c @@ -82,9 +82,9 @@ files_struct *print_fsp_open(connection_struct *conn,char *jobname) /**************************************************************************** print a file - called on closing the file ****************************************************************************/ -void print_fsp_end(files_struct *fsp) +void print_fsp_end(files_struct *fsp, BOOL normal_close) { - print_job_end(fsp->print_jobid); + print_job_end(fsp->print_jobid, normal_close); if (fsp->fsp_name) { string_free(&fsp->fsp_name); diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 46d872df7c..4dbb01e839 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -950,9 +950,11 @@ int print_job_start(struct current_user *user, int snum, char *jobname) /**************************************************************************** Print a file - called on closing the file. This spools the job. + If normal close is false then we're tearing down the jobs - treat as an + error. ****************************************************************************/ -BOOL print_job_end(int jobid) +BOOL print_job_end(int jobid, BOOL normal_close) { struct printjob *pjob = print_job_find(jobid); int snum, ret; @@ -970,12 +972,17 @@ BOOL print_job_end(int jobid) snum = print_job_snum(jobid); - if (sys_fstat(pjob->fd, &sbuf) == 0) { + if (normal_close && (sys_fstat(pjob->fd, &sbuf) == 0)) { pjob->size = sbuf.st_size; close(pjob->fd); pjob->fd = -1; } else { - /* Couldn't stat the job file, so something has gone wrong. Cleanup */ + + /* + * Not a normal close or we couldn't stat the job file, + * so something has gone wrong. Cleanup. + */ + unlink(pjob->filename); tdb_delete(tdb, print_key(jobid)); return False; -- cgit