s4:librpc/rpc: make dcerpc_request_recv() static
[Samba.git] / source3 / libads / ldap_printer.c
blobe4bfbcead7d43083c8d6a4b509ff22a53e783440
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/ndr_spoolss_c.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 struct dcerpc_binding_handle *b = cli->binding_handle;
319 WERROR result;
320 char *printername;
321 struct spoolss_PrinterEnumValues *info;
322 uint32_t count;
323 uint32 i;
324 struct policy_handle pol;
325 WERROR werr;
327 if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
328 DEBUG(3, ("Insufficient memory\n"));
329 return WERR_NOMEM;
332 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
333 printername,
334 SEC_FLAG_MAXIMUM_ALLOWED,
335 &pol);
336 if (!W_ERROR_IS_OK(result)) {
337 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
338 printername, win_errstr(result)));
339 SAFE_FREE(printername);
340 return result;
343 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
344 SPOOL_DSDRIVER_KEY,
346 &count,
347 &info);
349 if (!W_ERROR_IS_OK(result)) {
350 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
351 printername, win_errstr(result)));
352 } else {
353 /* Have the data we need now, so start building */
354 for (i=0; i < count; i++) {
355 struct regval_blob *v;
357 v = regval_compose(mem_ctx, info[i].value_name,
358 info[i].type,
359 info[i].data->data,
360 info[i].data->length);
361 if (v == NULL) {
362 return WERR_NOMEM;
365 map_regval_to_ads(mem_ctx, mods, v);
366 talloc_free(v);
370 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
371 SPOOL_DSSPOOLER_KEY,
373 &count,
374 &info);
375 if (!W_ERROR_IS_OK(result)) {
376 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
377 printername, win_errstr(result)));
378 } else {
379 for (i=0; i < count; i++) {
380 struct regval_blob *v;
382 v = regval_compose(mem_ctx, info[i].value_name,
383 info[i].type,
384 info[i].data->data,
385 info[i].data->length);
386 if (v == NULL) {
387 return WERR_NOMEM;
390 map_regval_to_ads(mem_ctx, mods, v);
391 talloc_free(v);
395 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
397 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &pol, &werr);
398 SAFE_FREE(printername);
400 return result;
403 #endif