s4:regshell - don't use negative exit codes
[Samba/ekacnet.git] / source3 / libads / ldap_printer.c
blob0aa21badf4e3c5df98dfecfe6460a1e5cb4f6a97
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"
24 #include "registry/reg_objects.h"
26 #ifdef HAVE_ADS
29 find a printer given the name and the hostname
30 Note that results "res" may be allocated on return so that the
31 results can be used. It should be freed using ads_msgfree.
33 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
34 const char *printer,
35 const char *servername)
37 ADS_STATUS status;
38 char *srv_dn, **srv_cn, *s = NULL;
39 const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
41 status = ads_find_machine_acct(ads, res, servername);
42 if (!ADS_ERR_OK(status)) {
43 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
44 servername));
45 return status;
47 if (ads_count_replies(ads, *res) != 1) {
48 if (res) {
49 ads_msgfree(ads, *res);
50 *res = NULL;
52 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
54 srv_dn = ldap_get_dn(ads->ldap.ld, *res);
55 if (srv_dn == NULL) {
56 if (res) {
57 ads_msgfree(ads, *res);
58 *res = NULL;
60 return ADS_ERROR(LDAP_NO_MEMORY);
62 srv_cn = ldap_explode_dn(srv_dn, 1);
63 if (srv_cn == NULL) {
64 ldap_memfree(srv_dn);
65 if (res) {
66 ads_msgfree(ads, *res);
67 *res = NULL;
69 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
71 if (res) {
72 ads_msgfree(ads, *res);
73 *res = NULL;
76 if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
77 ldap_memfree(srv_dn);
78 return ADS_ERROR(LDAP_NO_MEMORY);
80 status = ads_search(ads, res, s, attrs);
82 ldap_memfree(srv_dn);
83 ldap_value_free(srv_cn);
84 SAFE_FREE(s);
85 return status;
88 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
90 const char *ldap_expr;
91 const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
92 "serverName", "description", NULL };
94 /* For the moment only display all printers */
96 ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
97 "(objectCategory=printQueue))";
99 return ads_search(ads, res, ldap_expr, attrs);
103 modify a printer entry in the directory
105 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
106 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
108 return ads_gen_mod(ads, prt_dn, *mods);
112 add a printer to the directory
114 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
115 TALLOC_CTX *ctx, ADS_MODLIST *mods)
117 ads_mod_str(ctx, mods, "objectClass", "printQueue");
118 return ads_gen_add(ads, prt_dn, *mods);
122 map a REG_SZ to an ldap mod
124 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
125 struct regval_blob *value)
127 char *str_value = NULL;
128 size_t converted_size;
129 ADS_STATUS status;
131 if (regval_type(value) != REG_SZ)
132 return false;
134 if (regval_size(value) && *((smb_ucs2_t *) regval_data_p(value))) {
135 if (!pull_ucs2_talloc(ctx, &str_value,
136 (const smb_ucs2_t *) regval_data_p(value),
137 &converted_size))
139 return false;
141 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
142 return ADS_ERR_OK(status);
144 return true;
149 map a REG_DWORD to an ldap mod
151 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
152 struct regval_blob *value)
154 char *str_value = NULL;
155 ADS_STATUS status;
157 if (regval_type(value) != REG_DWORD)
158 return False;
159 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) regval_data_p(value)));
160 if (!str_value) {
161 return False;
163 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
164 return ADS_ERR_OK(status);
168 map a boolean REG_BINARY to an ldap mod
170 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
171 struct regval_blob *value)
173 char *str_value;
174 ADS_STATUS status;
176 if ((regval_type(value) != REG_BINARY) || (regval_size(value) != 1))
177 return False;
178 str_value = talloc_asprintf(ctx, "%s",
179 *(regval_data_p(value)) ? "TRUE" : "FALSE");
180 if (!str_value) {
181 return False;
183 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
184 return ADS_ERR_OK(status);
188 map a REG_MULTI_SZ to an ldap mod
190 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
191 struct regval_blob *value)
193 char **str_values = NULL;
194 size_t converted_size;
195 smb_ucs2_t *cur_str = (smb_ucs2_t *) regval_data_p(value);
196 uint32 size = 0, num_vals = 0, i=0;
197 ADS_STATUS status;
199 if (regval_type(value) != REG_MULTI_SZ)
200 return False;
202 while(cur_str && *cur_str && (size < regval_size(value))) {
203 size += 2 * (strlen_w(cur_str) + 1);
204 cur_str += strlen_w(cur_str) + 1;
205 num_vals++;
208 if (num_vals) {
209 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
210 if (!str_values) {
211 return False;
213 memset(str_values, '\0',
214 (num_vals + 1) * sizeof(char *));
216 cur_str = (smb_ucs2_t *) regval_data_p(value);
217 for (i=0; i < num_vals; i++) {
218 cur_str += pull_ucs2_talloc(ctx, &str_values[i],
219 cur_str, &converted_size) ?
220 converted_size : (size_t)-1;
223 status = ads_mod_strlist(ctx, mods, regval_name(value),
224 (const char **) str_values);
225 return ADS_ERR_OK(status);
227 return True;
230 struct valmap_to_ads {
231 const char *valname;
232 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, struct regval_blob *);
236 map a REG_SZ to an ldap mod
238 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
239 struct regval_blob *value)
241 const struct valmap_to_ads map[] = {
242 {SPOOL_REG_ASSETNUMBER, map_sz},
243 {SPOOL_REG_BYTESPERMINUTE, map_dword},
244 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
245 {SPOOL_REG_DESCRIPTION, map_sz},
246 {SPOOL_REG_DRIVERNAME, map_sz},
247 {SPOOL_REG_DRIVERVERSION, map_dword},
248 {SPOOL_REG_FLAGS, map_dword},
249 {SPOOL_REG_LOCATION, map_sz},
250 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
251 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
252 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
253 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
254 {SPOOL_REG_PORTNAME, map_multi_sz},
255 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
256 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
257 {SPOOL_REG_PRINTCOLLATE, map_bool},
258 {SPOOL_REG_PRINTCOLOR, map_bool},
259 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
260 {SPOOL_REG_PRINTENDTIME, map_dword},
261 {SPOOL_REG_PRINTFORMNAME, map_sz},
262 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
263 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
264 {SPOOL_REG_PRINTMACADDRESS, map_sz},
265 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
266 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
267 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
268 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
269 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
270 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
271 {SPOOL_REG_PRINTMEMORY, map_dword},
272 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
273 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
274 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
275 {SPOOL_REG_PRINTNOTIFY, map_sz},
276 {SPOOL_REG_PRINTNUMBERUP, map_dword},
277 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
278 {SPOOL_REG_PRINTOWNER, map_sz},
279 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
280 {SPOOL_REG_PRINTRATE, map_dword},
281 {SPOOL_REG_PRINTRATEUNIT, map_sz},
282 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
283 {SPOOL_REG_PRINTSHARENAME, map_sz},
284 {SPOOL_REG_PRINTSPOOLING, map_sz},
285 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
286 {SPOOL_REG_PRINTSTARTTIME, map_dword},
287 {SPOOL_REG_PRINTSTATUS, map_sz},
288 {SPOOL_REG_PRIORITY, map_dword},
289 {SPOOL_REG_SERVERNAME, map_sz},
290 {SPOOL_REG_SHORTSERVERNAME, map_sz},
291 {SPOOL_REG_UNCNAME, map_sz},
292 {SPOOL_REG_URL, map_sz},
293 {SPOOL_REG_VERSIONNUMBER, map_dword},
294 {NULL, NULL}
296 int i;
298 for (i=0; map[i].valname; i++) {
299 if (StrCaseCmp(map[i].valname, regval_name(value)) == 0) {
300 if (!map[i].fn(ctx, mods, value)) {
301 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value)));
302 } else {
303 DEBUG(7, ("Mapped value %s\n", regval_name(value)));
311 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
312 TALLOC_CTX *mem_ctx,
313 ADS_MODLIST *mods,
314 const char *printer)
316 WERROR result;
317 char *printername;
318 struct spoolss_PrinterEnumValues *info;
319 uint32_t count;
320 uint32 i;
321 struct policy_handle pol;
323 if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
324 DEBUG(3, ("Insufficient memory\n"));
325 return WERR_NOMEM;
328 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
329 printername,
330 SEC_FLAG_MAXIMUM_ALLOWED,
331 &pol);
332 if (!W_ERROR_IS_OK(result)) {
333 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
334 printername, win_errstr(result)));
335 SAFE_FREE(printername);
336 return result;
339 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
340 SPOOL_DSDRIVER_KEY,
342 &count,
343 &info);
345 if (!W_ERROR_IS_OK(result)) {
346 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
347 printername, win_errstr(result)));
348 } else {
349 /* Have the data we need now, so start building */
350 for (i=0; i < count; i++) {
351 struct regval_blob *v;
353 v = regval_compose(mem_ctx, info[i].value_name,
354 info[i].type,
355 info[i].data->data,
356 info[i].data->length);
357 if (v == NULL) {
358 return WERR_NOMEM;
361 map_regval_to_ads(mem_ctx, mods, v);
362 talloc_free(v);
366 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
367 SPOOL_DSSPOOLER_KEY,
369 &count,
370 &info);
371 if (!W_ERROR_IS_OK(result)) {
372 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
373 printername, win_errstr(result)));
374 } else {
375 for (i=0; i < count; i++) {
376 struct regval_blob *v;
378 v = regval_compose(mem_ctx, info[i].value_name,
379 info[i].type,
380 info[i].data->data,
381 info[i].data->length);
382 if (v == NULL) {
383 return WERR_NOMEM;
386 map_regval_to_ads(mem_ctx, mods, v);
387 talloc_free(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 struct regval_ctr *ctr = data->keys[key].values;
407 for (val=0; val < regval_ctr_numvals(ctr); val++)
408 map_regval_to_ads(mem_ctx, mods, regval_ctr_specific_value(ctr, val));
410 return True;
413 #endif