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/>.
21 #include "../librpc/gen_ndr/cli_spoolss.h"
22 #include "rpc_client/cli_spoolss.h"
28 find a printer given the name and the hostname
29 Note that results "res" may be allocated on return so that the
30 results can be used. It should be freed using ads_msgfree.
32 ADS_STATUS
ads_find_printer_on_server(ADS_STRUCT
*ads
, LDAPMessage
**res
,
34 const char *servername
)
37 char *srv_dn
, **srv_cn
, *s
= NULL
;
38 const char *attrs
[] = {"*", "nTSecurityDescriptor", NULL
};
40 status
= ads_find_machine_acct(ads
, res
, servername
);
41 if (!ADS_ERR_OK(status
)) {
42 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
46 if (ads_count_replies(ads
, *res
) != 1) {
48 ads_msgfree(ads
, *res
);
51 return ADS_ERROR(LDAP_NO_SUCH_OBJECT
);
53 srv_dn
= ldap_get_dn(ads
->ldap
.ld
, *res
);
56 ads_msgfree(ads
, *res
);
59 return ADS_ERROR(LDAP_NO_MEMORY
);
61 srv_cn
= ldap_explode_dn(srv_dn
, 1);
65 ads_msgfree(ads
, *res
);
68 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX
);
71 ads_msgfree(ads
, *res
);
75 if (asprintf(&s
, "(cn=%s-%s)", srv_cn
[0], printer
) == -1) {
77 return ADS_ERROR(LDAP_NO_MEMORY
);
79 status
= ads_search(ads
, res
, s
, attrs
);
82 ldap_value_free(srv_cn
);
87 ADS_STATUS
ads_find_printers(ADS_STRUCT
*ads
, LDAPMessage
**res
)
89 const char *ldap_expr
;
90 const char *attrs
[] = { "objectClass", "printerName", "location", "driverName",
91 "serverName", "description", NULL
};
93 /* For the moment only display all printers */
95 ldap_expr
= "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
96 "(objectCategory=printQueue))";
98 return ads_search(ads
, res
, ldap_expr
, attrs
);
102 modify a printer entry in the directory
104 ADS_STATUS
ads_mod_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
105 TALLOC_CTX
*ctx
, const ADS_MODLIST
*mods
)
107 return ads_gen_mod(ads
, prt_dn
, *mods
);
111 add a printer to the directory
113 ADS_STATUS
ads_add_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
114 TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
)
116 ads_mod_str(ctx
, mods
, "objectClass", "printQueue");
117 return ads_gen_add(ads
, prt_dn
, *mods
);
121 map a REG_SZ to an ldap mod
123 static bool map_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
124 const struct regval_blob
*value
)
126 char *str_value
= NULL
;
127 size_t converted_size
;
130 if (regval_type(value
) != REG_SZ
)
133 if (regval_size(value
) && *((smb_ucs2_t
*) regval_data_p(value
))) {
134 if (!pull_ucs2_talloc(ctx
, &str_value
,
135 (const smb_ucs2_t
*) regval_data_p(value
),
140 status
= ads_mod_str(ctx
, mods
, regval_name(value
), str_value
);
141 return ADS_ERR_OK(status
);
148 map a REG_DWORD to an ldap mod
150 static bool map_dword(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
151 const struct regval_blob
*value
)
153 char *str_value
= NULL
;
156 if (regval_type(value
) != REG_DWORD
)
158 str_value
= talloc_asprintf(ctx
, "%d", *((uint32
*) regval_data_p(value
)));
162 status
= ads_mod_str(ctx
, mods
, regval_name(value
), str_value
);
163 return ADS_ERR_OK(status
);
167 map a boolean REG_BINARY to an ldap mod
169 static bool map_bool(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
170 const struct regval_blob
*value
)
175 if ((regval_type(value
) != REG_BINARY
) || (regval_size(value
) != 1))
177 str_value
= talloc_asprintf(ctx
, "%s",
178 *(regval_data_p(value
)) ? "TRUE" : "FALSE");
182 status
= ads_mod_str(ctx
, mods
, regval_name(value
), str_value
);
183 return ADS_ERR_OK(status
);
187 map a REG_MULTI_SZ to an ldap mod
189 static bool map_multi_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
190 const struct regval_blob
*value
)
192 char **str_values
= NULL
;
193 size_t converted_size
;
194 smb_ucs2_t
*cur_str
= (smb_ucs2_t
*) regval_data_p(value
);
195 uint32 size
= 0, num_vals
= 0, i
=0;
198 if (regval_type(value
) != REG_MULTI_SZ
)
201 while(cur_str
&& *cur_str
&& (size
< regval_size(value
))) {
202 size
+= 2 * (strlen_w(cur_str
) + 1);
203 cur_str
+= strlen_w(cur_str
) + 1;
208 str_values
= TALLOC_ARRAY(ctx
, char *, num_vals
+ 1);
212 memset(str_values
, '\0',
213 (num_vals
+ 1) * sizeof(char *));
215 cur_str
= (smb_ucs2_t
*) regval_data_p(value
);
216 for (i
=0; i
< num_vals
; i
++) {
217 cur_str
+= pull_ucs2_talloc(ctx
, &str_values
[i
],
218 cur_str
, &converted_size
) ?
219 converted_size
: (size_t)-1;
222 status
= ads_mod_strlist(ctx
, mods
, regval_name(value
),
223 (const char **) str_values
);
224 return ADS_ERR_OK(status
);
229 struct valmap_to_ads
{
231 bool (*fn
)(TALLOC_CTX
*, ADS_MODLIST
*, const struct regval_blob
*);
235 map a REG_SZ to an ldap mod
237 static void map_regval_to_ads(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
238 struct regval_blob
*value
)
240 const struct valmap_to_ads map
[] = {
241 {SPOOL_REG_ASSETNUMBER
, map_sz
},
242 {SPOOL_REG_BYTESPERMINUTE
, map_dword
},
243 {SPOOL_REG_DEFAULTPRIORITY
, map_dword
},
244 {SPOOL_REG_DESCRIPTION
, map_sz
},
245 {SPOOL_REG_DRIVERNAME
, map_sz
},
246 {SPOOL_REG_DRIVERVERSION
, map_dword
},
247 {SPOOL_REG_FLAGS
, map_dword
},
248 {SPOOL_REG_LOCATION
, map_sz
},
249 {SPOOL_REG_OPERATINGSYSTEM
, map_sz
},
250 {SPOOL_REG_OPERATINGSYSTEMHOTFIX
, map_sz
},
251 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK
, map_sz
},
252 {SPOOL_REG_OPERATINGSYSTEMVERSION
, map_sz
},
253 {SPOOL_REG_PORTNAME
, map_multi_sz
},
254 {SPOOL_REG_PRINTATTRIBUTES
, map_dword
},
255 {SPOOL_REG_PRINTBINNAMES
, map_multi_sz
},
256 {SPOOL_REG_PRINTCOLLATE
, map_bool
},
257 {SPOOL_REG_PRINTCOLOR
, map_bool
},
258 {SPOOL_REG_PRINTDUPLEXSUPPORTED
, map_bool
},
259 {SPOOL_REG_PRINTENDTIME
, map_dword
},
260 {SPOOL_REG_PRINTFORMNAME
, map_sz
},
261 {SPOOL_REG_PRINTKEEPPRINTEDJOBS
, map_bool
},
262 {SPOOL_REG_PRINTLANGUAGE
, map_multi_sz
},
263 {SPOOL_REG_PRINTMACADDRESS
, map_sz
},
264 {SPOOL_REG_PRINTMAXCOPIES
, map_sz
},
265 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED
, map_dword
},
266 {SPOOL_REG_PRINTMAXXEXTENT
, map_dword
},
267 {SPOOL_REG_PRINTMAXYEXTENT
, map_dword
},
268 {SPOOL_REG_PRINTMEDIAREADY
, map_multi_sz
},
269 {SPOOL_REG_PRINTMEDIASUPPORTED
, map_multi_sz
},
270 {SPOOL_REG_PRINTMEMORY
, map_dword
},
271 {SPOOL_REG_PRINTMINXEXTENT
, map_dword
},
272 {SPOOL_REG_PRINTMINYEXTENT
, map_dword
},
273 {SPOOL_REG_PRINTNETWORKADDRESS
, map_sz
},
274 {SPOOL_REG_PRINTNOTIFY
, map_sz
},
275 {SPOOL_REG_PRINTNUMBERUP
, map_dword
},
276 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED
, map_multi_sz
},
277 {SPOOL_REG_PRINTOWNER
, map_sz
},
278 {SPOOL_REG_PRINTPAGESPERMINUTE
, map_dword
},
279 {SPOOL_REG_PRINTRATE
, map_dword
},
280 {SPOOL_REG_PRINTRATEUNIT
, map_sz
},
281 {SPOOL_REG_PRINTSEPARATORFILE
, map_sz
},
282 {SPOOL_REG_PRINTSHARENAME
, map_sz
},
283 {SPOOL_REG_PRINTSPOOLING
, map_sz
},
284 {SPOOL_REG_PRINTSTAPLINGSUPPORTED
, map_bool
},
285 {SPOOL_REG_PRINTSTARTTIME
, map_dword
},
286 {SPOOL_REG_PRINTSTATUS
, map_sz
},
287 {SPOOL_REG_PRIORITY
, map_dword
},
288 {SPOOL_REG_SERVERNAME
, map_sz
},
289 {SPOOL_REG_SHORTSERVERNAME
, map_sz
},
290 {SPOOL_REG_UNCNAME
, map_sz
},
291 {SPOOL_REG_URL
, map_sz
},
292 {SPOOL_REG_VERSIONNUMBER
, map_dword
},
297 for (i
=0; map
[i
].valname
; i
++) {
298 if (StrCaseCmp(map
[i
].valname
, regval_name(value
)) == 0) {
299 if (!map
[i
].fn(ctx
, mods
, value
)) {
300 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value
)));
302 DEBUG(7, ("Mapped value %s\n", regval_name(value
)));
310 WERROR
get_remote_printer_publishing_data(struct rpc_pipe_client
*cli
,
317 struct spoolss_PrinterEnumValues
*info
;
320 struct policy_handle pol
;
322 if ((asprintf(&printername
, "%s\\%s", cli
->srv_name_slash
, printer
) == -1)) {
323 DEBUG(3, ("Insufficient memory\n"));
327 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
329 SEC_FLAG_MAXIMUM_ALLOWED
,
331 if (!W_ERROR_IS_OK(result
)) {
332 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
333 printername
, win_errstr(result
)));
334 SAFE_FREE(printername
);
338 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
344 if (!W_ERROR_IS_OK(result
)) {
345 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
346 printername
, win_errstr(result
)));
348 /* Have the data we need now, so start building */
349 for (i
=0; i
< count
; i
++) {
350 struct regval_blob
*v
;
352 v
= regval_compose(mem_ctx
, info
[i
].value_name
,
355 info
[i
].data
->length
);
360 map_regval_to_ads(mem_ctx
, mods
, v
);
365 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
370 if (!W_ERROR_IS_OK(result
)) {
371 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
372 printername
, win_errstr(result
)));
374 for (i
=0; i
< count
; i
++) {
375 struct regval_blob
*v
;
377 v
= regval_compose(mem_ctx
, info
[i
].value_name
,
380 info
[i
].data
->length
);
385 map_regval_to_ads(mem_ctx
, mods
, v
);
390 ads_mod_str(mem_ctx
, mods
, SPOOL_REG_PRINTERNAME
, printer
);
392 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
393 SAFE_FREE(printername
);
398 bool get_local_printer_publishing_data(TALLOC_CTX
*mem_ctx
,
400 NT_PRINTER_DATA
*data
)
404 for (key
=0; key
< data
->num_keys
; key
++) {
405 struct regval_ctr
*ctr
= data
->keys
[key
].values
;
406 for (val
=0; val
< regval_ctr_numvals(ctr
); val
++)
407 map_regval_to_ads(mem_ctx
, mods
, regval_ctr_specific_value(ctr
, val
));