From 7207662504f585352b0ceeb99f8998ef58db7f15 Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 11 Jul 2002 03:27:12 +0000 Subject: [PATCH] all that is left to do is to actually perform the file deletion now. I have the file list. One more commit should do it. --- source/printing/nt_printing.c | 170 +++++++++++++++++++++++++++++++++---- source/rpc_parse/parse_spoolss.c | 4 + source/rpc_server/srv_spoolss_nt.c | 28 +++++- 3 files changed, 183 insertions(+), 19 deletions(-) diff --git a/source/printing/nt_printing.c b/source/printing/nt_printing.c index fe90625e78a..17a16b84bce 100644 --- a/source/printing/nt_printing.c +++ b/source/printing/nt_printing.c @@ -3461,21 +3461,130 @@ BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i ) return False; } + +/********************************************************************** + 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 ) +{ + char *s; + + if ( !info ) + return False; + + if ( strequal(file, info->driverpath) ) + return True; + + if ( strequal(file, info->datafile) ) + return True; + + if ( strequal(file, info->configfile) ) + return True; + + if ( strequal(file, info->helpfile) ) + return True; + + s = (char*) info->dependentfiles; + + if ( s ) { + while ( *s ) + { + if ( strequal(file, s) ) + return True; + s += strlen(s) + 1; + } + } + + return False; + +} + +/********************************************************************** + Utility function to remove the dependent file pointed to by the + input parameter from the list + *********************************************************************/ + +static void trim_dependent_file( char* s ) +{ + char *p; + + /* set p to the next character string in the list */ + + p = s + strlen( s ) + 1; + + /* check to see that we have another string to copy back */ + + if ( *p == '\0' ) + { + /* loop over s copying characters from p to s */ + while ( *p!='\0' && *(p+1)!='\0' ) + *s++ = *p++; + } + + /* add the two trailing NULL's */ + + *s = '\0'; + *(s+1) = '\0'; +} + /********************************************************************** Check if any of the files used by src are also used by drv *********************************************************************/ -static BOOL check_driver_file_overlap( 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; + char *s; - - return False; + 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; + fstrcpy( src->driverpath, "" ); + } + + if ( drv_file_in_use(src->datafile, drv) ) { + in_use = True; + fstrcpy( src->datafile, "" ); + } + + if ( drv_file_in_use(src->configfile, drv) ) { + in_use = True; + fstrcpy( src->configfile, "" ); + } + + s = (char*)src->dependentfiles; + + if ( s ) { + while ( *s ) + { + if ( drv_file_in_use(s, drv) ) { + in_use = True; + trim_dependent_file( s ); + } + else + s += strlen(s) + 1; + } + } + + + return in_use; } /**************************************************************************** Determine whether or not a particular driver files are currently being - used by any other driver. Requires using the full path from [print$] + 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 ****************************************************************************/ BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ) @@ -3500,7 +3609,7 @@ BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ) DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", ndrivers, info->environment, version)); - if(ndrivers == -1) + if (ndrivers == -1) continue; /* check each driver for overlap in files */ @@ -3512,18 +3621,23 @@ BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ) ZERO_STRUCT(driver); if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], - info->environment, version)) ) + 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 ( check_driver_file_overlap(info, driver.info_3) ) { - free_a_printer_driver(driver, 3); - SAFE_FREE( list ); - return True; + if ( !strequal(info->name, driver.info_3->name) + || (info->cversion != driver.info_3->cversion) ) + { + if ( trim_overlap_drv_files(info, driver.info_3) ) { + free_a_printer_driver(driver, 3); + SAFE_FREE( list ); + return True; + } } free_a_printer_driver(driver, 3); @@ -3545,7 +3659,31 @@ BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ) static NTSTATUS delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i ) { - + char *s; + + if ( !i ) + return NT_STATUS_ACCESS_DENIED; + + DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", i->name, i->cversion)); + + + if ( *i->driverpath ) + DEBUG(10,("deleting [%s]\n", i->driverpath)); + if ( *i->configfile ) + DEBUG(10,("deleting [%s]\n", i->configfile)); + if ( *i->datafile ) + DEBUG(10,("deleting [%s]\n", i->datafile)); + if ( *i->helpfile ) + DEBUG(10,("deleting [%s]\n", i->helpfile)); + + s = (char*)i->dependentfiles; + + if ( s ) { + while ( *s ) { + DEBUG(10,("deleting dependent file [%s]\n", s)); + s += strlen( s ) + 1; + } + } return NT_STATUS_OK; } @@ -3565,7 +3703,9 @@ WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, BOOL delete_fil get_short_archi(arch, i->environment); slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, arch, i->cversion, i->name); - DEBUG(5,("delete_printer_driver: key = [%s]\n", key)); + + DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n", + key, delete_files ? "TRUE" : "FALSE" )); kbuf.dptr=key; kbuf.dsize=strlen(key)+1; @@ -3575,9 +3715,6 @@ WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, BOOL delete_fil return WERR_ACCESS_DENIED; } - DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n", - i->name)); - /* * now delete any associated files if delete_files == True * even if this part failes, we return succes because the @@ -3587,6 +3724,9 @@ WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, BOOL delete_fil if ( delete_files ) delete_driver_files( i ); + DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n", + i->name)); + return WERR_OK; } /**************************************************************************** diff --git a/source/rpc_parse/parse_spoolss.c b/source/rpc_parse/parse_spoolss.c index c74249878a9..b10a5c43771 100644 --- a/source/rpc_parse/parse_spoolss.c +++ b/source/rpc_parse/parse_spoolss.c @@ -1516,6 +1516,10 @@ BOOL spoolss_io_q_deleteprinterdriverex(char *desc, SPOOL_Q_DELETEPRINTERDRIVERE return False; if(!smb_io_unistr2("driver", &q_u->driver, True, ps, depth)) return False; + + if (!prs_align(ps)) + return False; + if(!prs_uint32("delete_flags ", ps, depth, &q_u->delete_flags)) return False; if(!prs_uint32("version ", ps, depth, &q_u->version)) diff --git a/source/rpc_server/srv_spoolss_nt.c b/source/rpc_server/srv_spoolss_nt.c index 8acdd9d5ab4..a37d8e9c19b 100644 --- a/source/rpc_server/srv_spoolss_nt.c +++ b/source/rpc_server/srv_spoolss_nt.c @@ -1590,6 +1590,7 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV NT_PRINTER_DRIVER_INFO_LEVEL info; int version; uint32 flags = q_u->delete_flags; + BOOL delete_files; unistr2_to_ascii(driver, &q_u->driver, sizeof(driver)-1 ); unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 ); @@ -1614,11 +1615,30 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV if ( printer_driver_in_use(info.info_3) ) return WERR_PRINTER_DRIVER_IN_USE; - if ( printer_driver_files_in_use(info.info_3) ) - /* no idea of the correct error here */ - return WERR_ACCESS_DENIED; + /* + * we have a couple of cases to consider. + * (1) Are any files in use? If so and DPD_DELTE_ALL_FILE is set, + * then the delete should fail if **any** files overlap with + * other drivers + * (2) If DPD_DELTE_UNUSED_FILES is sert, then delete all + * non-overlapping files + * (3) If neither DPD_DELTE_ALL_FILE nor DPD_DELTE_ALL_FILES + * is set, the do not delete any files + * Refer to MSDN docs on DeletePrinterDriverEx() for details. + */ + + delete_files = flags & (DPD_DELETE_ALL_FILES|DPD_DELETE_UNUSED_FILES); + + if ( delete_files ) + { + /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */ + + if ( printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) + /* no idea of the correct error here */ + return WERR_ACCESS_DENIED; + } - return delete_printer_driver(info.info_3, True); + return delete_printer_driver(info.info_3, delete_files); } -- 2.11.4.GIT