all that is left to do is to actually perform the
authorGerald Carter <jerry@samba.org>
Thu, 11 Jul 2002 03:27:12 +0000 (03:27 +0000)
committerGerald Carter <jerry@samba.org>
Thu, 11 Jul 2002 03:27:12 +0000 (03:27 +0000)
file deletion now.  I have the file list.
One more commit should do it.

source/printing/nt_printing.c
source/rpc_parse/parse_spoolss.c
source/rpc_server/srv_spoolss_nt.c

index fe90625e78a3a40bb867abf974e63992de99f583..17a16b84bcef6277427d8233d59f1a91b4d42baa 100644 (file)
@@ -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;
 }
 /****************************************************************************
index c74249878a99179e3d14494fee08759741177844..b10a5c4377158414e42d6879b798125019720163 100644 (file)
@@ -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))
index 8acdd9d5ab4de0c0e3692d0b8e5098d113d95139..a37d8e9c19b1e26dac68d713590d8b3c9aed2a53 100644 (file)
@@ -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);
 }