updated the 3.0 branch from the head branch - ready for alpha18
[nivanova/samba-autobuild/.git] / source3 / printing / nt_printing.c
index aff3bdebedf513195c959c7abeae32e31e66668f..ff08b99eb0fbe996d8b01848c09a673abf1d23e9 100644 (file)
@@ -1,8 +1,9 @@
 /*
- *  Unix SMB/Netbios implementation.
+ *  Unix SMB/CIFS implementation.
  *  RPC Pipe client / server routines
  *  Copyright (C) Andrew Tridgell              1992-2000,
  *  Copyright (C) Jean François Micouleau      1998-2000.
+ *  Copyright (C) Gerald Carter                     2002.
  *
  *  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
@@ -44,6 +45,7 @@ static TDB_CONTEXT *tdb_printers; /* used for printers files */
 
 GENERIC_MAPPING printer_generic_mapping = {
        PRINTER_READ,
+       PRINTER_WRITE,
        PRINTER_EXECUTE,
        PRINTER_ALL_ACCESS
 };
@@ -55,6 +57,22 @@ STANDARD_MAPPING printer_std_mapping = {
        PRINTER_ALL_ACCESS
 };
 
+/* Map generic permissions to print server object specific permissions */
+
+GENERIC_MAPPING printserver_generic_mapping = {
+       SERVER_READ,
+       SERVER_WRITE,
+       SERVER_EXECUTE,
+       SERVER_ALL_ACCESS
+};
+
+STANDARD_MAPPING printserver_std_mapping = {
+       SERVER_READ,
+       SERVER_WRITE,
+       SERVER_EXECUTE,
+       SERVER_ALL_ACCESS
+};
+
 /* We need one default form to support our default printer. Msoft adds the
 forms it wants and in the ORDER it wants them (note: DEVMODE papersize is an
 array index). Letter is always first, so (for the current code) additions
@@ -297,6 +315,11 @@ BOOL nt_printing_init(void)
 
        update_c_setprinter(True);
 
+       /*
+        * register callback to handle updating printers as new
+        * drivers are installed
+        */
+       message_register(MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer);
        return True;
 }
 
@@ -1042,7 +1065,7 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,
        /* Null password is ok - we are already an authenticated user... */
        null_pw = data_blob(NULL, 0);
        become_root();
-       conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
+       conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
        unbecome_root();
 
        if (conn == NULL) {
@@ -1360,7 +1383,7 @@ BOOL move_driver_to_download_area(NT_PRINTER_DRIVER_INFO_LEVEL driver_abstract,
 
        become_root();
        null_pw = data_blob(NULL, 0);
-       conn = make_connection("print$", null_pw, "A:", user->vuid, &nt_status);
+       conn = make_connection_with_chdir("print$", null_pw, "A:", user->vuid, &nt_status);
        unbecome_root();
 
        if (conn == NULL) {
@@ -1661,13 +1684,13 @@ static uint32 add_a_printer_driver_6(NT_PRINTER_DRIVER_INFO_LEVEL_6 *driver)
 
 /****************************************************************************
 ****************************************************************************/
-static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch)
+static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring driver, fstring arch)
 {
        NT_PRINTER_DRIVER_INFO_LEVEL_3 info;
 
        ZERO_STRUCT(info);
 
-       fstrcpy(info.name, in_prt);
+       fstrcpy(info.name, driver);
        fstrcpy(info.defaultdatatype, "RAW");
        
        fstrcpy(info.driverpath, "");
@@ -1688,7 +1711,7 @@ static WERROR get_a_printer_driver_3_default(NT_PRINTER_DRIVER_INFO_LEVEL_3 **in
 
 /****************************************************************************
 ****************************************************************************/
-static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring in_prt, fstring in_arch, uint32 version)
+static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, fstring drivername, fstring arch, uint32 version)
 {
        NT_PRINTER_DRIVER_INFO_LEVEL_3 driver;
        TDB_DATA kbuf, dbuf;
@@ -1699,21 +1722,19 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
 
        ZERO_STRUCT(driver);
 
-       get_short_archi(architecture, in_arch);
+       get_short_archi(architecture, arch);
 
-       DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, in_prt));
+       DEBUG(8,("get_a_printer_driver_3: [%s%s/%d/%s]\n", DRIVERS_PREFIX, architecture, version, drivername));
 
-       slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, in_prt);
+       slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, architecture, version, drivername);
 
        kbuf.dptr = key;
        kbuf.dsize = strlen(key)+1;
        
        dbuf = tdb_fetch(tdb_drivers, kbuf);
-#if 0
-       if (!dbuf.dptr) return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
-#else
-       if (!dbuf.dptr) return WERR_ACCESS_DENIED;
-#endif
+       if (!dbuf.dptr) 
+               return WERR_ACCESS_DENIED;
+
        len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff",
                          &driver.cversion,
                          driver.name,
@@ -1749,7 +1770,7 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr,
        if (len != dbuf.dsize) {
                        SAFE_FREE(driver.dependentfiles);
 
-               return get_a_printer_driver_3_default(info_ptr, in_prt, in_arch);
+               return get_a_printer_driver_3_default(info_ptr, drivername, arch);
        }
 
        *info_ptr = (NT_PRINTER_DRIVER_INFO_LEVEL_3 *)memdup(&driver, sizeof(driver));
@@ -1839,19 +1860,19 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32
                        else {
                                info3=driver.info_3;
                        
-                               DEBUGADD(106,("version:[%d]\n",         info3->cversion));
-                               DEBUGADD(106,("name:[%s]\n",            info3->name));
-                               DEBUGADD(106,("environment:[%s]\n",     info3->environment));
-                               DEBUGADD(106,("driverpath:[%s]\n",      info3->driverpath));
-                               DEBUGADD(106,("datafile:[%s]\n",        info3->datafile));
-                               DEBUGADD(106,("configfile:[%s]\n",      info3->configfile));
-                               DEBUGADD(106,("helpfile:[%s]\n",        info3->helpfile));
-                               DEBUGADD(106,("monitorname:[%s]\n",     info3->monitorname));
-                               DEBUGADD(106,("defaultdatatype:[%s]\n", info3->defaultdatatype));
+                               DEBUGADD(20,("version:[%d]\n",         info3->cversion));
+                               DEBUGADD(20,("name:[%s]\n",            info3->name));
+                               DEBUGADD(20,("environment:[%s]\n",     info3->environment));
+                               DEBUGADD(20,("driverpath:[%s]\n",      info3->driverpath));
+                               DEBUGADD(20,("datafile:[%s]\n",        info3->datafile));
+                               DEBUGADD(20,("configfile:[%s]\n",      info3->configfile));
+                               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(106,("dependentfile:[%s]\n",
+                                       DEBUGADD(20,("dependentfile:[%s]\n",
                                                      info3->dependentfiles[i]));
                                }
                                result=0;
@@ -1859,7 +1880,7 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32
                        break;
                }
                default:
-                       DEBUGADD(106,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
+                       DEBUGADD(20,("dump_a_printer_driver: Level %u not implemented\n", (unsigned int)level));
                        result=1;
                        break;
        }
@@ -2816,7 +2837,7 @@ WERROR mod_a_printer(NT_PRINTER_INFO_LEVEL printer, uint32 level)
  Initialize printer devmode & data with previously saved driver init values.
 ****************************************************************************/
 
-static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
+static BOOL set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
 {
        int                     len = 0;
        pstring                 key;
@@ -2869,9 +2890,14 @@ static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
         * NT/2k does not change out the entire DeviceMode of a printer
         * when changing the driver.  Only the driverextra, private, & 
         * driverversion fields.   --jerry  (Thu Mar 14 08:58:43 CST 2002)
+        *
+        * Later e4xamination revealed that Windows NT/2k does reset the
+        * the printer's device mode, bit **only** when you change a 
+        * property of the device mode such as the page orientation.
+        * --jerry
         */
 
-#if 0  /* JERRY */
+#if 1  /* JERRY */
 
        /* 
         *      Bind the saved DEVMODE to the new the printer.
@@ -2923,25 +2949,49 @@ static uint32 set_driver_init_2(NT_PRINTER_INFO_LEVEL_2 *info_ptr)
  is bound to the new printer.
 ****************************************************************************/
 
-uint32 set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
+BOOL set_driver_init(NT_PRINTER_INFO_LEVEL *printer, uint32 level)
 {
-       uint32 result;
+       BOOL result = False;
        
        switch (level)
        {
                case 2:
-               {
                        result=set_driver_init_2(printer->info_2);
                        break;
-               }
+                       
                default:
-                       result=1;
+                       DEBUG(0,("set_driver_init: Programmer's error!  Unknown driver_init level [%d]\n",
+                               level));
                        break;
        }
        
        return result;
 }
 
+/****************************************************************************
+ Delete driver init data stored for a specified driver
+****************************************************************************/
+
+BOOL del_driver_init(char *drivername)
+{
+       pstring key;
+       TDB_DATA kbuf;
+
+       if (!drivername || !*drivername) {
+               DEBUG(3,("del_driver_init: No drivername specified!\n"));
+               return False;
+       }
+
+       slprintf(key, sizeof(key)-1, "%s%s", DRIVER_INIT_PREFIX, drivername);
+
+       kbuf.dptr = key;
+       kbuf.dsize = strlen(key)+1;
+
+       DEBUG(6,("del_driver_init: Removing driver init data for [%s]\n", drivername));
+
+       return (tdb_delete(tdb_drivers, kbuf) == 0);
+}
+
 /****************************************************************************
  Pack up the DEVMODE and specifics for a printer into a 'driver init' entry 
  in the tdb. Note: this is different from the driver entry and the printer
@@ -3284,17 +3334,31 @@ uint32 add_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
 /****************************************************************************
 ****************************************************************************/
 WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
-                            fstring printername, fstring architecture, uint32 version)
+                            fstring drivername, fstring architecture, uint32 version)
 {
        WERROR result;
        
        switch (level)
        {
                case 3:
-               {
-                       result=get_a_printer_driver_3(&driver->info_3, printername, architecture, version);
+                       /* 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, 
+                                               architecture, 3);
+                                               
+                               if ( !W_ERROR_IS_OK(result) ) {
+                                       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);                         
+                       }
                        break;
-               }
+                       
                default:
                        result=W_ERROR(1);
                        break;
@@ -3302,6 +3366,7 @@ WERROR get_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL *driver, uint32 level,
        
        if (W_ERROR_IS_OK(result))
                dump_a_printer_driver(*driver, level);
+               
        return result;
 }
 
@@ -3360,95 +3425,347 @@ uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level)
   Determine whether or not a particular driver is currently assigned
   to a printer
 ****************************************************************************/
-BOOL printer_driver_in_use (char *arch, char *driver)
+
+BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i )
 {
-       TDB_DATA kbuf, newkey, dbuf;
-       NT_PRINTER_INFO_LEVEL_2 info;
-       int ret;
+       int snum;
+       int n_services = lp_numservices();
+       NT_PRINTER_INFO_LEVEL *printer = NULL;
 
-       if (!tdb_printers)
-               if (!nt_printing_init())
-                       return False;
+       if ( !i ) 
+               return False;
 
-       DEBUG(5,("printer_driver_in_use: Beginning search through printers.tdb...\n"));
+       DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n"));
        
        /* loop through the printers.tdb and check for the drivername */
-       for (kbuf = tdb_firstkey(tdb_printers); kbuf.dptr;
-            newkey = tdb_nextkey(tdb_printers, kbuf), safe_free(kbuf.dptr), kbuf=newkey
+       
+       for (snum=0; snum<n_services; snum++
        {
-
-               dbuf = tdb_fetch(tdb_printers, kbuf);
-               if (!dbuf.dptr) 
+               if ( !(lp_snum_ok(snum) && lp_print_ok(snum) ) )
                        continue;
-
-               if (strncmp(kbuf.dptr, PRINTERS_PREFIX, strlen(PRINTERS_PREFIX)) != 0) 
+               
+               if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) )
                        continue;
+               
+               if ( !StrCaseCmp(i->name, printer->info_2->drivername) ) {
+                       free_a_printer( &printer, 2 );
+                       return True;
+               }
+               
+               free_a_printer( &printer, 2 );
+       }
+       
+       DEBUG(5,("printer_driver_in_use: Completed search through ntprinters.tdb...\n"));
+       
+       /* report that the driver is not in use by default */
+       
+       return False;
+}
 
-               ret = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddddddddddfffffPfffff",
-                       &info.attributes,
-                       &info.priority,
-                       &info.default_priority,
-                       &info.starttime,
-                       &info.untiltime,
-                       &info.status,
-                       &info.cjobs,
-                       &info.averageppm,
-                       &info.changeid,
-                       &info.c_setprinter,
-                       &info.setuptime,
-                       info.servername,
-                       info.printername,
-                       info.sharename,
-                       info.portname,
-                       info.drivername,
-                       info.comment,
-                       info.location,
-                       info.sepfile,
-                       info.printprocessor,
-                       info.datatype,
-                       info.parameters);
 
-               SAFE_FREE(dbuf.dptr);
+/**********************************************************************
+ 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 (ret == -1) {
-                       DEBUG (0,("printer_driver_in_use: tdb_unpack failed for printer %s\n",
-                                       info.printername));
-                       continue;
+       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 trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, 
+                                      NT_PRINTER_DRIVER_INFO_LEVEL_3 *drv )
+{
+       BOOL in_use = False;
+       char *s;
+       
+       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.  
+  
+  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 )
+{
+       int                             i;
+       int                             ndrivers;
+       uint32                          version;
+       fstring                         *list = NULL;
+       NT_PRINTER_DRIVER_INFO_LEVEL    driver;
+       
+       /* loop over all driver versions */
+       
+       DEBUG(5,("printer_driver_files_in_use: Beginning search through ntdrivers.tdb...\n"));
+       
+       for ( version=0; version<DRIVER_MAX_VERSION; version++ )
+       {
+               /* get the list of drivers */
+               
+               list = NULL;
+               ndrivers = get_ntdrivers(&list, info->environment, version);
                
-               DEBUG (10,("printer_driver_in_use: Printer - %s (%s)\n",
-                       info.printername, info.drivername));
+               DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", 
+                       ndrivers, info->environment, version));
+
+               if (ndrivers == -1)
+                       continue;
                        
-               if (strcmp(info.drivername, driver) == 0) 
+               /* check each driver for overlap in files */
+               
+               for (i=0; i<ndrivers; i++) 
                {
-                       DEBUG(5,("printer_driver_in_use: Printer %s using %s\n",
-                               info.printername, driver));
-                       return True;
+                       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) 
+                               || (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);
                }       
+               
+               SAFE_FREE(list);
        }
-       DEBUG(5,("printer_driver_in_use: Completed search through printers.tdb...\n"));
-       
        
+       DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n"));
        
-       /* report that the driver is in use by default */
        return False;
 }
 
+/****************************************************************************
+  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 *i, struct current_user *user )
+{
+       char *s;
+       connection_struct *conn;
+       DATA_BLOB null_pw;
+       NTSTATUS nt_status;
+       
+       if ( !i )
+               return False;
+               
+       DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", i->name, i->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.
+        */
+        
+       become_root();
+       null_pw = data_blob( NULL, 0 );
+        conn = make_connection_with_chdir( "print$", null_pw, "A:", user->vuid, &nt_status );
+       unbecome_root();
+       
+       if ( !conn ) {
+               DEBUG(0,("delete_driver_files: Unable to connect\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;
+       }
+
+       /* now delete the files; must strip the '\print$' string from 
+          fron of path                                                */
+       
+       if ( *i->driverpath ) {
+               if ( (s = strchr( &i->driverpath[1], '\\' )) != NULL ) {
+                       DEBUG(10,("deleting driverfile [%s]\n", s));
+                       unlink_internals(conn, 0, s);
+               }
+       }
+               
+       if ( *i->configfile ) {
+               if ( (s = strchr( &i->configfile[1], '\\' )) != NULL ) {
+                       DEBUG(10,("deleting configfile [%s]\n", s));
+                       unlink_internals(conn, 0, s);
+               }
+       }
+       
+       if ( *i->datafile ) {
+               if ( (s = strchr( &i->datafile[1], '\\' )) != NULL ) {
+                       DEBUG(10,("deleting datafile [%s]\n", s));
+                       unlink_internals(conn, 0, s);
+               }
+       }
+       
+       if ( *i->helpfile ) {
+               if ( (s = strchr( &i->helpfile[1], '\\' )) != NULL ) {
+                       DEBUG(10,("deleting helpfile [%s]\n", s));
+                       unlink_internals(conn, 0, s);
+               }
+       }
+       
+       s = (char*)i->dependentfiles;
+       
+       while ( s && *s ) {
+               char *file;
+
+               if ( (file = strchr( s+1, '\\' )) != NULL )
+               {
+                       DEBUG(10,("deleting dependent file [%s]\n", file));
+                       unlink_internals(conn, 0, file );
+                       file += strlen( file ) + 1;
+               }
+
+               s = file;
+       }
+
+       return True;
+}
+
 /****************************************************************************
  Remove a printer driver from the TDB.  This assumes that the the driver was
  previously looked up.
  ***************************************************************************/
-WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
+
+static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
+                              uint32 version, BOOL delete_files )
 {
        pstring         key;
        fstring         arch;
        TDB_DATA        kbuf;
+       NT_PRINTER_DRIVER_INFO_LEVEL    ctr;
 
+       /* delete the tdb data first */
 
        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));
+               arch, version, i->name);
+
+       DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n",
+               key, delete_files ? "TRUE" : "FALSE" ));
+
+       ctr.info_3 = i;
+       dump_a_printer_driver( ctr, 3 );
 
        kbuf.dptr=key;
        kbuf.dsize=strlen(key)+1;
@@ -3457,18 +3774,56 @@ WERROR delete_printer_driver (NT_PRINTER_DRIVER_INFO_LEVEL_3 *i)
                DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key));
                return WERR_ACCESS_DENIED;
        }
-       
+
+       /*
+        * now delete any associated files if delete_files == True
+        * even if this part failes, we return succes because the
+        * driver doesn not exist any more
+        */
+
+       if ( delete_files )
+               delete_driver_files( i, user );
+
        DEBUG(5,("delete_printer_driver: [%s] driver delete successful.\n",
                i->name));
-       
+
        return WERR_OK;
 }
+
+/****************************************************************************
+ Remove a printer driver from the TDB.  This assumes that the the driver was
+ previously looked up.
+ ***************************************************************************/
+
+WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user,
+                              uint32 version, BOOL delete_files )
+{
+       int ver;
+       WERROR err;
+
+       /* see if we should delete all versions of this driver */
+
+       if ( version == DRIVER_ANY_VERSION ) {
+               for ( ver=0; ver<DRIVER_MAX_VERSION; ver++ ) {
+                       err = delete_printer_driver_internal(i, user, ver, delete_files );
+                       if ( !W_ERROR_IS_OK(err) )
+                               return err;
+               }
+       }
+       else
+               delete_printer_driver_internal(i, user, version, delete_files );
+
+       return WERR_OK;
+}
+
+
 /****************************************************************************
 ****************************************************************************/
+
 BOOL get_specific_param_by_index(NT_PRINTER_INFO_LEVEL printer, uint32 level, uint32 param_index,
                                  fstring value, uint8 **data, uint32 *type, uint32 *len)
 {
-       /* right now that's enough ! */ 
+       /* right now that's enough ! */
        NT_PRINTER_PARAM *param;
        int i=0;
        
@@ -3542,7 +3897,7 @@ BOOL get_specific_param(NT_PRINTER_INFO_LEVEL printer, uint32 level,
  Store a security desc for a printer.
 ****************************************************************************/
 
-WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
+WERROR nt_printing_setsec(const char *printername, SEC_DESC_BUF *secdesc_ctr)
 {
        SEC_DESC_BUF *new_secdesc_ctr = NULL;
        SEC_DESC_BUF *old_secdesc_ctr = NULL;
@@ -3637,7 +3992,6 @@ WERROR nt_printing_setsec(char *printername, SEC_DESC_BUF *secdesc_ctr)
 
 static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
 {
-       extern DOM_SID global_sam_sid;
        SEC_ACE ace[3];
        SEC_ACCESS sa;
        SEC_ACL *psa = NULL;
@@ -3663,7 +4017,7 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
                   This should emulate a lanman printer as security
                   settings can't be changed. */
 
-               sid_copy(&owner_sid, &global_sam_sid);
+               sid_copy(&owner_sid, get_global_sam_sid());
                sid_append_rid(&owner_sid, DOMAIN_USER_RID_ADMIN);
        }
 
@@ -3704,7 +4058,7 @@ static SEC_DESC_BUF *construct_default_printer_sdb(TALLOC_CTX *ctx)
  Get a security desc for a printer.
 ****************************************************************************/
 
-BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secdesc_ctr)
+BOOL nt_printing_getsec(TALLOC_CTX *ctx, const char *printername, SEC_DESC_BUF **secdesc_ctr)
 {
        prs_struct ps;
        fstring key;
@@ -3732,7 +4086,7 @@ BOOL nt_printing_getsec(TALLOC_CTX *ctx, char *printername, SEC_DESC_BUF **secde
                prs_init(&ps, (uint32)sec_desc_size((*secdesc_ctr)->sec) +
                                sizeof(SEC_DESC_BUF), ctx, MARSHALL);
 
-               if (sec_io_desc_buf("nt_printing_setsec", secdesc_ctr, &ps, 1))
+               if (sec_io_desc_buf("nt_printing_getsec", secdesc_ctr, &ps, 1))
                        tdb_prs_store(tdb_printers, key, &ps);
 
                prs_mem_free(&ps);
@@ -3873,7 +4227,7 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type)
        uint32 access_granted;
        NTSTATUS status;
        BOOL result;
-       char *pname;
+       const char *pname;
        TALLOC_CTX *mem_ctx = NULL;
        extern struct current_user current_user;