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 "rpc_client/rpc_client.h"
23 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
24 #include "rpc_client/cli_spoolss.h"
26 #include "libcli/registry/util_reg.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 const char *name
, struct registry_value
*value
)
121 const char *str_value
= NULL
;
124 if (value
->type
!= REG_SZ
)
127 if (value
->data
.length
&& value
->data
.data
) {
128 if (!pull_reg_sz(ctx
, &value
->data
, &str_value
)) {
131 status
= ads_mod_str(ctx
, mods
, name
, str_value
);
132 return ADS_ERR_OK(status
);
138 map a REG_DWORD to an ldap mod
140 static bool map_dword(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
141 const char *name
, struct registry_value
*value
)
143 char *str_value
= NULL
;
146 if (value
->type
!= REG_DWORD
) {
149 if (value
->data
.length
!= sizeof(uint32
)) {
152 str_value
= talloc_asprintf(ctx
, "%d", IVAL(value
->data
.data
, 0));
156 status
= ads_mod_str(ctx
, mods
, name
, str_value
);
157 return ADS_ERR_OK(status
);
161 map a boolean REG_BINARY to an ldap mod
163 static bool map_bool(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
164 const char *name
, struct registry_value
*value
)
166 const char *str_value
;
169 if (value
->type
!= REG_BINARY
) {
172 if (value
->data
.length
!= 1) {
176 str_value
= *value
->data
.data
? "TRUE" : "FALSE";
178 status
= ads_mod_str(ctx
, mods
, name
, str_value
);
179 return ADS_ERR_OK(status
);
183 map a REG_MULTI_SZ to an ldap mod
185 static bool map_multi_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
186 const char *name
, struct registry_value
*value
)
188 const char **str_values
= NULL
;
191 if (value
->type
!= REG_MULTI_SZ
) {
195 if (value
->data
.length
&& value
->data
.data
) {
196 if (!pull_reg_multi_sz(ctx
, &value
->data
, &str_values
)) {
199 status
= ads_mod_strlist(ctx
, mods
, name
, str_values
);
200 return ADS_ERR_OK(status
);
205 struct valmap_to_ads
{
207 bool (*fn
)(TALLOC_CTX
*, ADS_MODLIST
*, const char *, struct registry_value
*);
211 map a REG_SZ to an ldap mod
213 static void map_regval_to_ads(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
214 const char *name
, struct registry_value
*value
)
216 const struct valmap_to_ads map
[] = {
217 {SPOOL_REG_ASSETNUMBER
, map_sz
},
218 {SPOOL_REG_BYTESPERMINUTE
, map_dword
},
219 {SPOOL_REG_DEFAULTPRIORITY
, map_dword
},
220 {SPOOL_REG_DESCRIPTION
, map_sz
},
221 {SPOOL_REG_DRIVERNAME
, map_sz
},
222 {SPOOL_REG_DRIVERVERSION
, map_dword
},
223 {SPOOL_REG_FLAGS
, map_dword
},
224 {SPOOL_REG_LOCATION
, map_sz
},
225 {SPOOL_REG_OPERATINGSYSTEM
, map_sz
},
226 {SPOOL_REG_OPERATINGSYSTEMHOTFIX
, map_sz
},
227 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK
, map_sz
},
228 {SPOOL_REG_OPERATINGSYSTEMVERSION
, map_sz
},
229 {SPOOL_REG_PORTNAME
, map_multi_sz
},
230 {SPOOL_REG_PRINTATTRIBUTES
, map_dword
},
231 {SPOOL_REG_PRINTBINNAMES
, map_multi_sz
},
232 {SPOOL_REG_PRINTCOLLATE
, map_bool
},
233 {SPOOL_REG_PRINTCOLOR
, map_bool
},
234 {SPOOL_REG_PRINTDUPLEXSUPPORTED
, map_bool
},
235 {SPOOL_REG_PRINTENDTIME
, map_dword
},
236 {SPOOL_REG_PRINTFORMNAME
, map_sz
},
237 {SPOOL_REG_PRINTKEEPPRINTEDJOBS
, map_bool
},
238 {SPOOL_REG_PRINTLANGUAGE
, map_multi_sz
},
239 {SPOOL_REG_PRINTMACADDRESS
, map_sz
},
240 {SPOOL_REG_PRINTMAXCOPIES
, map_sz
},
241 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED
, map_dword
},
242 {SPOOL_REG_PRINTMAXXEXTENT
, map_dword
},
243 {SPOOL_REG_PRINTMAXYEXTENT
, map_dword
},
244 {SPOOL_REG_PRINTMEDIAREADY
, map_multi_sz
},
245 {SPOOL_REG_PRINTMEDIASUPPORTED
, map_multi_sz
},
246 {SPOOL_REG_PRINTMEMORY
, map_dword
},
247 {SPOOL_REG_PRINTMINXEXTENT
, map_dword
},
248 {SPOOL_REG_PRINTMINYEXTENT
, map_dword
},
249 {SPOOL_REG_PRINTNETWORKADDRESS
, map_sz
},
250 {SPOOL_REG_PRINTNOTIFY
, map_sz
},
251 {SPOOL_REG_PRINTNUMBERUP
, map_dword
},
252 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED
, map_multi_sz
},
253 {SPOOL_REG_PRINTOWNER
, map_sz
},
254 {SPOOL_REG_PRINTPAGESPERMINUTE
, map_dword
},
255 {SPOOL_REG_PRINTRATE
, map_dword
},
256 {SPOOL_REG_PRINTRATEUNIT
, map_sz
},
257 {SPOOL_REG_PRINTSEPARATORFILE
, map_sz
},
258 {SPOOL_REG_PRINTSHARENAME
, map_sz
},
259 {SPOOL_REG_PRINTSPOOLING
, map_sz
},
260 {SPOOL_REG_PRINTSTAPLINGSUPPORTED
, map_bool
},
261 {SPOOL_REG_PRINTSTARTTIME
, map_dword
},
262 {SPOOL_REG_PRINTSTATUS
, map_sz
},
263 {SPOOL_REG_PRIORITY
, map_dword
},
264 {SPOOL_REG_SERVERNAME
, map_sz
},
265 {SPOOL_REG_SHORTSERVERNAME
, map_sz
},
266 {SPOOL_REG_UNCNAME
, map_sz
},
267 {SPOOL_REG_URL
, map_sz
},
268 {SPOOL_REG_VERSIONNUMBER
, map_dword
},
273 for (i
=0; map
[i
].valname
; i
++) {
274 if (strcasecmp_m(map
[i
].valname
, name
) == 0) {
275 if (!map
[i
].fn(ctx
, mods
, name
, value
)) {
276 DEBUG(5, ("Add of value %s to modlist failed\n", name
));
278 DEBUG(7, ("Mapped value %s\n", name
));
285 WERROR
get_remote_printer_publishing_data(struct rpc_pipe_client
*cli
,
290 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
293 struct spoolss_PrinterEnumValues
*info
;
296 struct policy_handle pol
;
299 if ((asprintf(&printername
, "%s\\%s", cli
->srv_name_slash
, printer
) == -1)) {
300 DEBUG(3, ("Insufficient memory\n"));
304 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
306 SEC_FLAG_MAXIMUM_ALLOWED
,
308 if (!W_ERROR_IS_OK(result
)) {
309 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
310 printername
, win_errstr(result
)));
311 SAFE_FREE(printername
);
315 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
321 if (!W_ERROR_IS_OK(result
)) {
322 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
323 printername
, win_errstr(result
)));
325 /* Have the data we need now, so start building */
326 for (i
=0; i
< count
; i
++) {
327 struct registry_value v
;
328 v
.type
= info
[i
].type
;
329 v
.data
= *info
[i
].data
;
331 map_regval_to_ads(mem_ctx
, mods
, info
[i
].value_name
, &v
);
335 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
340 if (!W_ERROR_IS_OK(result
)) {
341 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
342 printername
, win_errstr(result
)));
344 for (i
=0; i
< count
; i
++) {
345 struct registry_value v
;
346 v
.type
= info
[i
].type
;
347 v
.data
= *info
[i
].data
;
349 map_regval_to_ads(mem_ctx
, mods
, info
[i
].value_name
, &v
);
353 ads_mod_str(mem_ctx
, mods
, SPOOL_REG_PRINTERNAME
, printer
);
355 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &werr
);
356 SAFE_FREE(printername
);