s4:role transfer - use always type "enum drepl_role_master" for role specifications
[Samba/gebeck_regimport.git] / source3 / libads / ldap_printer.c
blobe4a7d34cf186eb53bb6014e93e41d7ad58cd55e0
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 "ads.h"
22 #include "../librpc/gen_ndr/cli_spoolss.h"
23 #include "rpc_client/cli_spoolss.h"
24 #include "registry.h"
25 #include "registry/reg_objects.h"
26 #include "nt_printing.h"
28 #ifdef HAVE_ADS
31 find a printer given the name and the hostname
32 Note that results "res" may be allocated on return so that the
33 results can be used. It should be freed using ads_msgfree.
35 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
36 const char *printer,
37 const char *servername)
39 ADS_STATUS status;
40 char *srv_dn, **srv_cn, *s = NULL;
41 const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
43 status = ads_find_machine_acct(ads, res, servername);
44 if (!ADS_ERR_OK(status)) {
45 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
46 servername));
47 return status;
49 if (ads_count_replies(ads, *res) != 1) {
50 if (res) {
51 ads_msgfree(ads, *res);
52 *res = NULL;
54 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
56 srv_dn = ldap_get_dn(ads->ldap.ld, *res);
57 if (srv_dn == NULL) {
58 if (res) {
59 ads_msgfree(ads, *res);
60 *res = NULL;
62 return ADS_ERROR(LDAP_NO_MEMORY);
64 srv_cn = ldap_explode_dn(srv_dn, 1);
65 if (srv_cn == NULL) {
66 ldap_memfree(srv_dn);
67 if (res) {
68 ads_msgfree(ads, *res);
69 *res = NULL;
71 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
73 if (res) {
74 ads_msgfree(ads, *res);
75 *res = NULL;
78 if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
79 ldap_memfree(srv_dn);
80 return ADS_ERROR(LDAP_NO_MEMORY);
82 status = ads_search(ads, res, s, attrs);
84 ldap_memfree(srv_dn);
85 ldap_value_free(srv_cn);
86 SAFE_FREE(s);
87 return status;
90 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
92 const char *ldap_expr;
93 const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
94 "serverName", "description", NULL };
96 /* For the moment only display all printers */
98 ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
99 "(objectCategory=printQueue))";
101 return ads_search(ads, res, ldap_expr, attrs);
105 modify a printer entry in the directory
107 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
108 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
110 return ads_gen_mod(ads, prt_dn, *mods);
114 add a printer to the directory
116 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
117 TALLOC_CTX *ctx, ADS_MODLIST *mods)
119 ads_mod_str(ctx, mods, "objectClass", "printQueue");
120 return ads_gen_add(ads, prt_dn, *mods);
124 map a REG_SZ to an ldap mod
126 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
127 struct regval_blob *value)
129 char *str_value = NULL;
130 size_t converted_size;
131 ADS_STATUS status;
133 if (regval_type(value) != REG_SZ)
134 return false;
136 if (regval_size(value) && *((smb_ucs2_t *) regval_data_p(value))) {
137 if (!pull_ucs2_talloc(ctx, &str_value,
138 (const smb_ucs2_t *) regval_data_p(value),
139 &converted_size))
141 return false;
143 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
144 return ADS_ERR_OK(status);
146 return true;
151 map a REG_DWORD to an ldap mod
153 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
154 struct regval_blob *value)
156 char *str_value = NULL;
157 ADS_STATUS status;
159 if (regval_type(value) != REG_DWORD)
160 return False;
161 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) regval_data_p(value)));
162 if (!str_value) {
163 return False;
165 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
166 return ADS_ERR_OK(status);
170 map a boolean REG_BINARY to an ldap mod
172 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
173 struct regval_blob *value)
175 char *str_value;
176 ADS_STATUS status;
178 if ((regval_type(value) != REG_BINARY) || (regval_size(value) != 1))
179 return False;
180 str_value = talloc_asprintf(ctx, "%s",
181 *(regval_data_p(value)) ? "TRUE" : "FALSE");
182 if (!str_value) {
183 return False;
185 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
186 return ADS_ERR_OK(status);
190 map a REG_MULTI_SZ to an ldap mod
192 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
193 struct regval_blob *value)
195 char **str_values = NULL;
196 size_t converted_size;
197 smb_ucs2_t *cur_str = (smb_ucs2_t *) regval_data_p(value);
198 uint32 size = 0, num_vals = 0, i=0;
199 ADS_STATUS status;
201 if (regval_type(value) != REG_MULTI_SZ)
202 return False;
204 while(cur_str && *cur_str && (size < regval_size(value))) {
205 size += 2 * (strlen_w(cur_str) + 1);
206 cur_str += strlen_w(cur_str) + 1;
207 num_vals++;
210 if (num_vals) {
211 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
212 if (!str_values) {
213 return False;
215 memset(str_values, '\0',
216 (num_vals + 1) * sizeof(char *));
218 cur_str = (smb_ucs2_t *) regval_data_p(value);
219 for (i=0; i < num_vals; i++) {
220 cur_str += pull_ucs2_talloc(ctx, &str_values[i],
221 cur_str, &converted_size) ?
222 converted_size : (size_t)-1;
225 status = ads_mod_strlist(ctx, mods, regval_name(value),
226 (const char **) str_values);
227 return ADS_ERR_OK(status);
229 return True;
232 struct valmap_to_ads {
233 const char *valname;
234 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, struct regval_blob *);
238 map a REG_SZ to an ldap mod
240 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
241 struct regval_blob *value)
243 const struct valmap_to_ads map[] = {
244 {SPOOL_REG_ASSETNUMBER, map_sz},
245 {SPOOL_REG_BYTESPERMINUTE, map_dword},
246 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
247 {SPOOL_REG_DESCRIPTION, map_sz},
248 {SPOOL_REG_DRIVERNAME, map_sz},
249 {SPOOL_REG_DRIVERVERSION, map_dword},
250 {SPOOL_REG_FLAGS, map_dword},
251 {SPOOL_REG_LOCATION, map_sz},
252 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
253 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
254 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
255 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
256 {SPOOL_REG_PORTNAME, map_multi_sz},
257 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
258 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
259 {SPOOL_REG_PRINTCOLLATE, map_bool},
260 {SPOOL_REG_PRINTCOLOR, map_bool},
261 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
262 {SPOOL_REG_PRINTENDTIME, map_dword},
263 {SPOOL_REG_PRINTFORMNAME, map_sz},
264 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
265 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
266 {SPOOL_REG_PRINTMACADDRESS, map_sz},
267 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
268 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
269 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
270 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
271 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
272 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
273 {SPOOL_REG_PRINTMEMORY, map_dword},
274 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
275 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
276 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
277 {SPOOL_REG_PRINTNOTIFY, map_sz},
278 {SPOOL_REG_PRINTNUMBERUP, map_dword},
279 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
280 {SPOOL_REG_PRINTOWNER, map_sz},
281 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
282 {SPOOL_REG_PRINTRATE, map_dword},
283 {SPOOL_REG_PRINTRATEUNIT, map_sz},
284 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
285 {SPOOL_REG_PRINTSHARENAME, map_sz},
286 {SPOOL_REG_PRINTSPOOLING, map_sz},
287 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
288 {SPOOL_REG_PRINTSTARTTIME, map_dword},
289 {SPOOL_REG_PRINTSTATUS, map_sz},
290 {SPOOL_REG_PRIORITY, map_dword},
291 {SPOOL_REG_SERVERNAME, map_sz},
292 {SPOOL_REG_SHORTSERVERNAME, map_sz},
293 {SPOOL_REG_UNCNAME, map_sz},
294 {SPOOL_REG_URL, map_sz},
295 {SPOOL_REG_VERSIONNUMBER, map_dword},
296 {NULL, NULL}
298 int i;
300 for (i=0; map[i].valname; i++) {
301 if (StrCaseCmp(map[i].valname, regval_name(value)) == 0) {
302 if (!map[i].fn(ctx, mods, value)) {
303 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value)));
304 } else {
305 DEBUG(7, ("Mapped value %s\n", regval_name(value)));
313 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
314 TALLOC_CTX *mem_ctx,
315 ADS_MODLIST *mods,
316 const char *printer)
318 WERROR result;
319 char *printername;
320 struct spoolss_PrinterEnumValues *info;
321 uint32_t count;
322 uint32 i;
323 struct policy_handle pol;
325 if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
326 DEBUG(3, ("Insufficient memory\n"));
327 return WERR_NOMEM;
330 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
331 printername,
332 SEC_FLAG_MAXIMUM_ALLOWED,
333 &pol);
334 if (!W_ERROR_IS_OK(result)) {
335 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
336 printername, win_errstr(result)));
337 SAFE_FREE(printername);
338 return result;
341 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
342 SPOOL_DSDRIVER_KEY,
344 &count,
345 &info);
347 if (!W_ERROR_IS_OK(result)) {
348 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
349 printername, win_errstr(result)));
350 } else {
351 /* Have the data we need now, so start building */
352 for (i=0; i < count; i++) {
353 struct regval_blob *v;
355 v = regval_compose(mem_ctx, info[i].value_name,
356 info[i].type,
357 info[i].data->data,
358 info[i].data->length);
359 if (v == NULL) {
360 return WERR_NOMEM;
363 map_regval_to_ads(mem_ctx, mods, v);
364 talloc_free(v);
368 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
369 SPOOL_DSSPOOLER_KEY,
371 &count,
372 &info);
373 if (!W_ERROR_IS_OK(result)) {
374 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
375 printername, win_errstr(result)));
376 } else {
377 for (i=0; i < count; i++) {
378 struct regval_blob *v;
380 v = regval_compose(mem_ctx, info[i].value_name,
381 info[i].type,
382 info[i].data->data,
383 info[i].data->length);
384 if (v == NULL) {
385 return WERR_NOMEM;
388 map_regval_to_ads(mem_ctx, mods, v);
389 talloc_free(v);
393 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
395 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
396 SAFE_FREE(printername);
398 return result;
401 #endif