ctdb-failover: Split statd_callout add-client/del-client
[Samba.git] / source3 / printing / nt_printing_ads.c
blob01b787f321210d88577b0c57f6d1e1357c2969b0
1 /*
2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-2000,
5 * Copyright (C) Jean François Micouleau 1998-2000.
6 * Copyright (C) Gerald Carter 2002-2005.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "../librpc/gen_ndr/spoolss.h"
24 #include "rpc_server/spoolss/srv_spoolss_util.h"
25 #include "nt_printing.h"
26 #include "ads.h"
27 #include "secrets.h"
28 #include "../libcli/registry/util_reg.h"
29 #include "auth.h"
30 #include "../librpc/ndr/libndr.h"
31 #include "rpc_client/cli_winreg_spoolss.h"
33 #ifdef HAVE_ADS
34 /*****************************************************************
35 ****************************************************************/
37 WERROR nt_printer_guid_store(struct messaging_context *msg_ctx,
38 const char *printer, struct GUID guid)
40 TALLOC_CTX *tmp_ctx;
41 const struct auth_session_info *session_info;
42 const char *guid_str;
43 DATA_BLOB blob;
44 WERROR result;
46 tmp_ctx = talloc_new(NULL);
47 if (!tmp_ctx) {
48 DEBUG(0, ("Out of memory?!\n"));
49 return WERR_NOT_ENOUGH_MEMORY;
52 session_info = get_session_info_system();
53 if (session_info == NULL) {
54 DEBUG(0, ("Could not get system session_info\n"));
55 result = WERR_NOT_ENOUGH_MEMORY;
56 goto done;
59 guid_str = GUID_string(tmp_ctx, &guid);
60 if (!guid_str) {
61 DEBUG(0, ("Out of memory?!\n"));
62 result = WERR_NOT_ENOUGH_MEMORY;
63 goto done;
66 /* We used to store this as a REG_BINARY but that causes
67 Vista to whine */
69 if (!push_reg_sz(tmp_ctx, &blob, guid_str)) {
70 DEBUG(0, ("Could not marshall string %s for objectGUID\n",
71 guid_str));
72 result = WERR_NOT_ENOUGH_MEMORY;
73 goto done;
76 result = winreg_set_printer_dataex_internal(tmp_ctx, session_info, msg_ctx,
77 printer,
78 SPOOL_DSSPOOLER_KEY, "objectGUID",
79 REG_SZ, blob.data, blob.length);
80 if (!W_ERROR_IS_OK(result)) {
81 DEBUG(0, ("Failed to store GUID for printer %s\n", printer));
82 goto done;
85 result = WERR_OK;
86 done:
87 talloc_free(tmp_ctx);
89 return result;
92 static WERROR nt_printer_dn_lookup(TALLOC_CTX *mem_ctx,
93 ADS_STRUCT *ads,
94 const char *printer,
95 char **pprinter_dn)
97 char *printer_dn = NULL;
98 char *srv_dn = NULL;
99 char *srv_cn_0 = NULL;
100 char *srv_cn_escaped = NULL;
101 char *sharename_escaped = NULL;
102 char *srv_dn_utf8 = NULL;
103 char **srv_cn_utf8 = NULL;
104 size_t converted_size;
105 ADS_STATUS ads_status;
106 LDAPMessage *res;
107 WERROR result;
108 bool ok;
110 ads_status = ads_find_machine_acct(ads, &res, lp_netbios_name());
111 if (!ADS_ERR_OK(ads_status)) {
112 DEBUG(2, ("Failed to find machine account for %s\n",
113 lp_netbios_name()));
114 result = WERR_NOT_FOUND;
115 goto err_out;
119 * We use ldap_get_dn here as we need the answer in utf8 to call
120 * ldap_explode_dn(). JRA.
122 srv_dn_utf8 = ldap_get_dn((LDAP *)ads->ldap.ld, (LDAPMessage *)res);
123 ads_msgfree(ads, res);
124 if (srv_dn_utf8 == NULL) {
125 result = WERR_RPC_S_SERVER_UNAVAILABLE;
126 goto err_out;
129 srv_cn_utf8 = ldap_explode_dn(srv_dn_utf8, 1);
130 if (srv_cn_utf8 == NULL) {
131 ldap_memfree(srv_dn_utf8);
132 result = WERR_RPC_S_SERVER_UNAVAILABLE;
133 goto err_out;
136 /* Now convert to CH_UNIX. */
137 ok = pull_utf8_talloc(mem_ctx, &srv_dn, srv_dn_utf8, &converted_size);
138 ldap_memfree(srv_dn_utf8);
139 if (!ok) {
140 ldap_memfree(srv_cn_utf8);
141 result = WERR_RPC_S_SERVER_UNAVAILABLE;
142 goto err_out;
145 ok = pull_utf8_talloc(mem_ctx, &srv_cn_0, srv_cn_utf8[0], &converted_size);
146 ldap_memfree(srv_cn_utf8);
147 if (!ok) {
148 result = WERR_RPC_S_SERVER_UNAVAILABLE;
149 goto err_out;
152 srv_cn_escaped = escape_rdn_val_string_alloc(srv_cn_0);
153 if (srv_cn_escaped == NULL) {
154 result = WERR_RPC_S_SERVER_UNAVAILABLE;
155 goto err_out;
158 sharename_escaped = escape_rdn_val_string_alloc(printer);
159 if (sharename_escaped == NULL) {
160 result = WERR_RPC_S_SERVER_UNAVAILABLE;
161 goto err_out;
164 printer_dn = talloc_asprintf(mem_ctx,
165 "cn=%s-%s,%s",
166 srv_cn_escaped,
167 sharename_escaped,
168 srv_dn);
169 if (printer_dn == NULL) {
170 result = WERR_NOT_ENOUGH_MEMORY;
171 goto err_out;
174 *pprinter_dn = printer_dn;
176 result = WERR_OK;
177 err_out:
178 SAFE_FREE(sharename_escaped);
179 SAFE_FREE(srv_cn_escaped);
180 TALLOC_FREE(srv_cn_0);
181 TALLOC_FREE(srv_dn);
182 return result;
185 static WERROR nt_printer_guid_retrieve_internal(ADS_STRUCT *ads,
186 const char *printer_dn,
187 struct GUID *pguid)
189 ADS_STATUS ads_status;
190 LDAPMessage *res;
191 const char *attrs[] = {"objectGUID", NULL};
192 struct GUID guid;
193 bool ok;
195 ads_status = ads_search_dn(ads, &res, printer_dn, attrs);
196 if (!ADS_ERR_OK(ads_status)) {
197 DEBUG(2, ("Failed to retrieve GUID from DC - %s\n",
198 ads_errstr(ads_status)));
199 return WERR_FILE_NOT_FOUND;
202 ZERO_STRUCT(guid);
203 ok = ads_pull_guid(ads, res, &guid);
204 ads_msgfree(ads, res);
205 if (!ok) {
206 return WERR_NOT_ENOUGH_MEMORY;
209 *pguid = guid;
211 return WERR_OK;
214 WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
215 struct GUID *pguid)
217 ADS_STRUCT *ads = NULL;
218 char *printer_dn;
219 WERROR result;
220 ADS_STATUS ads_status;
221 TALLOC_CTX *tmp_ctx = talloc_stackframe();
223 ads = ads_init(tmp_ctx,
224 lp_realm(),
225 lp_workgroup(),
226 NULL,
227 ADS_SASL_PLAIN);
228 if (ads == NULL) {
229 result = WERR_RPC_S_SERVER_UNAVAILABLE;
230 goto out;
233 ads_status = ads_connect_machine(ads);
234 if (!ADS_ERR_OK(ads_status)) {
235 DEBUG(3, ("ads_connect_machine failed: %s\n", ads_errstr(ads_status)));
236 result = WERR_ACCESS_DENIED;
237 goto out;
240 result = nt_printer_dn_lookup(tmp_ctx, ads, printer, &printer_dn);
241 if (!W_ERROR_IS_OK(result)) {
242 goto out;
245 result = nt_printer_guid_retrieve_internal(ads, printer_dn, pguid);
246 out:
247 TALLOC_FREE(tmp_ctx);
249 return result;
252 WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
253 const struct auth_session_info *session_info,
254 struct messaging_context *msg_ctx,
255 const char *printer, struct GUID *guid)
257 TALLOC_CTX *tmp_ctx;
258 enum winreg_Type type;
259 DATA_BLOB blob;
260 uint32_t len;
261 NTSTATUS status;
262 WERROR result;
264 tmp_ctx = talloc_new(mem_ctx);
265 if (tmp_ctx == NULL) {
266 DEBUG(0, ("out of memory?!\n"));
267 return WERR_NOT_ENOUGH_MEMORY;
270 result = winreg_get_printer_dataex_internal(tmp_ctx, session_info,
271 msg_ctx, printer,
272 SPOOL_DSSPOOLER_KEY,
273 "objectGUID",
274 &type,
275 &blob.data,
276 &len);
277 if (!W_ERROR_IS_OK(result)) {
278 DEBUG(0, ("Failed to get GUID for printer %s\n", printer));
279 goto out_ctx_free;
281 blob.length = (size_t)len;
283 /* We used to store the guid as REG_BINARY, then swapped
284 to REG_SZ for Vista compatibility so check for both */
286 switch (type) {
287 case REG_SZ: {
288 bool ok;
289 const char *guid_str;
290 ok = pull_reg_sz(tmp_ctx, &blob, &guid_str);
291 if (!ok) {
292 DEBUG(0, ("Failed to unmarshall GUID for printer %s\n",
293 printer));
294 result = WERR_REGISTRY_CORRUPT;
295 goto out_ctx_free;
297 status = GUID_from_string(guid_str, guid);
298 if (!NT_STATUS_IS_OK(status)) {
299 DEBUG(0, ("bad GUID for printer %s\n", printer));
300 result = ntstatus_to_werror(status);
301 goto out_ctx_free;
303 break;
305 case REG_BINARY:
306 if (blob.length != sizeof(struct GUID)) {
307 DEBUG(0, ("bad GUID for printer %s\n", printer));
308 result = WERR_REGISTRY_CORRUPT;
309 goto out_ctx_free;
311 memcpy(guid, blob.data, sizeof(struct GUID));
312 break;
313 default:
314 DEBUG(0,("GUID value stored as invalid type (%d)\n", type));
315 result = WERR_REGISTRY_CORRUPT;
316 goto out_ctx_free;
317 break;
319 result = WERR_OK;
321 out_ctx_free:
322 talloc_free(tmp_ctx);
323 return result;
326 static WERROR nt_printer_devmode_to_mods(TALLOC_CTX *ctx,
327 struct spoolss_DeviceMode *devmode,
328 ADS_MODLIST *mods)
330 char *str = NULL;
331 ADS_STATUS status;
334 the device mode fields bits allow us to make an educated guess if a
335 printer feature is supported. For sure a feature must be unsupported if
336 the fields bit is not set. Device Mode Extra Data and FeatureOptionPairs
337 might help to figure out more information here. Common attributes, that
338 we can't handle yet:
339 SPOOL_REG_PRINTBINNAMES - printBinNames
340 SPOOL_REG_PRINTMAXXEXTENT - printMaxXExtent
341 SPOOL_REG_PRINTMAXYEXTENT - printMaxYExtent
342 SPOOL_REG_PRINTMINXEXTENT - printMinXExtent
343 SPOOL_REG_PRINTMINYEXTENT - printMinYExtent
344 SPOOL_REG_PRINTSTAPLINGSUPPORTED - printStaplingSupported
345 SPOOL_REG_PRINTPAGESPERMINUTE - printPagesPerMinute
346 SPOOL_REG_PRINTRATE - printRate
347 SPOOL_REG_PRINTRATEUNIT - printRateUnit
348 SPOOL_REG_PRINTMEDIAREADY - printMediaReady
349 SPOOL_REG_PRINTMEDIASUPPORTED - printMediaSupported
350 SPOOL_REG_PRINTNUMBERUP - printNumberUp
351 SPOOL_REG_PRINTMAXCOPIES - printMaxCopies
353 if (devmode->fields & DEVMODE_COLOR) {
354 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLOR, "TRUE");
355 } else {
356 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLOR, "FALSE");
358 if (!ADS_ERR_OK(status)) {
359 return WERR_NOT_ENOUGH_MEMORY;
362 if (devmode->fields & DEVMODE_DUPLEX) {
363 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTDUPLEXSUPPORTED, "TRUE");
364 } else {
365 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTDUPLEXSUPPORTED, "FALSE");
367 if (!ADS_ERR_OK(status)) {
368 return WERR_NOT_ENOUGH_MEMORY;
371 if (devmode->fields & DEVMODE_COLLATE) {
372 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLLATE, "TRUE");
373 } else {
374 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTCOLLATE, "FALSE");
376 if (!ADS_ERR_OK(status)) {
377 return WERR_NOT_ENOUGH_MEMORY;
380 /* portrait mode is always supported, LANDSCAPE is optional */
381 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTORIENTATIONSSUPPORTED, "PORTRAIT");
382 if (!ADS_ERR_OK(status)) {
383 return WERR_NOT_ENOUGH_MEMORY;
385 if (devmode->fields & DEVMODE_ORIENTATION) {
386 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTORIENTATIONSSUPPORTED, "LANDSCAPE");
387 if (!ADS_ERR_OK(status)) {
388 return WERR_NOT_ENOUGH_MEMORY;
392 /* the driverVersion attribute in AD contains actually specversion */
393 str = talloc_asprintf(ctx, "%u", devmode->specversion);
394 if (str == NULL) {
395 return WERR_NOT_ENOUGH_MEMORY;
397 if (strlen(str) != 0) {
398 status = ads_mod_str(ctx, mods, SPOOL_REG_DRIVERVERSION, str);
399 if (!ADS_ERR_OK(status)) {
400 return WERR_NOT_ENOUGH_MEMORY;
404 /* devmode->yresolution is a good candidate for printMaxResolutionSupported */
405 str = talloc_asprintf(ctx, "%u", devmode->yresolution);
406 if (str == NULL) {
407 return WERR_NOT_ENOUGH_MEMORY;
409 if (strlen(str) != 0) {
410 status = ads_mod_str(ctx, mods, SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, str);
411 if (!ADS_ERR_OK(status)) {
412 return WERR_NOT_ENOUGH_MEMORY;
416 return WERR_OK;
421 static WERROR nt_printer_info_to_mods(TALLOC_CTX *ctx,
422 struct spoolss_PrinterInfo2 *info2,
423 ADS_MODLIST *mods)
425 char *info_str;
427 ads_mod_str(ctx, mods, SPOOL_REG_PRINTERNAME, info2->sharename);
428 ads_mod_str(ctx, mods, SPOOL_REG_PRINTSHARENAME, info2->sharename);
429 ads_mod_str(ctx, mods, SPOOL_REG_SHORTSERVERNAME, lp_netbios_name());
430 ads_mod_str(ctx, mods, SPOOL_REG_SERVERNAME, get_mydnsfullname());
432 info_str = talloc_asprintf(ctx, "\\\\%s\\%s",
433 get_mydnsfullname(), info2->sharename);
434 if (info_str == NULL) {
435 return WERR_NOT_ENOUGH_MEMORY;
437 ads_mod_str(ctx, mods, SPOOL_REG_UNCNAME, info_str);
439 info_str = talloc_asprintf(ctx, "%d", 4);
440 if (info_str == NULL) {
441 return WERR_NOT_ENOUGH_MEMORY;
443 ads_mod_str(ctx, mods, SPOOL_REG_VERSIONNUMBER, info_str);
445 /* empty strings in the mods list result in an attribute error */
446 if (strlen(info2->drivername) != 0)
447 ads_mod_str(ctx, mods, SPOOL_REG_DRIVERNAME, info2->drivername);
448 if (strlen(info2->location) != 0)
449 ads_mod_str(ctx, mods, SPOOL_REG_LOCATION, info2->location);
450 if (strlen(info2->comment) != 0)
451 ads_mod_str(ctx, mods, SPOOL_REG_DESCRIPTION, info2->comment);
452 if (strlen(info2->portname) != 0)
453 ads_mod_str(ctx, mods, SPOOL_REG_PORTNAME, info2->portname);
454 if (strlen(info2->sepfile) != 0)
455 ads_mod_str(ctx, mods, SPOOL_REG_PRINTSEPARATORFILE, info2->sepfile);
457 info_str = talloc_asprintf(ctx, "%u", info2->starttime);
458 if (info_str == NULL) {
459 return WERR_NOT_ENOUGH_MEMORY;
461 ads_mod_str(ctx, mods, SPOOL_REG_PRINTSTARTTIME, info_str);
463 info_str = talloc_asprintf(ctx, "%u", info2->untiltime);
464 if (info_str == NULL) {
465 return WERR_NOT_ENOUGH_MEMORY;
467 ads_mod_str(ctx, mods, SPOOL_REG_PRINTENDTIME, info_str);
469 info_str = talloc_asprintf(ctx, "%u", info2->priority);
470 if (info_str == NULL) {
471 return WERR_NOT_ENOUGH_MEMORY;
473 ads_mod_str(ctx, mods, SPOOL_REG_PRIORITY, info_str);
475 if (info2->attributes & PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS) {
476 ads_mod_str(ctx, mods, SPOOL_REG_PRINTKEEPPRINTEDJOBS, "TRUE");
477 } else {
478 ads_mod_str(ctx, mods, SPOOL_REG_PRINTKEEPPRINTEDJOBS, "FALSE");
481 switch (info2->attributes & 0x3) {
482 case 0:
483 ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
484 SPOOL_REGVAL_PRINTWHILESPOOLING);
485 break;
486 case 1:
487 ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
488 SPOOL_REGVAL_PRINTAFTERSPOOLED);
489 break;
490 case 2:
491 ads_mod_str(ctx, mods, SPOOL_REG_PRINTSPOOLING,
492 SPOOL_REGVAL_PRINTDIRECT);
493 break;
494 default:
495 DEBUG(3, ("unsupported printer attributes %x\n",
496 info2->attributes));
499 if (info2->devmode != NULL) {
500 WERROR werr;
501 werr = nt_printer_devmode_to_mods(ctx, info2->devmode, mods);
502 if (!W_ERROR_IS_OK(werr)) {
503 return werr;
507 return WERR_OK;
510 static WERROR nt_printer_publish_ads(struct messaging_context *msg_ctx,
511 ADS_STRUCT *ads,
512 struct spoolss_PrinterInfo2 *pinfo2)
514 ADS_STATUS ads_rc;
515 TALLOC_CTX *ctx = talloc_stackframe();
516 ADS_MODLIST mods;
517 struct GUID guid;
518 WERROR win_rc = WERR_OK;
519 const char *printer = pinfo2->sharename;
520 char *printer_dn = NULL;
522 /* build the ads mods */
523 DEBUG(5, ("publishing printer %s\n", printer));
525 win_rc = nt_printer_dn_lookup(ctx, ads, printer, &printer_dn);
526 if (!W_ERROR_IS_OK(win_rc)) {
527 DEBUG(2, ("Failed to create printer dn\n"));
528 TALLOC_FREE(ctx);
529 return win_rc;
532 mods = ads_init_mods(ctx);
534 if (mods == NULL) {
535 TALLOC_FREE(ctx);
536 return WERR_NOT_ENOUGH_MEMORY;
539 win_rc = nt_printer_info_to_mods(ctx, pinfo2, &mods);
540 if (!W_ERROR_IS_OK(win_rc)) {
541 TALLOC_FREE(ctx);
542 return win_rc;
545 /* publish it */
546 ads_rc = ads_mod_printer_entry(ads, printer_dn, ctx, &mods);
547 if (ads_rc.err.rc == LDAP_NO_SUCH_OBJECT) {
548 int i;
549 for (i=0; mods[i] != 0; i++)
551 mods[i] = (LDAPMod *)-1;
552 ads_rc = ads_add_printer_entry(ads, printer_dn, ctx, &mods);
555 if (!ADS_ERR_OK(ads_rc)) {
556 DEBUG(3, ("error publishing %s: %s\n",
557 printer, ads_errstr(ads_rc)));
558 /* XXX failed to publish, so no guid to retrieve */
561 win_rc = nt_printer_guid_retrieve_internal(ads, printer_dn, &guid);
562 if (!W_ERROR_IS_OK(win_rc)) {
563 TALLOC_FREE(ctx);
564 return win_rc;
567 win_rc = nt_printer_guid_store(msg_ctx, printer, guid);
568 if (!W_ERROR_IS_OK(win_rc)) {
569 DEBUG(3, ("failed to store printer %s guid\n",
570 printer));
571 /* not catastrophic, retrieve on next use */
572 win_rc = WERR_OK;
575 TALLOC_FREE(ctx);
577 return win_rc;
580 static WERROR nt_printer_unpublish_ads(ADS_STRUCT *ads,
581 const char *printer)
583 ADS_STATUS ads_rc;
584 LDAPMessage *res = NULL;
585 char *prt_dn = NULL;
587 DEBUG(5, ("unpublishing printer %s\n", printer));
589 /* remove the printer from the directory */
590 ads_rc = ads_find_printer_on_server(ads, &res,
591 printer, lp_netbios_name());
593 if (ADS_ERR_OK(ads_rc) && res && ads_count_replies(ads, res)) {
594 prt_dn = ads_get_dn(ads, talloc_tos(), res);
595 if (!prt_dn) {
596 ads_msgfree(ads, res);
597 return WERR_NOT_ENOUGH_MEMORY;
599 ads_rc = ads_del_dn(ads, prt_dn);
600 TALLOC_FREE(prt_dn);
603 if (res) {
604 ads_msgfree(ads, res);
606 return WERR_OK;
609 /****************************************************************************
610 * Publish a printer in the directory
612 * @param mem_ctx memory context
613 * @param session_info session_info to access winreg pipe
614 * @param pinfo2 printer information
615 * @param action publish/unpublish action
616 * @return WERROR indicating status of publishing
617 ***************************************************************************/
619 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
620 const struct auth_session_info *session_info,
621 struct messaging_context *msg_ctx,
622 struct spoolss_PrinterInfo2 *pinfo2,
623 int action)
625 TALLOC_CTX *tmp_ctx = talloc_stackframe();
626 uint32_t info2_mask = SPOOLSS_PRINTER_INFO_ATTRIBUTES;
627 struct spoolss_SetPrinterInfo2 *sinfo2;
628 ADS_STATUS ads_rc;
629 ADS_STRUCT *ads = NULL;
630 WERROR win_rc;
632 sinfo2 = talloc_zero(tmp_ctx, struct spoolss_SetPrinterInfo2);
633 if (!sinfo2) {
634 win_rc = WERR_NOT_ENOUGH_MEMORY;
635 goto done;
638 switch (action) {
639 case DSPRINT_PUBLISH:
640 case DSPRINT_UPDATE:
641 pinfo2->attributes |= PRINTER_ATTRIBUTE_PUBLISHED;
642 break;
643 case DSPRINT_UNPUBLISH:
644 pinfo2->attributes &= (~PRINTER_ATTRIBUTE_PUBLISHED);
645 break;
646 default:
647 win_rc = WERR_NOT_SUPPORTED;
648 goto done;
651 sinfo2->attributes = pinfo2->attributes;
653 win_rc = winreg_update_printer_internal(tmp_ctx, session_info, msg_ctx,
654 pinfo2->sharename, info2_mask,
655 sinfo2, NULL, NULL);
656 if (!W_ERROR_IS_OK(win_rc)) {
657 DBG_NOTICE("Failed to update data for printer [%s] - %s\n",
658 pinfo2->sharename,
659 win_errstr(win_rc));
660 goto done;
663 TALLOC_FREE(sinfo2);
665 ads = ads_init(tmp_ctx,
666 lp_realm(),
667 lp_workgroup(),
668 NULL,
669 ADS_SASL_PLAIN);
670 if (!ads) {
671 DEBUG(3, ("ads_init() failed\n"));
672 win_rc = WERR_RPC_S_SERVER_UNAVAILABLE;
673 goto done;
676 /* ads_connect_machine() will find the DC for us */
677 ads_rc = ads_connect_machine(ads);
678 if (!ADS_ERR_OK(ads_rc)) {
679 DEBUG(3, ("ads_connect_machine failed: %s\n", ads_errstr(ads_rc)));
680 win_rc = WERR_ACCESS_DENIED;
681 goto done;
684 switch (action) {
685 case DSPRINT_PUBLISH:
686 case DSPRINT_UPDATE:
687 win_rc = nt_printer_publish_ads(msg_ctx, ads, pinfo2);
688 break;
689 case DSPRINT_UNPUBLISH:
690 win_rc = nt_printer_unpublish_ads(ads, pinfo2->sharename);
691 break;
694 done:
695 TALLOC_FREE(tmp_ctx);
697 return win_rc;
700 WERROR check_published_printers(struct messaging_context *msg_ctx)
702 const struct loadparm_substitution *lp_sub =
703 loadparm_s3_global_substitution();
704 ADS_STATUS ads_rc;
705 ADS_STRUCT *ads = NULL;
706 int snum;
707 int n_services = lp_numservices();
708 TALLOC_CTX *tmp_ctx = talloc_stackframe();
709 struct auth_session_info *session_info = NULL;
710 struct spoolss_PrinterInfo2 *pinfo2;
711 NTSTATUS status;
712 WERROR result;
714 ads = ads_init(tmp_ctx,
715 lp_realm(),
716 lp_workgroup(),
717 NULL,
718 ADS_SASL_PLAIN);
719 if (!ads) {
720 DEBUG(3, ("ads_init() failed\n"));
721 TALLOC_FREE(tmp_ctx);
722 return WERR_RPC_S_SERVER_UNAVAILABLE;
725 /* ads_connect_machine() will find the DC for us */
726 ads_rc = ads_connect_machine(ads);
727 if (!ADS_ERR_OK(ads_rc)) {
728 DEBUG(3, ("ads_connect_machine failed: %s\n", ads_errstr(ads_rc)));
729 result = WERR_ACCESS_DENIED;
730 goto done;
733 status = make_session_info_system(tmp_ctx, &session_info);
734 if (!NT_STATUS_IS_OK(status)) {
735 DEBUG(0, ("check_published_printers: "
736 "Could not create system session_info\n"));
737 result = WERR_ACCESS_DENIED;
738 goto done;
741 for (snum = 0; snum < n_services; snum++) {
742 if (!lp_snum_ok(snum) || !lp_printable(snum)) {
743 continue;
746 result = winreg_get_printer_internal(tmp_ctx, session_info, msg_ctx,
747 lp_servicename(talloc_tos(), lp_sub, snum),
748 &pinfo2);
749 if (!W_ERROR_IS_OK(result)) {
750 continue;
753 if (pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED) {
754 nt_printer_publish_ads(msg_ctx, ads, pinfo2);
757 TALLOC_FREE(pinfo2);
760 result = WERR_OK;
761 done:
762 talloc_free(tmp_ctx);
763 return result;
766 bool is_printer_published(TALLOC_CTX *mem_ctx,
767 const struct auth_session_info *session_info,
768 struct messaging_context *msg_ctx,
769 const char *servername,
770 const char *printer,
771 struct spoolss_PrinterInfo2 **info2)
773 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
774 WERROR result;
775 struct dcerpc_binding_handle *b;
777 result = winreg_printer_binding_handle(mem_ctx,
778 session_info,
779 msg_ctx,
780 &b);
781 if (!W_ERROR_IS_OK(result)) {
782 return false;
785 result = winreg_get_printer(mem_ctx, b,
786 printer, &pinfo2);
787 if (!W_ERROR_IS_OK(result)) {
788 return false;
791 if (!(pinfo2->attributes & PRINTER_ATTRIBUTE_PUBLISHED)) {
792 TALLOC_FREE(pinfo2);
793 return false;
796 if (info2) {
797 *info2 = talloc_move(mem_ctx, &pinfo2);
799 talloc_free(pinfo2);
800 return true;
802 #else
803 WERROR nt_printer_guid_store(struct messaging_context *msg_ctx,
804 const char *printer, struct GUID guid)
806 return WERR_NOT_SUPPORTED;
809 WERROR nt_printer_guid_retrieve(TALLOC_CTX *mem_ctx, const char *printer,
810 struct GUID *pguid)
812 return WERR_NOT_SUPPORTED;
815 WERROR nt_printer_guid_get(TALLOC_CTX *mem_ctx,
816 const struct auth_session_info *session_info,
817 struct messaging_context *msg_ctx,
818 const char *printer, struct GUID *guid)
820 return WERR_NOT_SUPPORTED;
823 WERROR nt_printer_publish(TALLOC_CTX *mem_ctx,
824 const struct auth_session_info *session_info,
825 struct messaging_context *msg_ctx,
826 struct spoolss_PrinterInfo2 *pinfo2,
827 int action)
829 return WERR_OK;
832 WERROR check_published_printers(struct messaging_context *msg_ctx)
834 return WERR_OK;
837 bool is_printer_published(TALLOC_CTX *mem_ctx,
838 const struct auth_session_info *session_info,
839 struct messaging_context *msg_ctx,
840 const char *servername,
841 const char *printer,
842 struct spoolss_PrinterInfo2 **info2)
844 return False;
846 #endif /* HAVE_ADS */