s3-spoolss: use rpccli_spoolss_enumprinterdataex in ldap_printer.c.
[Samba/gbeck.git] / source3 / libads / ldap_printer.c
blobe3e8e918f551b1aa8572aa44efed75193fdb2367
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"
22 #ifdef HAVE_ADS
25 find a printer given the name and the hostname
26 Note that results "res" may be allocated on return so that the
27 results can be used. It should be freed using ads_msgfree.
29 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
30 const char *printer,
31 const char *servername)
33 ADS_STATUS status;
34 char *srv_dn, **srv_cn, *s = NULL;
35 const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
37 status = ads_find_machine_acct(ads, res, servername);
38 if (!ADS_ERR_OK(status)) {
39 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
40 servername));
41 return status;
43 if (ads_count_replies(ads, *res) != 1) {
44 if (res) {
45 ads_msgfree(ads, *res);
46 *res = NULL;
48 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
50 srv_dn = ldap_get_dn(ads->ldap.ld, *res);
51 if (srv_dn == NULL) {
52 if (res) {
53 ads_msgfree(ads, *res);
54 *res = NULL;
56 return ADS_ERROR(LDAP_NO_MEMORY);
58 srv_cn = ldap_explode_dn(srv_dn, 1);
59 if (srv_cn == NULL) {
60 ldap_memfree(srv_dn);
61 if (res) {
62 ads_msgfree(ads, *res);
63 *res = NULL;
65 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
67 if (res) {
68 ads_msgfree(ads, *res);
69 *res = NULL;
72 if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
73 ldap_memfree(srv_dn);
74 return ADS_ERROR(LDAP_NO_MEMORY);
76 status = ads_search(ads, res, s, attrs);
78 ldap_memfree(srv_dn);
79 ldap_value_free(srv_cn);
80 SAFE_FREE(s);
81 return status;
84 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
86 const char *ldap_expr;
87 const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
88 "serverName", "description", NULL };
90 /* For the moment only display all printers */
92 ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
93 "(objectCategory=printQueue))";
95 return ads_search(ads, res, ldap_expr, attrs);
99 modify a printer entry in the directory
101 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
102 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
104 return ads_gen_mod(ads, prt_dn, *mods);
108 add a printer to the directory
110 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
111 TALLOC_CTX *ctx, ADS_MODLIST *mods)
113 ads_mod_str(ctx, mods, "objectClass", "printQueue");
114 return ads_gen_add(ads, prt_dn, *mods);
118 map a REG_SZ to an ldap mod
120 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
121 const REGISTRY_VALUE *value)
123 char *str_value = NULL;
124 size_t converted_size;
125 ADS_STATUS status;
127 if (value->type != REG_SZ)
128 return false;
130 if (value->size && *((smb_ucs2_t *) value->data_p)) {
131 if (!pull_ucs2_talloc(ctx, &str_value,
132 (const smb_ucs2_t *) value->data_p,
133 &converted_size))
135 return false;
137 status = ads_mod_str(ctx, mods, value->valuename, str_value);
138 return ADS_ERR_OK(status);
140 return true;
145 map a REG_DWORD to an ldap mod
147 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
148 const REGISTRY_VALUE *value)
150 char *str_value = NULL;
151 ADS_STATUS status;
153 if (value->type != REG_DWORD)
154 return False;
155 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) value->data_p));
156 if (!str_value) {
157 return False;
159 status = ads_mod_str(ctx, mods, value->valuename, str_value);
160 return ADS_ERR_OK(status);
164 map a boolean REG_BINARY to an ldap mod
166 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
167 const REGISTRY_VALUE *value)
169 char *str_value;
170 ADS_STATUS status;
172 if ((value->type != REG_BINARY) || (value->size != 1))
173 return False;
174 str_value = talloc_asprintf(ctx, "%s",
175 *(value->data_p) ? "TRUE" : "FALSE");
176 if (!str_value) {
177 return False;
179 status = ads_mod_str(ctx, mods, value->valuename, str_value);
180 return ADS_ERR_OK(status);
184 map a REG_MULTI_SZ to an ldap mod
186 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
187 const REGISTRY_VALUE *value)
189 char **str_values = NULL;
190 size_t converted_size;
191 smb_ucs2_t *cur_str = (smb_ucs2_t *) value->data_p;
192 uint32 size = 0, num_vals = 0, i=0;
193 ADS_STATUS status;
195 if (value->type != REG_MULTI_SZ)
196 return False;
198 while(cur_str && *cur_str && (size < value->size)) {
199 size += 2 * (strlen_w(cur_str) + 1);
200 cur_str += strlen_w(cur_str) + 1;
201 num_vals++;
204 if (num_vals) {
205 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
206 if (!str_values) {
207 return False;
209 memset(str_values, '\0',
210 (num_vals + 1) * sizeof(char *));
212 cur_str = (smb_ucs2_t *) value->data_p;
213 for (i=0; i < num_vals; i++) {
214 cur_str += pull_ucs2_talloc(ctx, &str_values[i],
215 cur_str, &converted_size) ?
216 converted_size : (size_t)-1;
219 status = ads_mod_strlist(ctx, mods, value->valuename,
220 (const char **) str_values);
221 return ADS_ERR_OK(status);
223 return True;
226 struct valmap_to_ads {
227 const char *valname;
228 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *);
232 map a REG_SZ to an ldap mod
234 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
235 REGISTRY_VALUE *value)
237 const struct valmap_to_ads map[] = {
238 {SPOOL_REG_ASSETNUMBER, map_sz},
239 {SPOOL_REG_BYTESPERMINUTE, map_dword},
240 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
241 {SPOOL_REG_DESCRIPTION, map_sz},
242 {SPOOL_REG_DRIVERNAME, map_sz},
243 {SPOOL_REG_DRIVERVERSION, map_dword},
244 {SPOOL_REG_FLAGS, map_dword},
245 {SPOOL_REG_LOCATION, map_sz},
246 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
247 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
248 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
249 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
250 {SPOOL_REG_PORTNAME, map_multi_sz},
251 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
252 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
253 {SPOOL_REG_PRINTCOLLATE, map_bool},
254 {SPOOL_REG_PRINTCOLOR, map_bool},
255 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
256 {SPOOL_REG_PRINTENDTIME, map_dword},
257 {SPOOL_REG_PRINTFORMNAME, map_sz},
258 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
259 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
260 {SPOOL_REG_PRINTMACADDRESS, map_sz},
261 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
262 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
263 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
264 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
265 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
266 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
267 {SPOOL_REG_PRINTMEMORY, map_dword},
268 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
269 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
270 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
271 {SPOOL_REG_PRINTNOTIFY, map_sz},
272 {SPOOL_REG_PRINTNUMBERUP, map_dword},
273 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
274 {SPOOL_REG_PRINTOWNER, map_sz},
275 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
276 {SPOOL_REG_PRINTRATE, map_dword},
277 {SPOOL_REG_PRINTRATEUNIT, map_sz},
278 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
279 {SPOOL_REG_PRINTSHARENAME, map_sz},
280 {SPOOL_REG_PRINTSPOOLING, map_sz},
281 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
282 {SPOOL_REG_PRINTSTARTTIME, map_dword},
283 {SPOOL_REG_PRINTSTATUS, map_sz},
284 {SPOOL_REG_PRIORITY, map_dword},
285 {SPOOL_REG_SERVERNAME, map_sz},
286 {SPOOL_REG_SHORTSERVERNAME, map_sz},
287 {SPOOL_REG_UNCNAME, map_sz},
288 {SPOOL_REG_URL, map_sz},
289 {SPOOL_REG_VERSIONNUMBER, map_dword},
290 {NULL, NULL}
292 int i;
294 for (i=0; map[i].valname; i++) {
295 if (StrCaseCmp(map[i].valname, value->valuename) == 0) {
296 if (!map[i].fn(ctx, mods, value)) {
297 DEBUG(5, ("Add of value %s to modlist failed\n", value->valuename));
298 } else {
299 DEBUG(7, ("Mapped value %s\n", value->valuename));
307 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
308 TALLOC_CTX *mem_ctx,
309 ADS_MODLIST *mods,
310 const char *printer)
312 WERROR result;
313 char *printername;
314 struct spoolss_PrinterEnumValues *info;
315 uint32_t count;
316 uint32 i;
317 POLICY_HND pol;
319 if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
320 DEBUG(3, ("Insufficient memory\n"));
321 return WERR_NOMEM;
324 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
325 printername,
326 SEC_FLAG_MAXIMUM_ALLOWED,
327 &pol);
328 if (!W_ERROR_IS_OK(result)) {
329 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
330 printername, win_errstr(result)));
331 SAFE_FREE(printername);
332 return result;
335 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
336 SPOOL_DSDRIVER_KEY,
338 &count,
339 &info);
341 if (!W_ERROR_IS_OK(result)) {
342 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
343 printername, win_errstr(result)));
344 } else {
345 /* Have the data we need now, so start building */
346 for (i=0; i < count; i++) {
347 REGISTRY_VALUE v;
348 DATA_BLOB blob;
350 result = push_spoolss_PrinterData(mem_ctx, &blob,
351 info[i].type,
352 info[i].data);
353 if (W_ERROR_IS_OK(result)) {
354 fstrcpy(v.valuename, info[i].value_name);
355 v.type = info[i].type;
356 v.data_p = blob.data;
357 v.size = blob.length;
359 map_regval_to_ads(mem_ctx, mods, &v);
364 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
365 SPOOL_DSSPOOLER_KEY,
367 &count,
368 &info);
369 if (!W_ERROR_IS_OK(result)) {
370 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
371 printername, win_errstr(result)));
372 } else {
373 for (i=0; i < count; i++) {
374 REGISTRY_VALUE v;
375 DATA_BLOB blob;
377 result = push_spoolss_PrinterData(mem_ctx, &blob,
378 info[i].type,
379 info[i].data);
380 if (W_ERROR_IS_OK(result)) {
381 fstrcpy(v.valuename, info[i].value_name);
382 v.type = info[i].type;
383 v.data_p = blob.data;
384 v.size = blob.length;
386 map_regval_to_ads(mem_ctx, mods, &v);
391 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
393 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
394 SAFE_FREE(printername);
396 return result;
399 bool get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
400 ADS_MODLIST *mods,
401 NT_PRINTER_DATA *data)
403 uint32 key,val;
405 for (key=0; key < data->num_keys; key++) {
406 REGVAL_CTR *ctr = data->keys[key].values;
407 for (val=0; val < ctr->num_values; val++)
408 map_regval_to_ads(mem_ctx, mods, ctr->values[val]);
410 return True;
413 #endif