diff options
| -rw-r--r-- | source3/printing/nt_printing.c | 19 | ||||
| -rw-r--r-- | source3/printing/pcap.c | 22 | ||||
| -rw-r--r-- | source3/printing/print_cups.c | 2 | ||||
| -rw-r--r-- | source3/printing/printing.c | 20 | ||||
| -rw-r--r-- | source3/rpc_parse/parse_spoolss.c | 2 | ||||
| -rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 137 | 
6 files changed, 131 insertions, 71 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index ecf873c1ba..08d5ea430a 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -2838,7 +2838,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; @@ -2891,9 +2891,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. @@ -2945,19 +2950,19 @@ 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;  	} diff --git a/source3/printing/pcap.c b/source3/printing/pcap.c index 920c6f354e..01e03c7c6b 100644 --- a/source3/printing/pcap.c +++ b/source3/printing/pcap.c @@ -111,7 +111,7 @@ static void ScanQconfig_fn(char *psz,void (*fn)(char *, char *))  	iEtat = 0;  	/* scan qconfig file for searching <printername>:	*/ -	for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) +	for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); SAFE_FREE(line))  	{  		if (*line == '*' || *line == 0)  		continue; @@ -181,7 +181,7 @@ static BOOL ScanQconfig(char *psz,char *pszPrintername)  	if ((pfile = x_fopen(psz, O_RDONLY, 0)) == NULL)  	{  	      DEBUG(0,( "Unable to open qconfig file %s for read!\n", psz)); -	      free(pName); +	      SAFE_FREE(pName);  	      return(False);  	}  	slprintf(pName, iLg + 9, "%s:",pszPrintername); @@ -189,7 +189,7 @@ static BOOL ScanQconfig(char *psz,char *pszPrintername)  	/*DEBUG(3,( " Looking for entry %s\n",pName));*/  	iEtat = 0;  	/* scan qconfig file for searching <printername>:	*/ -	for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) +	for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); SAFE_FREE(line))  	{  		if (*line == '*' || *line == 0)  		continue; @@ -208,8 +208,8 @@ static BOOL ScanQconfig(char *psz,char *pszPrintername)  		  	 {  		  	   /* name is found without stanza device  */  		  	   /* probably a good printer ???		*/ -		  	   free (line); -		  	   free(pName); +		  	   SAFE_FREE (line); +		  	   SAFE_FREE(pName);  		  	   fclose(pfile);  		  	   return(True);  		  	  } @@ -222,15 +222,15 @@ static BOOL ScanQconfig(char *psz,char *pszPrintername)  		  	  else if (strlocate(line,"device"))  		  	  {  		  		/* it's a good virtual printer */ -		  		free (line); -		  		free(pName); +		  		SAFE_FREE (line); +		  		SAFE_FREE(pName);  		  		fclose(pfile);  		  		return(True);  		  	  }  		  	  break;  		}  	} -	free (pName); +	SAFE_FREE (pName);  	x_fclose(pfile);  	return(False);  } @@ -288,7 +288,7 @@ BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname)        return(False);      } -  for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) +  for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); SAFE_FREE(line))      {        if (*line == '#' || *line == 0)  	continue; @@ -307,7 +307,7 @@ BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname)  	    {  	      /* normalise the case */  	      pstrcpy(pszPrintername,p); -	      free(line); +	      SAFE_FREE(line);  	      x_fclose(pfile);  	      return(True);	        	    } @@ -369,7 +369,7 @@ void pcap_printer_fn(void (*fn)(char *, char *))        return;      } -  for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); free(line)) +  for (;(line = fgets_slash(NULL,sizeof(pstring),pfile)); SAFE_FREE(line))      {        if (*line == '#' || *line == 0)  	continue; diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c index b5315e10b2..51ebb739a3 100644 --- a/source3/printing/print_cups.c +++ b/source3/printing/print_cups.c @@ -824,7 +824,7 @@ cups_queue_get(int snum, print_queue_struct **q, print_status_struct *status)  				ippDelete(response);  				httpClose(http); -				free (queue); +				SAFE_FREE(queue);  				return (0);  			} diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 47fc019d64..aa9df5e47f 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -52,7 +52,8 @@ BOOL print_backend_init(void)  {  	char *sversion = "INFO/version"; -	if (tdb && local_pid == sys_getpid()) return True; +	if (tdb && local_pid == sys_getpid()) +		return True;  	tdb = tdb_open_log(lock_path("printing.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);  	if (!tdb) {  		DEBUG(0,("print_backend_init: Failed to open printing backend database %s\n", @@ -108,7 +109,7 @@ static struct printjob *print_job_find(int jobid)  		return NULL;  	memcpy(&pjob, ret.dptr, sizeof(pjob)); -	free(ret.dptr); +	SAFE_FREE(ret.dptr);  	return &pjob;  } @@ -291,7 +292,7 @@ static pid_t get_updating_pid(fstring printer_name)  		return (pid_t)-1;  	memcpy(&updating_pid, data.dptr, sizeof(pid_t)); -	free(data.dptr); +	SAFE_FREE(data.dptr);  	if (process_exists(updating_pid))  		return updating_pid; @@ -568,10 +569,9 @@ BOOL print_job_exists(int jobid)  	return tdb_exists(tdb, print_key(jobid));  } -  /**************************************************************************** - Work out which service a jobid is for - note that we have to look up by queue name to ensure that it works for  + Work out which service a jobid is for. + Note that we have to look up by queue name to ensure that it works for    other than the process that started the job.  ****************************************************************************/ @@ -922,7 +922,7 @@ static int get_queue_status(int snum, print_status_struct *status)  		if (data.dsize == sizeof(print_status_struct)) {  			memcpy(status, data.dptr, sizeof(print_status_struct));  		} -		free(data.dptr); +		SAFE_FREE(data.dptr);  	}  	return status->qcount;  } @@ -968,7 +968,7 @@ static int get_total_jobs(int snum)  }  /*************************************************************************** -start spooling a job - return the jobid + Start spooling a job - return the jobid.  ***************************************************************************/  int print_job_start(struct current_user *user, int snum, char *jobname) @@ -1116,7 +1116,7 @@ to open spool file %s.\n", pjob.filename));  }  /**************************************************************************** - Update the number of pages spooled to jobid. + Update the number of pages spooled to jobid  ****************************************************************************/  void print_job_endpage(int jobid) @@ -1330,7 +1330,7 @@ int print_queue_status(int snum,  		if (data.dsize == sizeof(*status)) {  			memcpy(status, data.dptr, sizeof(*status));  		} -		free(data.dptr); +		SAFE_FREE(data.dptr);  	}  	/* diff --git a/source3/rpc_parse/parse_spoolss.c b/source3/rpc_parse/parse_spoolss.c index 60b5e60a81..aa7fcd0010 100644 --- a/source3/rpc_parse/parse_spoolss.c +++ b/source3/rpc_parse/parse_spoolss.c @@ -695,6 +695,7 @@ BOOL spoolss_io_devmode(char *desc, prs_struct *ps, int depth, DEVICEMODE *devmo  	while ((available_space > 0)  && (i < DM_NUM_OPTIONAL_FIELDS))  	{ +		DEBUG(10, ("spoolss_io_devmode: [%d] bytes left to parse in devmode\n", available_space));  		if (!prs_uint32(opt_fields[i].name, ps, depth, opt_fields[i].field))  			return False;  		available_space -= sizeof(uint32); @@ -1115,6 +1116,7 @@ BOOL make_spoolss_q_getprinterdata(SPOOL_Q_GETPRINTERDATA *q_u,          q_u->handle = *handle;  	init_unistr2(&q_u->valuename, valuename, strlen(valuename) + 1);          q_u->size = size; +          return True;  } diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index fc63275869..56806823d1 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -809,8 +809,10 @@ void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)  	/* Iterate the printer list */ -	for (snum=0; snum<n_services; snum++) { -		if (lp_snum_ok(snum) && lp_print_ok(snum) ) { +	for (snum=0; snum<n_services; snum++) +	{ +		if (lp_snum_ok(snum) && lp_print_ok(snum) )  +		{  			WERROR result;  			NT_PRINTER_INFO_LEVEL *printer = NULL; @@ -818,15 +820,19 @@ void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len)  			if (!W_ERROR_IS_OK(result))  				continue; -			if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername)) { +			if (printer && printer->info_2 && !strcmp(drivername, printer->info_2->drivername))  +			{  				DEBUG(6,("Updating printer [%s]\n", printer->info_2->printername)); +				  				/* all we care about currently is the change_id */ +				  				result = mod_a_printer(*printer, 2);  				if (!W_ERROR_IS_OK(result)) {  					DEBUG(3,("do_drv_upgrade_printer: mod_a_printer() failed with status [%s]\n",  					dos_errstr(result)));  				}  			} +			  			free_a_printer(&printer, 2);  		}  	} @@ -1000,16 +1006,6 @@ Can't find printer handle we created for printer %s\n", name ));  	}  /* -	if (printer_default->datatype_ptr != NULL) -	{ -		unistr2_to_ascii(datatype, printer_default->datatype, sizeof(datatype)-1); -		set_printer_hnd_datatype(handle, datatype); -	} -	else -		set_printer_hnd_datatype(handle, ""); -*/ -	 -	/*  	   First case: the user is opening the print server:  	   Disallow MS AddPrinterWizard if parameter disables it. A Win2k @@ -3492,10 +3488,26 @@ static WERROR enum_all_printers_info_1_remote(fstring name, NEW_BUFFER *buffer,   enum_all_printers_info_1_network.  *********************************************************************/ -static WERROR enum_all_printers_info_1_network(NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned) +static WERROR enum_all_printers_info_1_network(fstring name, NEW_BUFFER *buffer, uint32 offered, uint32 *needed, uint32 *returned)  { +	char *s = name; +  	DEBUG(4,("enum_all_printers_info_1_network\n"));	 +	/* If we respond to a enum_printers level 1 on our name with flags +	   set to PRINTER_ENUM_REMOTE with a list of printers then these +	   printers incorrectly appear in the APW browse list. +	   Specifically the printers for the server appear at the workgroup +	   level where all the other servers in the domain are +	   listed. Windows responds to this call with a +	   WERR_CAN_NOT_COMPLETE so we should do the same. */  + +	if (name[0] == '\\' && name[1] == '\\') +		 s = name + 2; + +	if (is_myname_or_ipaddr(s)) +		 return WERR_CAN_NOT_COMPLETE; +  	return enum_all_printers_info_1(PRINTER_ENUM_UNKNOWN_8, buffer, offered, needed, returned);  } @@ -3582,7 +3594,7 @@ static WERROR enumprinters_level1( uint32 flags, fstring name,  		return enum_all_printers_info_1_remote(name, buffer, offered, needed, returned);  	if (flags & PRINTER_ENUM_NETWORK) -		return enum_all_printers_info_1_network(buffer, offered, needed, returned); +		return enum_all_printers_info_1_network(name, buffer, offered, needed, returned);  	return WERR_OK; /* NT4sp5 does that */  } @@ -5247,7 +5259,10 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level,  		 * bound to the printer, simulating what happens in the Windows arch.  		 */  		if (!strequal(printer->info_2->drivername, old_printer->info_2->drivername)){ -			set_driver_init(printer, 2); +			if (!set_driver_init(printer, 2)) { +				DEBUG(5,("update_printer: Error restoring driver initialization data for driver [%s]!\n", +					printer->info_2->drivername)); +			}  			msg.flags |= PRINTER_MESSAGE_DRIVER;  		}  	} @@ -6603,16 +6618,70 @@ WERROR _spoolss_addprinterdriver(pipes_struct *p, SPOOL_Q_ADDPRINTERDRIVER *q_u,  			driver_name));  	} -	/* if driver is not 9x, delete existing driver init data */ +	/* +	 * Based on the version (e.g. driver destination dir: 0=9x,2=Nt/2k,3=2k/Xp), +	 * decide if the driver init data should be deleted. The rules are: +	 *  1) never delete init data if it is a 9x driver, they don't use it anyway +	 *  2) delete init data only if there is no 2k/Xp driver +	 *  3) always delete init data +	 * The generalized rule is always use init data from the highest order driver. +	 * It is necessary to follow the driver install by an initialization step to +	 * finish off this process. +	*/ +	if (level == 3) +		version = driver.info_3->cversion; +	else if (level == 6) +		version = driver.info_6->version; +	else +		version = -1; +	switch (version) { +		/* +		 * 9x printer driver - never delete init data +		*/ +		case 0:  +			DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n", +					driver_name)); +			break; +		 +		/* +		 * Nt or 2k (compatiblity mode) printer driver - only delete init data if +		 * there is no 2k/Xp driver init data for this driver name. +		*/ +		case 2: +		{ +			NT_PRINTER_DRIVER_INFO_LEVEL driver1; -	if ((level == 3 && driver.info_3->cversion != 0) || -			(level == 6 && driver.info_6->version  != 0)) { +			if (!W_ERROR_IS_OK(get_a_printer_driver(&driver1, 3, driver_name, "Windows NT x86", 3))) { +				/* +				 * No 2k/Xp driver found, delete init data (if any) for the new Nt driver. +				*/  		if (!del_driver_init(driver_name)) -			DEBUG(3,("_spoolss_addprinterdriver: del_driver_init(%s) failed!\n", driver_name)); +					DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) Nt failed!\n", driver_name));  	} else { -		DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for 9x driver [%s]\n", driver_name)); +				/* +				 * a 2k/Xp driver was found, don't delete init data because Nt driver will use it. +				*/ +				free_a_printer_driver(driver1,3); +				DEBUG(10,("_spoolss_addprinterdriver: init data not deleted for Nt driver [%s]\n",  +						driver_name)); +			} +		} +		break; + +		/* +		 * 2k or Xp printer driver - always delete init data +		*/ +		case 3:	 +			if (!del_driver_init(driver_name)) +				DEBUG(6,("_spoolss_addprinterdriver: del_driver_init(%s) 2k/Xp failed!\n", driver_name)); +			break; + +		default: +			DEBUG(0,("_spoolss_addprinterdriver: invalid level=%d\n", level)); +			break;  	} +	   done:  	free_a_printer_driver(driver, level);  	return err; @@ -6756,23 +6825,6 @@ WERROR _spoolss_enumprinterdata(pipes_struct *p, SPOOL_Q_ENUMPRINTERDATA *q_u, S  	if ( (in_value_len==0) && (in_data_len==0) ) {  		DEBUGADD(6,("Activating NT mega-hack to find sizes\n")); -#if 0 -		/* -		 * NT can ask for a specific parameter size - we need to return NO_MORE_ITEMS -		 * if this parameter size doesn't exist. -		 * Ok - my opinion here is that the client is not asking for the greatest -		 * possible size of all the parameters, but is asking specifically for the size needed -		 * for this specific parameter. In that case we can remove the loop below and -		 * simplify this lookup code considerably. JF - comments welcome. JRA. -		 */ - -		if (!get_specific_param_by_index(*printer, 2, idx, value, &data, &type, &data_len)) { -			SAFE_FREE(data); -			free_a_printer(&printer, 2); -			return WERR_NO_MORE_ITEMS; -		} -#endif -  		SAFE_FREE(data);  		param_index=0; @@ -7925,7 +7977,7 @@ static WERROR getprintprocessordirectory_level_1(UNISTR2 *name,  	unistr2_to_ascii(long_archi, environment, sizeof(long_archi)-1); -	if (get_short_archi(short_archi, long_archi)==FALSE) +	if (get_short_archi(short_archi, long_archi)==False)  		return WERR_INVALID_ENVIRONMENT;  	if((info=(PRINTPROCESSOR_DIRECTORY_1 *)malloc(sizeof(PRINTPROCESSOR_DIRECTORY_1))) == NULL) @@ -7958,6 +8010,7 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC  	NEW_BUFFER *buffer = NULL;  	uint32 offered = q_u->offered;  	uint32 *needed = &r_u->needed; +	WERROR result;  	/* that's an [in out] buffer */  	spoolss_move_buffer(q_u->buffer, &r_u->buffer); @@ -7969,11 +8022,11 @@ WERROR _spoolss_getprintprocessordirectory(pipes_struct *p, SPOOL_Q_GETPRINTPROC  	switch(level) {  	case 1: -		return getprintprocessordirectory_level_1 +		result = getprintprocessordirectory_level_1  		  (&q_u->name, &q_u->environment, buffer, offered, needed);  	default: -		return WERR_UNKNOWN_LEVEL; +		result = WERR_UNKNOWN_LEVEL;  	} -	return WERR_ACCESS_DENIED; +	return result;  }  | 
