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/>.
22 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
23 #include "rpc_client/cli_spoolss.h"
25 #include "registry/reg_objects.h"
26 #include "nt_printing.h"
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
,
37 const char *servername
)
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",
49 if (ads_count_replies(ads
, *res
) != 1) {
50 ads_msgfree(ads
, *res
);
52 return ADS_ERROR(LDAP_NO_SUCH_OBJECT
);
54 srv_dn
= ldap_get_dn(ads
->ldap
.ld
, *res
);
56 ads_msgfree(ads
, *res
);
58 return ADS_ERROR(LDAP_NO_MEMORY
);
60 srv_cn
= ldap_explode_dn(srv_dn
, 1);
63 ads_msgfree(ads
, *res
);
65 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX
);
67 ads_msgfree(ads
, *res
);
70 if (asprintf(&s
, "(cn=%s-%s)", srv_cn
[0], printer
) == -1) {
72 return ADS_ERROR(LDAP_NO_MEMORY
);
74 status
= ads_search(ads
, res
, s
, attrs
);
77 ldap_value_free(srv_cn
);
82 ADS_STATUS
ads_find_printers(ADS_STRUCT
*ads
, LDAPMessage
**res
)
84 const char *ldap_expr
;
85 const char *attrs
[] = { "objectClass", "printerName", "location", "driverName",
86 "serverName", "description", NULL
};
88 /* For the moment only display all printers */
90 ldap_expr
= "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
91 "(objectCategory=printQueue))";
93 return ads_search(ads
, res
, ldap_expr
, attrs
);
97 modify a printer entry in the directory
99 ADS_STATUS
ads_mod_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
100 TALLOC_CTX
*ctx
, const ADS_MODLIST
*mods
)
102 return ads_gen_mod(ads
, prt_dn
, *mods
);
106 add a printer to the directory
108 ADS_STATUS
ads_add_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
109 TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
)
111 ads_mod_str(ctx
, mods
, "objectClass", "printQueue");
112 return ads_gen_add(ads
, prt_dn
, *mods
);
116 map a REG_SZ to an ldap mod
118 static bool map_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
119 struct regval_blob
*value
)
121 char *str_value
= NULL
;
122 size_t converted_size
;
125 if (regval_type(value
) != REG_SZ
)
128 if (regval_size(value
) && *((smb_ucs2_t
*) regval_data_p(value
))) {
129 if (!pull_ucs2_talloc(ctx
, &str_value
,
130 (const smb_ucs2_t
*) regval_data_p(value
),
135 status
= ads_mod_str(ctx
, mods
, regval_name(value
), str_value
);
136 return ADS_ERR_OK(status
);
143 map a REG_DWORD to an ldap mod
145 static bool map_dword(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
146 struct regval_blob
*value
)
148 char *str_value
= NULL
;
151 if (regval_type(value
) != REG_DWORD
)
153 str_value
= talloc_asprintf(ctx
, "%d", *((uint32
*) regval_data_p(value
)));
157 status
= ads_mod_str(ctx
, mods
, regval_name(value
), str_value
);
158 return ADS_ERR_OK(status
);
162 map a boolean REG_BINARY to an ldap mod
164 static bool map_bool(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
165 struct regval_blob
*value
)
170 if ((regval_type(value
) != REG_BINARY
) || (regval_size(value
) != 1))
172 str_value
= talloc_asprintf(ctx
, "%s",
173 *(regval_data_p(value
)) ? "TRUE" : "FALSE");
177 status
= ads_mod_str(ctx
, mods
, regval_name(value
), str_value
);
178 return ADS_ERR_OK(status
);
182 map a REG_MULTI_SZ to an ldap mod
184 static bool map_multi_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
185 struct regval_blob
*value
)
187 char **str_values
= NULL
;
188 size_t converted_size
;
189 smb_ucs2_t
*cur_str
= (smb_ucs2_t
*) regval_data_p(value
);
190 uint32 size
= 0, num_vals
= 0, i
=0;
193 if (regval_type(value
) != REG_MULTI_SZ
)
196 while(cur_str
&& *cur_str
&& (size
< regval_size(value
))) {
197 size
+= 2 * (strlen_w(cur_str
) + 1);
198 cur_str
+= strlen_w(cur_str
) + 1;
203 str_values
= TALLOC_ARRAY(ctx
, char *, num_vals
+ 1);
207 memset(str_values
, '\0',
208 (num_vals
+ 1) * sizeof(char *));
210 cur_str
= (smb_ucs2_t
*) regval_data_p(value
);
211 for (i
=0; i
< num_vals
; i
++) {
212 cur_str
+= pull_ucs2_talloc(ctx
, &str_values
[i
],
213 cur_str
, &converted_size
) ?
214 converted_size
: (size_t)-1;
217 status
= ads_mod_strlist(ctx
, mods
, regval_name(value
),
218 (const char **) str_values
);
219 return ADS_ERR_OK(status
);
224 struct valmap_to_ads
{
226 bool (*fn
)(TALLOC_CTX
*, ADS_MODLIST
*, struct regval_blob
*);
230 map a REG_SZ to an ldap mod
232 static void map_regval_to_ads(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
233 struct regval_blob
*value
)
235 const struct valmap_to_ads map
[] = {
236 {SPOOL_REG_ASSETNUMBER
, map_sz
},
237 {SPOOL_REG_BYTESPERMINUTE
, map_dword
},
238 {SPOOL_REG_DEFAULTPRIORITY
, map_dword
},
239 {SPOOL_REG_DESCRIPTION
, map_sz
},
240 {SPOOL_REG_DRIVERNAME
, map_sz
},
241 {SPOOL_REG_DRIVERVERSION
, map_dword
},
242 {SPOOL_REG_FLAGS
, map_dword
},
243 {SPOOL_REG_LOCATION
, map_sz
},
244 {SPOOL_REG_OPERATINGSYSTEM
, map_sz
},
245 {SPOOL_REG_OPERATINGSYSTEMHOTFIX
, map_sz
},
246 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK
, map_sz
},
247 {SPOOL_REG_OPERATINGSYSTEMVERSION
, map_sz
},
248 {SPOOL_REG_PORTNAME
, map_multi_sz
},
249 {SPOOL_REG_PRINTATTRIBUTES
, map_dword
},
250 {SPOOL_REG_PRINTBINNAMES
, map_multi_sz
},
251 {SPOOL_REG_PRINTCOLLATE
, map_bool
},
252 {SPOOL_REG_PRINTCOLOR
, map_bool
},
253 {SPOOL_REG_PRINTDUPLEXSUPPORTED
, map_bool
},
254 {SPOOL_REG_PRINTENDTIME
, map_dword
},
255 {SPOOL_REG_PRINTFORMNAME
, map_sz
},
256 {SPOOL_REG_PRINTKEEPPRINTEDJOBS
, map_bool
},
257 {SPOOL_REG_PRINTLANGUAGE
, map_multi_sz
},
258 {SPOOL_REG_PRINTMACADDRESS
, map_sz
},
259 {SPOOL_REG_PRINTMAXCOPIES
, map_sz
},
260 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED
, map_dword
},
261 {SPOOL_REG_PRINTMAXXEXTENT
, map_dword
},
262 {SPOOL_REG_PRINTMAXYEXTENT
, map_dword
},
263 {SPOOL_REG_PRINTMEDIAREADY
, map_multi_sz
},
264 {SPOOL_REG_PRINTMEDIASUPPORTED
, map_multi_sz
},
265 {SPOOL_REG_PRINTMEMORY
, map_dword
},
266 {SPOOL_REG_PRINTMINXEXTENT
, map_dword
},
267 {SPOOL_REG_PRINTMINYEXTENT
, map_dword
},
268 {SPOOL_REG_PRINTNETWORKADDRESS
, map_sz
},
269 {SPOOL_REG_PRINTNOTIFY
, map_sz
},
270 {SPOOL_REG_PRINTNUMBERUP
, map_dword
},
271 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED
, map_multi_sz
},
272 {SPOOL_REG_PRINTOWNER
, map_sz
},
273 {SPOOL_REG_PRINTPAGESPERMINUTE
, map_dword
},
274 {SPOOL_REG_PRINTRATE
, map_dword
},
275 {SPOOL_REG_PRINTRATEUNIT
, map_sz
},
276 {SPOOL_REG_PRINTSEPARATORFILE
, map_sz
},
277 {SPOOL_REG_PRINTSHARENAME
, map_sz
},
278 {SPOOL_REG_PRINTSPOOLING
, map_sz
},
279 {SPOOL_REG_PRINTSTAPLINGSUPPORTED
, map_bool
},
280 {SPOOL_REG_PRINTSTARTTIME
, map_dword
},
281 {SPOOL_REG_PRINTSTATUS
, map_sz
},
282 {SPOOL_REG_PRIORITY
, map_dword
},
283 {SPOOL_REG_SERVERNAME
, map_sz
},
284 {SPOOL_REG_SHORTSERVERNAME
, map_sz
},
285 {SPOOL_REG_UNCNAME
, map_sz
},
286 {SPOOL_REG_URL
, map_sz
},
287 {SPOOL_REG_VERSIONNUMBER
, map_dword
},
292 for (i
=0; map
[i
].valname
; i
++) {
293 if (StrCaseCmp(map
[i
].valname
, regval_name(value
)) == 0) {
294 if (!map
[i
].fn(ctx
, mods
, value
)) {
295 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value
)));
297 DEBUG(7, ("Mapped value %s\n", regval_name(value
)));
305 WERROR
get_remote_printer_publishing_data(struct rpc_pipe_client
*cli
,
310 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
313 struct spoolss_PrinterEnumValues
*info
;
316 struct policy_handle pol
;
319 if ((asprintf(&printername
, "%s\\%s", cli
->srv_name_slash
, printer
) == -1)) {
320 DEBUG(3, ("Insufficient memory\n"));
324 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
326 SEC_FLAG_MAXIMUM_ALLOWED
,
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
);
335 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
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
)));
345 /* Have the data we need now, so start building */
346 for (i
=0; i
< count
; i
++) {
347 struct regval_blob
*v
;
349 v
= regval_compose(mem_ctx
, info
[i
].value_name
,
352 info
[i
].data
->length
);
357 map_regval_to_ads(mem_ctx
, mods
, v
);
362 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
367 if (!W_ERROR_IS_OK(result
)) {
368 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
369 printername
, win_errstr(result
)));
371 for (i
=0; i
< count
; i
++) {
372 struct regval_blob
*v
;
374 v
= regval_compose(mem_ctx
, info
[i
].value_name
,
377 info
[i
].data
->length
);
382 map_regval_to_ads(mem_ctx
, mods
, v
);
387 ads_mod_str(mem_ctx
, mods
, SPOOL_REG_PRINTERNAME
, printer
);
389 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &werr
);
390 SAFE_FREE(printername
);