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"
24 #include "registry/reg_objects.h"
25 #include "nt_printing.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) {
50 ads_msgfree(ads, *res);
53 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
55 srv_dn = ldap_get_dn(ads->ldap.ld, *res);
58 ads_msgfree(ads, *res);
61 return ADS_ERROR(LDAP_NO_MEMORY);
63 srv_cn = ldap_explode_dn(srv_dn, 1);
67 ads_msgfree(ads, *res);
70 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
73 ads_msgfree(ads, *res);
77 if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
79 return ADS_ERROR(LDAP_NO_MEMORY);
81 status = ads_search(ads, res, s, attrs);
84 ldap_value_free(srv_cn);
89 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
91 const char *ldap_expr;
92 const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
93 "serverName", "description", NULL };
95 /* For the moment only display all printers */
97 ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
98 "(objectCategory=printQueue))";
100 return ads_search(ads, res, ldap_expr, attrs);
104 modify a printer entry in the directory
106 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
107 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
109 return ads_gen_mod(ads, prt_dn, *mods);
113 add a printer to the directory
115 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
116 TALLOC_CTX *ctx, ADS_MODLIST *mods)
118 ads_mod_str(ctx, mods, "objectClass", "printQueue");
119 return ads_gen_add(ads, prt_dn, *mods);
123 map a REG_SZ to an ldap mod
125 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
126 struct regval_blob *value)
128 char *str_value = NULL;
129 size_t converted_size;
132 if (regval_type(value) != REG_SZ)
135 if (regval_size(value) && *((smb_ucs2_t *) regval_data_p(value))) {
136 if (!pull_ucs2_talloc(ctx, &str_value,
137 (const smb_ucs2_t *) regval_data_p(value),
142 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
143 return ADS_ERR_OK(status);
150 map a REG_DWORD to an ldap mod
152 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
153 struct regval_blob *value)
155 char *str_value = NULL;
158 if (regval_type(value) != REG_DWORD)
160 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) regval_data_p(value)));
164 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
165 return ADS_ERR_OK(status);
169 map a boolean REG_BINARY to an ldap mod
171 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
172 struct regval_blob *value)
177 if ((regval_type(value) != REG_BINARY) || (regval_size(value) != 1))
179 str_value = talloc_asprintf(ctx, "%s",
180 *(regval_data_p(value)) ? "TRUE" : "FALSE");
184 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
185 return ADS_ERR_OK(status);
189 map a REG_MULTI_SZ to an ldap mod
191 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
192 struct regval_blob *value)
194 char **str_values = NULL;
195 size_t converted_size;
196 smb_ucs2_t *cur_str = (smb_ucs2_t *) regval_data_p(value);
197 uint32 size = 0, num_vals = 0, i=0;
200 if (regval_type(value) != REG_MULTI_SZ)
203 while(cur_str && *cur_str && (size < regval_size(value))) {
204 size += 2 * (strlen_w(cur_str) + 1);
205 cur_str += strlen_w(cur_str) + 1;
210 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
214 memset(str_values, '\0',
215 (num_vals + 1) * sizeof(char *));
217 cur_str = (smb_ucs2_t *) regval_data_p(value);
218 for (i=0; i < num_vals; i++) {
219 cur_str += pull_ucs2_talloc(ctx, &str_values[i],
220 cur_str, &converted_size) ?
221 converted_size : (size_t)-1;
224 status = ads_mod_strlist(ctx, mods, regval_name(value),
225 (const char **) str_values);
226 return ADS_ERR_OK(status);
231 struct valmap_to_ads {
233 bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, struct regval_blob *);
237 map a REG_SZ to an ldap mod
239 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
240 struct regval_blob *value)
242 const struct valmap_to_ads map[] = {
243 {SPOOL_REG_ASSETNUMBER, map_sz},
244 {SPOOL_REG_BYTESPERMINUTE, map_dword},
245 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
246 {SPOOL_REG_DESCRIPTION, map_sz},
247 {SPOOL_REG_DRIVERNAME, map_sz},
248 {SPOOL_REG_DRIVERVERSION, map_dword},
249 {SPOOL_REG_FLAGS, map_dword},
250 {SPOOL_REG_LOCATION, map_sz},
251 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
252 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
253 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
254 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
255 {SPOOL_REG_PORTNAME, map_multi_sz},
256 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
257 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
258 {SPOOL_REG_PRINTCOLLATE, map_bool},
259 {SPOOL_REG_PRINTCOLOR, map_bool},
260 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
261 {SPOOL_REG_PRINTENDTIME, map_dword},
262 {SPOOL_REG_PRINTFORMNAME, map_sz},
263 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
264 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
265 {SPOOL_REG_PRINTMACADDRESS, map_sz},
266 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
267 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
268 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
269 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
270 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
271 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
272 {SPOOL_REG_PRINTMEMORY, map_dword},
273 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
274 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
275 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
276 {SPOOL_REG_PRINTNOTIFY, map_sz},
277 {SPOOL_REG_PRINTNUMBERUP, map_dword},
278 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
279 {SPOOL_REG_PRINTOWNER, map_sz},
280 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
281 {SPOOL_REG_PRINTRATE, map_dword},
282 {SPOOL_REG_PRINTRATEUNIT, map_sz},
283 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
284 {SPOOL_REG_PRINTSHARENAME, map_sz},
285 {SPOOL_REG_PRINTSPOOLING, map_sz},
286 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
287 {SPOOL_REG_PRINTSTARTTIME, map_dword},
288 {SPOOL_REG_PRINTSTATUS, map_sz},
289 {SPOOL_REG_PRIORITY, map_dword},
290 {SPOOL_REG_SERVERNAME, map_sz},
291 {SPOOL_REG_SHORTSERVERNAME, map_sz},
292 {SPOOL_REG_UNCNAME, map_sz},
293 {SPOOL_REG_URL, map_sz},
294 {SPOOL_REG_VERSIONNUMBER, map_dword},
299 for (i=0; map[i].valname; i++) {
300 if (StrCaseCmp(map[i].valname, regval_name(value)) == 0) {
301 if (!map[i].fn(ctx, mods, value)) {
302 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value)));
304 DEBUG(7, ("Mapped value %s\n", regval_name(value)));
312 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
319 struct spoolss_PrinterEnumValues *info;
322 struct policy_handle pol;
324 if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
325 DEBUG(3, ("Insufficient memory\n"));
329 result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
331 SEC_FLAG_MAXIMUM_ALLOWED,
333 if (!W_ERROR_IS_OK(result)) {
334 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
335 printername, win_errstr(result)));
336 SAFE_FREE(printername);
340 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
346 if (!W_ERROR_IS_OK(result)) {
347 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
348 printername, win_errstr(result)));
350 /* Have the data we need now, so start building */
351 for (i=0; i < count; i++) {
352 struct regval_blob *v;
354 v = regval_compose(mem_ctx, info[i].value_name,
357 info[i].data->length);
362 map_regval_to_ads(mem_ctx, mods, v);
367 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
372 if (!W_ERROR_IS_OK(result)) {
373 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
374 printername, win_errstr(result)));
376 for (i=0; i < count; i++) {
377 struct regval_blob *v;
379 v = regval_compose(mem_ctx, info[i].value_name,
382 info[i].data->length);
387 map_regval_to_ads(mem_ctx, mods, v);
392 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
394 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
395 SAFE_FREE(printername);
400 static bool get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
402 NT_PRINTER_DATA *data)
406 for (key=0; key < data->num_keys; key++) {
407 struct regval_ctr *ctr = data->keys[key].values;
408 for (val=0; val < regval_ctr_numvals(ctr); val++)
409 map_regval_to_ads(mem_ctx, mods, regval_ctr_specific_value(ctr, val));