diff options
Diffstat (limited to 'source3')
-rw-r--r-- | source3/printing/nt_printing.c | 272 | ||||
-rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 137 |
2 files changed, 238 insertions, 171 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index bf90089448..2a96f9a83e 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -1745,7 +1745,7 @@ static WERROR get_a_printer_driver_3(NT_PRINTER_DRIVER_INFO_LEVEL_3 **info_ptr, dbuf = tdb_fetch(tdb_drivers, kbuf); if (!dbuf.dptr) - return WERR_ACCESS_DENIED; + return WERR_UNKNOWN_PRINTER_DRIVER; len += tdb_unpack(dbuf.dptr, dbuf.dsize, "dffffffff", &driver.cversion, @@ -1864,7 +1864,7 @@ static uint32 dump_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 NT_PRINTER_DRIVER_INFO_LEVEL_3 *info3; int i; - DEBUG(106,("Dumping printer driver at level [%d]\n", level)); + DEBUG(20,("Dumping printer driver at level [%d]\n", level)); switch (level) { @@ -3724,13 +3724,13 @@ uint32 free_a_printer_driver(NT_PRINTER_DRIVER_INFO_LEVEL driver, uint32 level) to a printer ****************************************************************************/ -BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i ) +BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3 ) { int snum; int n_services = lp_numservices(); NT_PRINTER_INFO_LEVEL *printer = NULL; - if ( !i ) + if ( !info_3 ) return False; DEBUG(5,("printer_driver_in_use: Beginning search through ntprinters.tdb...\n")); @@ -3745,7 +3745,7 @@ BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i ) if ( !W_ERROR_IS_OK(get_a_printer(&printer, 2, lp_servicename(snum))) ) continue; - if ( !StrCaseCmp(i->name, printer->info_2->drivername) ) { + if ( !StrCaseCmp(info_3->name, printer->info_2->drivername) ) { free_a_printer( &printer, 2 ); return True; } @@ -3767,7 +3767,7 @@ BOOL printer_driver_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i ) static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ) { - char *s; + int i = 0; if ( !info ) return False; @@ -3783,16 +3783,18 @@ static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ) 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; - } + /* see of there are any dependent files to examine */ + + if ( !info->dependentfiles ) + return False; + + while ( *info->dependentfiles[i] ) + { + if ( strequal(file, info->dependentfiles[i]) ) + return True; + + i++; } return False; @@ -3804,27 +3806,20 @@ static BOOL drv_file_in_use( char* file, NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ) input parameter from the list *********************************************************************/ -static void trim_dependent_file( char* s ) +static void trim_dependent_file( fstring files[], int idx ) { - 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' ) + /* bump everything down a slot */ + + while( *files[idx+1] ) { - /* loop over s copying characters from p to s */ - while ( *p!='\0' && *(p+1)!='\0' ) - *s++ = *p++; + fstrcpy( files[idx], files[idx+1] ); + idx++; } - /* add the two trailing NULL's */ - - *s = '\0'; - *(s+1) = '\0'; + *files[idx] = '\0'; + + return; } /********************************************************************** @@ -3834,8 +3829,8 @@ static void trim_dependent_file( char* s ) 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; + BOOL in_use = False; + int i = 0; if ( !src || !drv ) return False; @@ -3844,33 +3839,43 @@ static BOOL trim_overlap_drv_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *src, if ( drv_file_in_use(src->driverpath, drv) ) { in_use = True; + DEBUG(10,("Removing driverfile [%s] from list\n", src->driverpath)); fstrcpy( src->driverpath, "" ); } if ( drv_file_in_use(src->datafile, drv) ) { in_use = True; + DEBUG(10,("Removing datafile [%s] from list\n", src->datafile)); fstrcpy( src->datafile, "" ); } if ( drv_file_in_use(src->configfile, drv) ) { in_use = True; + DEBUG(10,("Removing configfile [%s] from list\n", src->configfile)); 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; - } + if ( drv_file_in_use(src->helpfile, drv) ) { + in_use = True; + DEBUG(10,("Removing helpfile [%s] from list\n", src->helpfile)); + fstrcpy( src->helpfile, "" ); } + + /* are there any dependentfiles to examine? */ + + if ( !src->dependentfiles ) + return in_use; + while ( *src->dependentfiles[i] ) + { + if ( drv_file_in_use(src->dependentfiles[i], drv) ) { + in_use = True; + DEBUG(10,("Removing [%s] from dependent file list\n", src->dependentfiles[i])); + trim_dependent_file( src->dependentfiles, i ); + } + else + i++; + } return in_use; } @@ -3894,59 +3899,62 @@ BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ) fstring *list = NULL; NT_PRINTER_DRIVER_INFO_LEVEL driver; + if ( !info ) + return False; + + version = info->cversion; + /* 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 */ + /* get the list of drivers */ - list = NULL; - ndrivers = get_ntdrivers(&list, info->environment, version); + list = NULL; + ndrivers = get_ntdrivers(&list, info->environment, version); - DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", - ndrivers, info->environment, version)); + DEBUGADD(4,("we have:[%d] drivers in environment [%s] and version [%d]\n", + ndrivers, info->environment, version)); - if (ndrivers == -1) - continue; - - /* check each driver for overlap in files */ + /* check each driver for overlap in files */ - for (i=0; i<ndrivers; i++) - { - DEBUGADD(5,("\tdriver: [%s]\n", list[i])); + for (i=0; i<ndrivers; i++) + { + DEBUGADD(5,("\tdriver: [%s]\n", list[i])); - ZERO_STRUCT(driver); + ZERO_STRUCT(driver); - if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, list[i], - info->environment, version)) ) - { - SAFE_FREE(list); - return True; - } + 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 */ + /* 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; - } + if ( !strequal(info->name, driver.info_3->name) ) + { + 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); - } + free_a_printer_driver(driver, 3); + } + + SAFE_FREE(list); DEBUG(5,("printer_driver_files_in_use: Completed search through ntdrivers.tdb...\n")); + driver.info_3 = info; + + if ( DEBUGLEVEL >= 20 ) + dump_a_printer_driver( driver, 3 ); + return False; } @@ -3956,17 +3964,18 @@ BOOL printer_driver_files_in_use ( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info ) this. ****************************************************************************/ -static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user ) +static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user ) { + int i = 0; char *s; connection_struct *conn; DATA_BLOB null_pw; NTSTATUS nt_status; - if ( !i ) + if ( !info_3 ) return False; - DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", i->name, i->cversion)); + DEBUG(6,("delete_driver_files: deleting driver [%s] - version [%d]\n", info_3->name, info_3->cversion)); /* * Connect to the print$ share under the same account as the @@ -3994,49 +4003,55 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct curre /* now delete the files; must strip the '\print$' string from fron of path */ - if ( *i->driverpath ) { - if ( (s = strchr( &i->driverpath[1], '\\' )) != NULL ) { + if ( *info_3->driverpath ) { + if ( (s = strchr( &info_3->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 ) { + if ( *info_3->configfile ) { + if ( (s = strchr( &info_3->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 ) { + if ( *info_3->datafile ) { + if ( (s = strchr( &info_3->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 ) { + if ( *info_3->helpfile ) { + if ( (s = strchr( &info_3->helpfile[1], '\\' )) != NULL ) { DEBUG(10,("deleting helpfile [%s]\n", s)); unlink_internals(conn, 0, s); } } - s = (char*)i->dependentfiles; + /* check if we are done removing files */ - while ( s && *s ) { - char *file; + if ( info_3->dependentfiles ) + { + while ( *info_3->dependentfiles[i] ) { + 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; + /* bypass the "\print$" portion of the path */ + + if ( (file = strchr( info_3->dependentfiles[i]+1, '\\' )) != NULL ) + { + DEBUG(10,("deleting dependent file [%s]\n", file)); + unlink_internals(conn, 0, file ); + } + + i++; } - - s = file; } + unbecome_user(); + return True; } @@ -4045,7 +4060,7 @@ static BOOL delete_driver_files( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct curre previously looked up. ***************************************************************************/ -static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, struct current_user *user, +WERROR delete_printer_driver( NT_PRINTER_DRIVER_INFO_LEVEL_3 *info_3, struct current_user *user, uint32 version, BOOL delete_files ) { pstring key; @@ -4055,14 +4070,14 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, /* delete the tdb data first */ - get_short_archi(arch, i->environment); + get_short_archi(arch, info_3->environment); slprintf(key, sizeof(key)-1, "%s%s/%d/%s", DRIVERS_PREFIX, - arch, version, i->name); + arch, version, info_3->name); DEBUG(5,("delete_printer_driver: key = [%s] delete_files = %s\n", key, delete_files ? "TRUE" : "FALSE" )); - ctr.info_3 = i; + ctr.info_3 = info_3; dump_a_printer_driver( ctr, 3 ); kbuf.dptr=key; @@ -4072,7 +4087,7 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, dbuf = tdb_fetch( tdb_drivers, kbuf ); if ( !dbuf.dptr ) { - DEBUG(8,("delete_printer_driver_internal: Driver unknown [%s]\n", key)); + DEBUG(8,("delete_printer_driver: Driver unknown [%s]\n", key)); return WERR_UNKNOWN_PRINTER_DRIVER; } @@ -4081,7 +4096,7 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, /* ok... the driver exists so the delete should return success */ if (tdb_delete(tdb_drivers, kbuf) == -1) { - DEBUG (0,("delete_printer_driver_internal: fail to delete %s!\n", key)); + DEBUG (0,("delete_printer_driver: fail to delete %s!\n", key)); return WERR_ACCESS_DENIED; } @@ -4092,51 +4107,14 @@ static WERROR delete_printer_driver_internal( NT_PRINTER_DRIVER_INFO_LEVEL_3 *i, */ if ( delete_files ) - delete_driver_files( i, user ); - - - DEBUG(5,("delete_printer_driver_internal: driver delete successful [%s]\n", key)); - - 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 ) -{ - WERROR err; - - /* - * see if we should delete all versions of this driver - * (DRIVER_ANY_VERSION uis only set for "Windows NT x86") - */ - - if ( version == DRIVER_ANY_VERSION ) - { - /* Windows NT 4.0 */ - - err = delete_printer_driver_internal(i, user, 2, delete_files ); - if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) ) - return err; + delete_driver_files( info_3, user ); - /* Windows 2000/XP */ - err = delete_printer_driver_internal(i, user, 3, delete_files ); - if ( !W_ERROR_IS_OK(err) && (W_ERROR_V(err) != ERRunknownprinterdriver ) ) - return err; + DEBUG(5,("delete_printer_driver: driver delete successful [%s]\n", key)); return WERR_OK; } - /* just delete what they asked for */ - - return delete_printer_driver_internal(i, user, version, delete_files ); -} - /**************************************************************************** Store a security desc for a printer. ****************************************************************************/ diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index c4105f9780..37f8071e69 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -1593,8 +1593,11 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER fstring driver; fstring arch; NT_PRINTER_DRIVER_INFO_LEVEL info; + NT_PRINTER_DRIVER_INFO_LEVEL info_win2k; int version; struct current_user user; + WERROR status; + WERROR status_win2k = WERR_ACCESS_DENIED; get_current_user(&user, p); @@ -1602,25 +1605,58 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER unistr2_to_ascii(arch, &q_u->arch, sizeof(arch)-1 ); /* check that we have a valid driver name first */ - if ((version=get_version_id(arch)) == -1) { - /* this is what NT returns */ + + if ((version=get_version_id(arch)) == -1) return WERR_INVALID_ENVIRONMENT; + + ZERO_STRUCT(info); + ZERO_STRUCT(info_win2k); + + if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) + { + /* try for Win2k driver if "Windows NT x86" */ + + if ( version == 2 ) { + version = 3; + if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) { + status = WERR_UNKNOWN_PRINTER_DRIVER; + goto done; + } + } } - /* if they said "Windows NT x86", then try for version 2 & 3 */ + if (printer_driver_in_use(info.info_3)) { + status = WERR_PRINTER_DRIVER_IN_USE; + goto done; + } if ( version == 2 ) - version = DRIVER_ANY_VERSION; + { + if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3))) + { + /* if we get to here, we now have 2 driver info structures to remove */ + /* remove the Win2k driver first*/ - ZERO_STRUCT(info); + status_win2k = delete_printer_driver(info_win2k.info_3, &user, 3, False ); + free_a_printer_driver( info_win2k, 3 ); + + /* this should not have failed---if it did, report to client */ + if ( !W_ERROR_IS_OK(status_win2k) ) + goto done; + } + } - if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) - return WERR_UNKNOWN_PRINTER_DRIVER; + status = delete_printer_driver(info.info_3, &user, version, False); + + /* if at least one of the deletes succeeded return OK */ - if (printer_driver_in_use(info.info_3)) - return WERR_PRINTER_DRIVER_IN_USE; + if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) ) + status = WERR_OK; + +done: + free_a_printer_driver( info, 3 ); - return delete_printer_driver(info.info_3, &user, DRIVER_ANY_VERSION, False); + return status; } /******************************************************************** @@ -1632,10 +1668,13 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV fstring driver; fstring arch; NT_PRINTER_DRIVER_INFO_LEVEL info; + NT_PRINTER_DRIVER_INFO_LEVEL info_win2k; int version; uint32 flags = q_u->delete_flags; BOOL delete_files; struct current_user user; + WERROR status; + WERROR status_win2k = WERR_ACCESS_DENIED; get_current_user(&user, p); @@ -1650,17 +1689,35 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV if ( flags & DPD_DELETE_SPECIFIC_VERSION ) version = q_u->version; - else if ( version == 2 ) - /* if they said "Windows NT x86", then try for version 2 & 3 */ - version = DRIVER_ANY_VERSION; ZERO_STRUCT(info); + ZERO_STRUCT(info_win2k); + + status = get_a_printer_driver(&info, 3, driver, arch, version); - if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) - return WERR_UNKNOWN_PRINTER_DRIVER; + if ( !W_ERROR_IS_OK(status) ) + { + /* if the client asked for a specific version, then we've failed */ - if ( printer_driver_in_use(info.info_3) ) - return WERR_PRINTER_DRIVER_IN_USE; + if ( flags & DPD_DELETE_SPECIFIC_VERSION ) + goto done; + + /* try for Win2k driver if "Windows NT x86" */ + + if ( version == 2 ) + { + version = 3; + if (!W_ERROR_IS_OK(get_a_printer_driver(&info, 3, driver, arch, version))) { + status = WERR_UNKNOWN_PRINTER_DRIVER; + goto done; + } + } + } + + if ( printer_driver_in_use(info.info_3) ) { + status = WERR_PRINTER_DRIVER_IN_USE; + goto done; + } /* * we have a couple of cases to consider. @@ -1676,16 +1733,48 @@ WERROR _spoolss_deleteprinterdriverex(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIV 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 */ + /* fail if any files are in use and DPD_DELETE_ALL_FILES is set */ + + if ( delete_files && printer_driver_files_in_use(info.info_3) & (flags&DPD_DELETE_ALL_FILES) ) { + /* no idea of the correct error here */ + status = WERR_ACCESS_DENIED; + goto done; + } + + + /* also check for W32X86/3 if necessary; maybe we already have? */ + + if ( (version == 2) && ((flags&DPD_DELETE_SPECIFIC_VERSION) != DPD_DELETE_SPECIFIC_VERSION) ) { + if (W_ERROR_IS_OK(get_a_printer_driver(&info_win2k, 3, driver, arch, 3))) + { + + if ( delete_files && printer_driver_files_in_use(info_win2k.info_3) & (flags&DPD_DELETE_ALL_FILES) ) { + /* no idea of the correct error here */ + status = WERR_ACCESS_DENIED; + goto done; + } - 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; + /* if we get to here, we now have 2 driver info structures to remove */ + /* remove the Win2k driver first*/ + + status_win2k = delete_printer_driver(info.info_3, &user, 3, delete_files); + free_a_printer_driver( info_win2k, 3 ); + + /* this should not have failed---if it did, report to client */ + + if ( !W_ERROR_IS_OK(status_win2k) ) + goto done; + } } - return delete_printer_driver(info.info_3, &user, version, delete_files); + status = delete_printer_driver(info.info_3, &user, version, delete_files); + + if ( W_ERROR_IS_OK(status) || W_ERROR_IS_OK(status_win2k) ) + status = WERR_OK; +done: + free_a_printer_driver( info, 3 ); + + return status; } |