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; } |