s3:libads:use regval_ctr/blob accessor functions in ldap_printer.c
[Samba/ekacnet.git] / source3 / libads / ldap_printer.c
blobb5321abbf0e0ec00b8163983e13b2e8f825bc2e6
1 /*
2 Unix SMB/CIFS implementation.
3 ads (active directory) printer utility library
4 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "../librpc/gen_ndr/cli_spoolss.h"
22 #include "rpc_client/cli_spoolss.h"
23 #include "registry.h"
25 #ifdef HAVE_ADS
28 find a printer given the name and the hostname
29 Note that results "res" may be allocated on return so that the
30 results can be used. It should be freed using ads_msgfree.
32 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
33 const char *printer,
34 const char *servername)
36 ADS_STATUS status;
37 char *srv_dn, **srv_cn, *s = NULL;
38 const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
40 status = ads_find_machine_acct(ads, res, servername);
41 if (!ADS_ERR_OK(status)) {
42 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
43 servername));
44 return status;
46 if (ads_count_replies(ads, *res) != 1) {
47 if (res) {
48 ads_msgfree(ads, *res);
49 *res = NULL;
51 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
53 srv_dn = ldap_get_dn(ads->ldap.ld, *res);
54 if (srv_dn == NULL) {
55 if (res) {
56 ads_msgfree(ads, *res);
57 *res = NULL;
59 return ADS_ERROR(LDAP_NO_MEMORY);
61 srv_cn = ldap_explode_dn(srv_dn, 1);
62 if (srv_cn == NULL) {
63 ldap_memfree(srv_dn);
64 if (res) {
65 ads_msgfree(ads, *res);
66 *res = NULL;
68 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
70 if (res) {
71 ads_msgfree(ads, *res);
72 *res = NULL;
75 if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
76 ldap_memfree(srv_dn);
77 return ADS_ERROR(LDAP_NO_MEMORY);
79 status = ads_search(ads, res, s, attrs);
81 ldap_memfree(srv_dn);
82 ldap_value_free(srv_cn);
83 SAFE_FREE(s);
84 return status;
87 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
89 const char *ldap_expr;
90 const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
91 "serverName", "description", NULL };
93 /* For the moment only display all printers */
95 ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
96 "(objectCategory=printQueue))";
98 return ads_search(ads, res, ldap_expr, attrs);
102 modify a printer entry in the directory
104 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
105 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
107 return ads_gen_mod(ads, prt_dn, *mods);
111 add a printer to the directory
113 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
114 TALLOC_CTX *ctx, ADS_MODLIST *mods)
116 ads_mod_str(ctx, mods, "objectClass", "printQueue");
117 return ads_gen_add(ads, prt_dn, *mods);
121 map a REG_SZ to an ldap mod
123 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
124 const struct regval_blob *value)
126 char *str_value = NULL;
127 size_t converted_size;
128 ADS_STATUS status;
130 if (regval_type(value) != REG_SZ)
131 return false;
133 if (regval_size(value) && *((smb_ucs2_t *) regval_data_p(value))) {
134 if (!pull_ucs2_talloc(ctx, &str_value,
135 (const smb_ucs2_t *) regval_data_p(value),
136 &converted_size))
138 return false;
140 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
141 return ADS_ERR_OK(status);
143 return true;
148 map a REG_DWORD to an ldap mod
150 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
151 const struct regval_blob *value)
153 char *str_value = NULL;
154 ADS_STATUS status;
156 if (regval_type(value) != REG_DWORD)
157 return False;
158 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) regval_data_p(value)));
159 if (!str_value) {
160 return False;
162 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
163 return ADS_ERR_OK(status);
167 map a boolean REG_BINARY to an ldap mod
169 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
170 const struct regval_blob *value)
172 char *str_value;
173 ADS_STATUS status;
175 if ((regval_type(value) != REG_BINARY) || (regval_size(value) != 1))
176 return False;
177 str_value = talloc_asprintf(ctx, "%s",
178 *(regval_data_p(value)) ? "TRUE" : "FALSE");
179 if (!str_value) {
180 return False;
182 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
183 return ADS_ERR_OK(status);
187 map a REG_MULTI_SZ to an ldap mod
189 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
190 const struct regval_blob *value)
192 char **str_values = NULL;
193 size_t converted_size;
194 smb_ucs2_t *cur_str = (smb_ucs2_t *) regval_data_p(value);
195 uint32 size = 0, num_vals = 0, i=0;
196 ADS_STATUS status;
198 if (regval_type(value) != REG_MULTI_SZ)
199 return False;
201 while(cur_str && *cur_str && (size < regval_size(value))) {
202 size += 2 * (strlen_w(cur_str) + 1);
203 cur_str += strlen_w(cur_str) + 1;
204 num_vals++;
207 if (num_vals) {
208 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
209 if (!str_values) {
210 return False;
212 memset(str_values, '\0',
213 (num_vals + 1) * sizeof(char *));
215 cur_str = (smb_ucs2_t *) regval_data_p(value);
216 for (i=0; i < num_vals; i++) {
217 cur_str += pull_ucs2_talloc(ctx, &str_values[i],
218 cur_str, &converted_size) ?
219 converted_size : (size_t)-1;
222 status = ads_mod_strlist(ctx, mods, regval_name(value),
223 (const char **) str_values);
224 return ADS_ERR_OK(status);
226 return True;
229 struct valmap_to_ads {
230 const char *valname;
231 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, const struct regval_blob *);
235 map a REG_SZ to an ldap mod
237 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
238 struct regval_blob *value)
240 const struct valmap_to_ads map[] = {
241 {SPOOL_REG_ASSETNUMBER, map_sz},
242 {SPOOL_REG_BYTESPERMINUTE, map_dword},
243 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
244 {SPOOL_REG_DESCRIPTION, map_sz},
245 {SPOOL_REG_DRIVERNAME, map_sz},
246 {SPOOL_REG_DRIVERVERSION, map_dword},
247 {SPOOL_REG_FLAGS, map_dword},
248 {SPOOL_REG_LOCATION, map_sz},
249 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
250 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
251 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
252 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
253 {SPOOL_REG_PORTNAME, map_multi_sz},
254 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
255 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
256 {SPOOL_REG_PRINTCOLLATE, map_bool},
257 {SPOOL_REG_PRINTCOLOR, map_bool},
258 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
259 {SPOOL_REG_PRINTENDTIME, map_dword},
260 {SPOOL_REG_PRINTFORMNAME, map_sz},
261 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
262 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
263 {SPOOL_REG_PRINTMACADDRESS, map_sz},
264 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
265 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
266 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
267 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
268 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
269 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
270 {SPOOL_REG_PRINTMEMORY, map_dword},
271 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
272 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
273 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
274 {SPOOL_REG_PRINTNOTIFY, map_sz},
275 {SPOOL_REG_PRINTNUMBERUP, map_dword},
276 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
277 {SPOOL_REG_PRINTOWNER, map_sz},
278 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
279 {SPOOL_REG_PRINTRATE, map_dword},
280 {SPOOL_REG_PRINTRATEUNIT, map_sz},
281 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
282 {SPOOL_REG_PRINTSHARENAME, map_sz},
283 {SPOOL_REG_PRINTSPOOLING, map_sz},
284 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
285 {SPOOL_REG_PRINTSTARTTIME, map_dword},
286 {SPOOL_REG_PRINTSTATUS, map_sz},
287 {SPOOL_REG_PRIORITY, map_dword},
288 {SPOOL_REG_SERVERNAME, map_sz},
289 {SPOOL_REG_SHORTSERVERNAME, map_sz},
290 {SPOOL_REG_UNCNAME, map_sz},
291 {SPOOL_REG_URL, map_sz},
292 {SPOOL_REG_VERSIONNUMBER, map_dword},
293 {NULL, NULL}
295 int i;
297 for (i=0; map[i].valname; i++) {
298 if (StrCaseCmp(map[i].valname, regval_name(value)) == 0) {
299 if (!map[i].fn(ctx, mods, value)) {
300 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value)));
301 } else {
302 DEBUG(7, ("Mapped value %s\n", regval_name(value)));
310 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
311 TALLOC_CTX *mem_ctx,
312 ADS_MODLIST *mods,
313 const char *printer)
315 WERROR result;
316 char *printername;
317 struct spoolss_PrinterEnumValues *info;
318 uint32_t count;
319 uint32 i;
320 struct policy_handle pol;
322 if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
323 DEBUG(3, ("Insufficient memory\n"));
324 return WERR_NOMEM;
327 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
328 printername,
329 SEC_FLAG_MAXIMUM_ALLOWED,
330 &pol);
331 if (!W_ERROR_IS_OK(result)) {
332 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
333 printername, win_errstr(result)));
334 SAFE_FREE(printername);
335 return result;
338 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
339 SPOOL_DSDRIVER_KEY,
341 &count,
342 &info);
344 if (!W_ERROR_IS_OK(result)) {
345 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
346 printername, win_errstr(result)));
347 } else {
348 /* Have the data we need now, so start building */
349 for (i=0; i < count; i++) {
350 struct regval_blob *v;
352 v = regval_compose(mem_ctx, info[i].value_name,
353 info[i].type,
354 info[i].data->data,
355 info[i].data->length);
356 if (v == NULL) {
357 return WERR_NOMEM;
360 map_regval_to_ads(mem_ctx, mods, v);
361 talloc_free(v);
365 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
366 SPOOL_DSSPOOLER_KEY,
368 &count,
369 &info);
370 if (!W_ERROR_IS_OK(result)) {
371 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
372 printername, win_errstr(result)));
373 } else {
374 for (i=0; i < count; i++) {
375 struct regval_blob *v;
377 v = regval_compose(mem_ctx, info[i].value_name,
378 info[i].type,
379 info[i].data->data,
380 info[i].data->length);
381 if (v == NULL) {
382 return WERR_NOMEM;
385 map_regval_to_ads(mem_ctx, mods, v);
386 talloc_free(v);
390 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
392 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
393 SAFE_FREE(printername);
395 return result;
398 bool get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
399 ADS_MODLIST *mods,
400 NT_PRINTER_DATA *data)
402 uint32 key,val;
404 for (key=0; key < data->num_keys; key++) {
405 struct regval_ctr *ctr = data->keys[key].values;
406 for (val=0; val < regval_ctr_numvals(ctr); val++)
407 map_regval_to_ads(mem_ctx, mods, regval_ctr_specific_value(ctr, val));
409 return True;
412 #endif