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"
25 #include "registry/reg_objects.h"
30 find a printer given the name and the hostname
31 Note that results "res" may be allocated on return so that the
32 results can be used. It should be freed using ads_msgfree.
34 ADS_STATUS
ads_find_printer_on_server(ADS_STRUCT
*ads
, LDAPMessage
**res
,
36 const char *servername
)
39 char *srv_dn
, **srv_cn
, *s
= NULL
;
40 const char *attrs
[] = {"*", "nTSecurityDescriptor", NULL
};
42 status
= ads_find_machine_acct(ads
, res
, servername
);
43 if (!ADS_ERR_OK(status
)) {
44 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
48 if (ads_count_replies(ads
, *res
) != 1) {
49 ads_msgfree(ads
, *res
);
51 return ADS_ERROR(LDAP_NO_SUCH_OBJECT
);
53 srv_dn
= ldap_get_dn(ads
->ldap
.ld
, *res
);
55 ads_msgfree(ads
, *res
);
57 return ADS_ERROR(LDAP_NO_MEMORY
);
59 srv_cn
= ldap_explode_dn(srv_dn
, 1);
62 ads_msgfree(ads
, *res
);
64 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX
);
66 ads_msgfree(ads
, *res
);
69 if (asprintf(&s
, "(cn=%s-%s)", srv_cn
[0], printer
) == -1) {
71 return ADS_ERROR(LDAP_NO_MEMORY
);
73 status
= ads_search(ads
, res
, s
, attrs
);
76 ldap_value_free(srv_cn
);
81 ADS_STATUS
ads_find_printers(ADS_STRUCT
*ads
, LDAPMessage
**res
)
83 const char *ldap_expr
;
84 const char *attrs
[] = { "objectClass", "printerName", "location", "driverName",
85 "serverName", "description", NULL
};
87 /* For the moment only display all printers */
89 ldap_expr
= "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
90 "(objectCategory=printQueue))";
92 return ads_search(ads
, res
, ldap_expr
, attrs
);
96 modify a printer entry in the directory
98 ADS_STATUS
ads_mod_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
99 TALLOC_CTX
*ctx
, const ADS_MODLIST
*mods
)
101 return ads_gen_mod(ads
, prt_dn
, *mods
);
105 add a printer to the directory
107 ADS_STATUS
ads_add_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
108 TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
)
110 ads_mod_str(ctx
, mods
, "objectClass", "printQueue");
111 return ads_gen_add(ads
, prt_dn
, *mods
);
115 map a REG_SZ to an ldap mod
117 static bool map_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
118 struct regval_blob
*value
)
120 char *str_value
= NULL
;
121 size_t converted_size
;
124 if (regval_type(value
) != REG_SZ
)
127 if (regval_size(value
) && *((smb_ucs2_t
*) regval_data_p(value
))) {
128 if (!pull_ucs2_talloc(ctx
, &str_value
,
129 (const smb_ucs2_t
*) regval_data_p(value
),
134 status
= ads_mod_str(ctx
, mods
, regval_name(value
), str_value
);
135 return ADS_ERR_OK(status
);
142 map a REG_DWORD to an ldap mod
144 static bool map_dword(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
145 struct regval_blob
*value
)
147 char *str_value
= NULL
;
150 if (regval_type(value
) != REG_DWORD
)
152 str_value
= talloc_asprintf(ctx
, "%d", *((uint32
*) regval_data_p(value
)));
156 status
= ads_mod_str(ctx
, mods
, regval_name(value
), 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 struct regval_blob
*value
)
169 if ((regval_type(value
) != REG_BINARY
) || (regval_size(value
) != 1))
171 str_value
= talloc_asprintf(ctx
, "%s",
172 *(regval_data_p(value
)) ? "TRUE" : "FALSE");
176 status
= ads_mod_str(ctx
, mods
, regval_name(value
), str_value
);
177 return ADS_ERR_OK(status
);
181 map a REG_MULTI_SZ to an ldap mod
183 static bool map_multi_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
184 struct regval_blob
*value
)
186 char **str_values
= NULL
;
187 size_t converted_size
;
188 smb_ucs2_t
*cur_str
= (smb_ucs2_t
*) regval_data_p(value
);
189 uint32 size
= 0, num_vals
= 0, i
=0;
192 if (regval_type(value
) != REG_MULTI_SZ
)
195 while(cur_str
&& *cur_str
&& (size
< regval_size(value
))) {
196 size
+= 2 * (strlen_w(cur_str
) + 1);
197 cur_str
+= strlen_w(cur_str
) + 1;
202 str_values
= TALLOC_ARRAY(ctx
, char *, num_vals
+ 1);
206 memset(str_values
, '\0',
207 (num_vals
+ 1) * sizeof(char *));
209 cur_str
= (smb_ucs2_t
*) regval_data_p(value
);
210 for (i
=0; i
< num_vals
; i
++) {
211 cur_str
+= pull_ucs2_talloc(ctx
, &str_values
[i
],
212 cur_str
, &converted_size
) ?
213 converted_size
: (size_t)-1;
216 status
= ads_mod_strlist(ctx
, mods
, regval_name(value
),
217 (const char **) str_values
);
218 return ADS_ERR_OK(status
);
223 struct valmap_to_ads
{
225 bool (*fn
)(TALLOC_CTX
*, ADS_MODLIST
*, struct regval_blob
*);
229 map a REG_SZ to an ldap mod
231 static void map_regval_to_ads(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
232 struct regval_blob
*value
)
234 const struct valmap_to_ads map
[] = {
235 {SPOOL_REG_ASSETNUMBER
, map_sz
},
236 {SPOOL_REG_BYTESPERMINUTE
, map_dword
},
237 {SPOOL_REG_DEFAULTPRIORITY
, map_dword
},
238 {SPOOL_REG_DESCRIPTION
, map_sz
},
239 {SPOOL_REG_DRIVERNAME
, map_sz
},
240 {SPOOL_REG_DRIVERVERSION
, map_dword
},
241 {SPOOL_REG_FLAGS
, map_dword
},
242 {SPOOL_REG_LOCATION
, map_sz
},
243 {SPOOL_REG_OPERATINGSYSTEM
, map_sz
},
244 {SPOOL_REG_OPERATINGSYSTEMHOTFIX
, map_sz
},
245 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK
, map_sz
},
246 {SPOOL_REG_OPERATINGSYSTEMVERSION
, map_sz
},
247 {SPOOL_REG_PORTNAME
, map_multi_sz
},
248 {SPOOL_REG_PRINTATTRIBUTES
, map_dword
},
249 {SPOOL_REG_PRINTBINNAMES
, map_multi_sz
},
250 {SPOOL_REG_PRINTCOLLATE
, map_bool
},
251 {SPOOL_REG_PRINTCOLOR
, map_bool
},
252 {SPOOL_REG_PRINTDUPLEXSUPPORTED
, map_bool
},
253 {SPOOL_REG_PRINTENDTIME
, map_dword
},
254 {SPOOL_REG_PRINTFORMNAME
, map_sz
},
255 {SPOOL_REG_PRINTKEEPPRINTEDJOBS
, map_bool
},
256 {SPOOL_REG_PRINTLANGUAGE
, map_multi_sz
},
257 {SPOOL_REG_PRINTMACADDRESS
, map_sz
},
258 {SPOOL_REG_PRINTMAXCOPIES
, map_sz
},
259 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED
, map_dword
},
260 {SPOOL_REG_PRINTMAXXEXTENT
, map_dword
},
261 {SPOOL_REG_PRINTMAXYEXTENT
, map_dword
},
262 {SPOOL_REG_PRINTMEDIAREADY
, map_multi_sz
},
263 {SPOOL_REG_PRINTMEDIASUPPORTED
, map_multi_sz
},
264 {SPOOL_REG_PRINTMEMORY
, map_dword
},
265 {SPOOL_REG_PRINTMINXEXTENT
, map_dword
},
266 {SPOOL_REG_PRINTMINYEXTENT
, map_dword
},
267 {SPOOL_REG_PRINTNETWORKADDRESS
, map_sz
},
268 {SPOOL_REG_PRINTNOTIFY
, map_sz
},
269 {SPOOL_REG_PRINTNUMBERUP
, map_dword
},
270 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED
, map_multi_sz
},
271 {SPOOL_REG_PRINTOWNER
, map_sz
},
272 {SPOOL_REG_PRINTPAGESPERMINUTE
, map_dword
},
273 {SPOOL_REG_PRINTRATE
, map_dword
},
274 {SPOOL_REG_PRINTRATEUNIT
, map_sz
},
275 {SPOOL_REG_PRINTSEPARATORFILE
, map_sz
},
276 {SPOOL_REG_PRINTSHARENAME
, map_sz
},
277 {SPOOL_REG_PRINTSPOOLING
, map_sz
},
278 {SPOOL_REG_PRINTSTAPLINGSUPPORTED
, map_bool
},
279 {SPOOL_REG_PRINTSTARTTIME
, map_dword
},
280 {SPOOL_REG_PRINTSTATUS
, map_sz
},
281 {SPOOL_REG_PRIORITY
, map_dword
},
282 {SPOOL_REG_SERVERNAME
, map_sz
},
283 {SPOOL_REG_SHORTSERVERNAME
, map_sz
},
284 {SPOOL_REG_UNCNAME
, map_sz
},
285 {SPOOL_REG_URL
, map_sz
},
286 {SPOOL_REG_VERSIONNUMBER
, map_dword
},
291 for (i
=0; map
[i
].valname
; i
++) {
292 if (StrCaseCmp(map
[i
].valname
, regval_name(value
)) == 0) {
293 if (!map
[i
].fn(ctx
, mods
, value
)) {
294 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value
)));
296 DEBUG(7, ("Mapped value %s\n", regval_name(value
)));
304 WERROR
get_remote_printer_publishing_data(struct rpc_pipe_client
*cli
,
309 struct dcerpc_binding_handle
*b
= cli
->binding_handle
;
312 struct spoolss_PrinterEnumValues
*info
;
315 struct policy_handle pol
;
318 if ((asprintf(&printername
, "%s\\%s", cli
->srv_name_slash
, printer
) == -1)) {
319 DEBUG(3, ("Insufficient memory\n"));
323 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
325 SEC_FLAG_MAXIMUM_ALLOWED
,
327 if (!W_ERROR_IS_OK(result
)) {
328 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
329 printername
, win_errstr(result
)));
330 SAFE_FREE(printername
);
334 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 /* Have the data we need now, so start building */
345 for (i
=0; i
< count
; i
++) {
346 struct regval_blob
*v
;
348 v
= regval_compose(mem_ctx
, info
[i
].value_name
,
351 info
[i
].data
->length
);
356 map_regval_to_ads(mem_ctx
, mods
, v
);
361 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
366 if (!W_ERROR_IS_OK(result
)) {
367 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
368 printername
, win_errstr(result
)));
370 for (i
=0; i
< count
; i
++) {
371 struct regval_blob
*v
;
373 v
= regval_compose(mem_ctx
, info
[i
].value_name
,
376 info
[i
].data
->length
);
381 map_regval_to_ads(mem_ctx
, mods
, v
);
386 ads_mod_str(mem_ctx
, mods
, SPOOL_REG_PRINTERNAME
, printer
);
388 dcerpc_spoolss_ClosePrinter(b
, mem_ctx
, &pol
, &werr
);
389 SAFE_FREE(printername
);