diff options
| -rw-r--r-- | source3/printing/nt_printing.c | 250 | ||||
| -rw-r--r-- | source3/rpc_server/srv_spoolss_nt.c | 43 | 
2 files changed, 187 insertions, 106 deletions
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index 532ab0794c..ab01e77c61 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -2508,16 +2508,10 @@ static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)          char *ascii_str;  	int i; -	for (i=0; i < info2->data.num_keys; i++) -		if (!(StrCaseCmp(SPOOL_DSSPOOLER_KEY,  -				 info2->data.keys[i].name))) -			ctr = &info2->data.keys[i].values; +	if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0) +		i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY); +	ctr = &info2->data.keys[i].values; -	if (!ctr) { -		add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY); -		ctr = &info2->data.keys[info2->data.num_keys - 1].values; -	} -	  	map_sz_into_ctr(ctr, SPOOL_REG_PRINTERNAME, info2->sharename);  	map_sz_into_ctr(ctr, SPOOL_REG_SHORTSERVERNAME, global_myname()); @@ -2561,96 +2555,208 @@ static BOOL map_nt_printer_info2_to_dsspooler(NT_PRINTER_INFO_LEVEL_2 *info2)  	return True;  } -/**************************************************************************** - * Publish a printer in the directory - * - * @param snum describing printer service - * @return WERROR indicating status of publishing - ***************************************************************************/ +#ifdef HAVE_ADS +static void store_printer_guid(NT_PRINTER_INFO_LEVEL_2 *info2, GUID guid) +{ +	int i; +	REGVAL_CTR *ctr=NULL; -WERROR nt_printer_publish(int snum, int action) +	/* find the DsSpooler key */ +	if ((i = lookup_printerkey(&info2->data, SPOOL_DSSPOOLER_KEY)) < 0) +		i = add_new_printer_key(&info2->data, SPOOL_DSSPOOLER_KEY); +	ctr = &info2->data.keys[i].values; + +	regval_ctr_delvalue(ctr, "objectGUID"); +	regval_ctr_addvalue(ctr, "objectGUID", REG_BINARY,  +			    (char *) &guid, sizeof(GUID));	 +} + +static WERROR publish_it(NT_PRINTER_INFO_LEVEL *printer)  { -#ifdef HAVE_ADS -	NT_PRINTER_INFO_LEVEL *printer = NULL; -	WERROR win_rc;  	ADS_STATUS ads_rc;  	TALLOC_CTX *ctx = talloc_init();  	ADS_MODLIST mods = ads_init_mods(ctx);  	char *prt_dn = NULL, *srv_dn, **srv_cn;  	void *res = NULL;  	ADS_STRUCT *ads; +	const char *attrs[] = {"objectGUID", NULL}; +	GUID guid; +	WERROR win_rc = WERR_OK; -	win_rc = get_a_printer(&printer, 2, lp_servicename(snum)); -	if (!W_ERROR_IS_OK(win_rc)) +	ZERO_STRUCT(guid); +	/* set the DsSpooler info and attributes */ +	if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) +			return WERR_NOMEM; +	printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED; +	win_rc = mod_a_printer(*printer, 2); +	if (!W_ERROR_IS_OK(win_rc)) { +		DEBUG(3, ("err %d saving data\n", +				  W_ERROR_V(win_rc)));  		return win_rc; +	} -	if ((SPOOL_DS_PUBLISH == action) || (SPOOL_DS_UPDATE == action)) { -		if (!(map_nt_printer_info2_to_dsspooler(printer->info_2))) -			return WERR_NOMEM; +	/* Build the ads mods */ +	get_local_printer_publishing_data(ctx, &mods,  +					  &printer->info_2->data); +	ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,  +		    printer->info_2->sharename); -		printer->info_2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED; +	/* connect to the ADS server */ +	ads = ads_init(NULL, NULL, lp_ads_server()); +	if (!ads) { +		DEBUG(3, ("ads_init() failed\n")); +		return WERR_SERVER_UNAVAILABLE; +	} +	ads_rc = ads_connect(ads); +	if (!ADS_ERR_OK(ads_rc)) { +		DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); +		ads_destroy(&ads); +		return WERR_ACCESS_DENIED; +	} +	/* figure out where to publish */ +	ads_find_machine_acct(ads, &res, global_myname()); +	srv_dn = ldap_get_dn(ads->ld, res); +	ads_msgfree(ads, res); +	srv_cn = ldap_explode_dn(srv_dn, 1); +	asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0],  +		 printer->info_2->sharename, srv_dn); +	ads_memfree(ads, srv_dn); + +	/* publish it */ +	ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods); +	if (LDAP_ALREADY_EXISTS == ads_rc.err.rc) +		ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods); +	 +	/* retreive the guid and store it locally */ +	if (ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) { +		ads_memfree(ads, prt_dn); +		ads_pull_guid(ads, res, &guid); +		ads_msgfree(ads, res); +		store_printer_guid(printer->info_2, guid);  		win_rc = mod_a_printer(*printer, 2); -		if (!W_ERROR_IS_OK(win_rc)) { -			DEBUG(3, ("nt_printer_publish: err %d saving data\n", -				  W_ERROR_V(win_rc))); -			free_a_printer(&printer, 2); -			return win_rc; -		} +	}  -		get_local_printer_publishing_data(ctx, &mods,  -						  &printer->info_2->data); -		ads_mod_str(ctx, &mods, SPOOL_REG_PRINTERNAME,  -			    lp_servicename(snum)); -	} else { -		printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED; -		win_rc = mod_a_printer(*printer, 2); -		if (!W_ERROR_IS_OK(win_rc)) { -			DEBUG(3, ("nt_printer_publish: err %d saving data\n", +	safe_free(prt_dn); +	ads_destroy(&ads); + +	return WERR_OK; +} + +WERROR unpublish_it(NT_PRINTER_INFO_LEVEL *printer) +{ +	ADS_STATUS ads_rc; +	ADS_STRUCT *ads; +	void *res; +	char *prt_dn = NULL; +	WERROR win_rc; + +	printer->info_2->attributes ^= PRINTER_ATTRIBUTE_PUBLISHED; +	win_rc = mod_a_printer(*printer, 2); +	if (!W_ERROR_IS_OK(win_rc)) { +		DEBUG(3, ("err %d saving data\n",  				  W_ERROR_V(win_rc))); -			free_a_printer(&printer, 2); -			return win_rc; -		} +		return win_rc;  	} - +	  	ads = ads_init(NULL, NULL, lp_ads_server()); - +	if (!ads) { +		DEBUG(3, ("ads_init() failed\n")); +		return WERR_SERVER_UNAVAILABLE; +	}  	ads_rc = ads_connect(ads); - -	if (SPOOL_DS_UNPUBLISH == action) { -		ads_rc = ads_find_printer_on_server(ads, &res,  -				printer->info_2->sharename, global_myname()); -		if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) { -				prt_dn = ads_get_dn(ads, res); -				ads_msgfree(ads, res); -				ads_rc = ads_del_dn(ads, prt_dn); -				ads_memfree(ads, prt_dn); -		} +	if (!ADS_ERR_OK(ads_rc)) { +		DEBUG(3, ("ads_connect failed: %s\n", ads_errstr(ads_rc))); +		ads_destroy(&ads); +		return WERR_ACCESS_DENIED;  	} - -	if ((SPOOL_DS_PUBLISH == action) || (SPOOL_DS_UPDATE == action)) { -		ads_find_machine_acct(ads, &res, global_myname()); -		srv_dn = ldap_get_dn(ads->ld, res); +	 +	/* remove the printer from the directory */ +	ads_rc = ads_find_printer_on_server(ads, &res,  +			    printer->info_2->sharename, global_myname()); +	if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) { +		prt_dn = ads_get_dn(ads, res);  		ads_msgfree(ads, res); -		srv_cn = ldap_explode_dn(srv_dn, 1); -		asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0],  -			 printer->info_2->sharename, srv_dn); -		ads_memfree(ads, srv_dn); - -		ads_rc = ads_add_printer_entry(ads, prt_dn, ctx, &mods); -		if (LDAP_ALREADY_EXISTS == ads_rc.err.rc) -			ads_rc = ads_mod_printer_entry(ads, prt_dn, ctx,&mods); -		safe_free(prt_dn); -		ads_destroy(&ads); +		ads_rc = ads_del_dn(ads, prt_dn); +		ads_memfree(ads, prt_dn);  	} -	free_a_printer(&printer, 2); +	ads_destroy(&ads);  	return WERR_OK; +} + +/**************************************************************************** + * Publish a printer in the directory + * + * @param snum describing printer service + * @return WERROR indicating status of publishing + ***************************************************************************/ + +WERROR nt_printer_publish(int snum, int action) +{ +	NT_PRINTER_INFO_LEVEL *printer = NULL; +	WERROR win_rc; + +	win_rc = get_a_printer(&printer, 2, lp_servicename(snum)); +	if (!W_ERROR_IS_OK(win_rc)) +		return win_rc; + +	switch(action) { +	case SPOOL_DS_PUBLISH: +	case SPOOL_DS_UPDATE: +		win_rc = publish_it(printer); +		break; +	case SPOOL_DS_UNPUBLISH: +		win_rc = unpublish_it(printer); +		break; +	default: +		win_rc = WERR_NOT_SUPPORTED; +	} +	 + +	free_a_printer(&printer, 2); +	return win_rc; +} + +BOOL is_printer_published(int snum, GUID *guid) +{ +	NT_PRINTER_INFO_LEVEL *printer = NULL; +	REGVAL_CTR *ctr; +	REGISTRY_VALUE *guid_val; +	WERROR win_rc; +	int i; + + +	win_rc = get_a_printer(&printer, 2, lp_servicename(snum)); +	if (!W_ERROR_IS_OK(win_rc)) +		return False; + +	if (!(printer->info_2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) +		return False; + +	if ((i = lookup_printerkey(&printer->info_2->data,  +				   SPOOL_DSSPOOLER_KEY)) < 0) +		return False; + +	ctr = &printer->info_2->data.keys[i].values; + +	guid_val = regval_ctr_getvalue(ctr, "objectGUID"); +	if (regval_size(guid_val) == sizeof(GUID)) +		memcpy(guid, regval_data_p(guid_val), sizeof(GUID)); + +	return True; +} +	  #else +WERROR nt_printer_publish(int snum, int action) +{  	return WERR_OK; -#endif  } - +BOOL is_printer_published(int snum, GUID *guid) +{ +	return False; +} +#endif  /****************************************************************************   ***************************************************************************/ diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index 0e3d69924b..6dd4352cbc 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -4154,43 +4154,18 @@ static BOOL construct_printer_info_5(PRINTER_INFO_5 *printer, int snum)  static BOOL construct_printer_info_7(PRINTER_INFO_7 *printer, int snum)  { -#ifdef HAVE_ADS  	char *guid_str = NULL;  	GUID guid; -	ADS_STRUCT *ads; -	ADS_STATUS ads_rc; -	void *res = NULL; -	char *prt_dn; -	const char *attrs[] = {"objectGUID", NULL}; -	 -	printer->action = SPOOL_DS_UNPUBLISH; - -	ads = ads_init(NULL, NULL, lp_ads_server()); -	ads_rc = ads_connect(ads); -	ads_rc = ads_find_printer_on_server(ads, &res, lp_servicename(snum), -					    global_myname()); -	if (ADS_ERR_OK(ads_rc) && ads_count_replies(ads, res)) { -		prt_dn = ads_get_dn(ads, res); -		ads_msgfree(ads, res); -		if (prt_dn &&  -		    ADS_ERR_OK(ads_search_dn(ads, &res, prt_dn, attrs))) { -			ads_rc = ads_search_dn(ads, &res, prt_dn, attrs); -			ads_memfree(ads, prt_dn); -			ads_pull_guid(ads, res, &guid); -			printer->action = SPOOL_DS_PUBLISH; -		} -	} - -	ads_msgfree(ads, res); -	asprintf(&guid_str, "{%s}", uuid_string_static(guid)); -	strupper(guid_str); -	init_unistr(&printer->guid, guid_str); - -#else -	printer->action = SPOOL_DS_UNPUBLISH; -	init_unistr(&printer->guid, ""); -#endif +	if (is_printer_published(snum, &guid)) { +		asprintf(&guid_str, "{%s}", uuid_string_static(guid)); +		strupper(guid_str); +		init_unistr(&printer->guid, guid_str); +		printer->action = SPOOL_DS_PUBLISH; +	} else { +		init_unistr(&printer->guid, ""); +		printer->action = SPOOL_DS_UNPUBLISH; +	}  	return True;  }  | 
