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"
29 find a printer given the name and the hostname
30 Note that results "res" may be allocated on return so that the
31 results can be used. It should be freed using ads_msgfree.
33 ADS_STATUS
ads_find_printer_on_server(ADS_STRUCT
*ads
, LDAPMessage
**res
,
35 const char *servername
)
38 char *srv_dn
, **srv_cn
, *s
= NULL
;
39 const char *attrs
[] = {"*", "nTSecurityDescriptor", NULL
};
41 status
= ads_find_machine_acct(ads
, res
, servername
);
42 if (!ADS_ERR_OK(status
)) {
43 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
47 if (ads_count_replies(ads
, *res
) != 1) {
49 ads_msgfree(ads
, *res
);
52 return ADS_ERROR(LDAP_NO_SUCH_OBJECT
);
54 srv_dn
= ldap_get_dn(ads
->ldap
.ld
, *res
);
57 ads_msgfree(ads
, *res
);
60 return ADS_ERROR(LDAP_NO_MEMORY
);
62 srv_cn
= ldap_explode_dn(srv_dn
, 1);
66 ads_msgfree(ads
, *res
);
69 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX
);
72 ads_msgfree(ads
, *res
);
76 if (asprintf(&s
, "(cn=%s-%s)", srv_cn
[0], printer
) == -1) {
78 return ADS_ERROR(LDAP_NO_MEMORY
);
80 status
= ads_search(ads
, res
, s
, attrs
);
83 ldap_value_free(srv_cn
);
88 ADS_STATUS
ads_find_printers(ADS_STRUCT
*ads
, LDAPMessage
**res
)
90 const char *ldap_expr
;
91 const char *attrs
[] = { "objectClass", "printerName", "location", "driverName",
92 "serverName", "description", NULL
};
94 /* For the moment only display all printers */
96 ldap_expr
= "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
97 "(objectCategory=printQueue))";
99 return ads_search(ads
, res
, ldap_expr
, attrs
);
103 modify a printer entry in the directory
105 ADS_STATUS
ads_mod_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
106 TALLOC_CTX
*ctx
, const ADS_MODLIST
*mods
)
108 return ads_gen_mod(ads
, prt_dn
, *mods
);
112 add a printer to the directory
114 ADS_STATUS
ads_add_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
115 TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
)
117 ads_mod_str(ctx
, mods
, "objectClass", "printQueue");
118 return ads_gen_add(ads
, prt_dn
, *mods
);
122 map a REG_SZ to an ldap mod
124 static bool map_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
125 struct regval_blob
*value
)
127 char *str_value
= NULL
;
128 size_t converted_size
;
131 if (regval_type(value
) != REG_SZ
)
134 if (regval_size(value
) && *((smb_ucs2_t
*) regval_data_p(value
))) {
135 if (!pull_ucs2_talloc(ctx
, &str_value
,
136 (const smb_ucs2_t
*) regval_data_p(value
),
141 status
= ads_mod_str(ctx
, mods
, regval_name(value
), str_value
);
142 return ADS_ERR_OK(status
);
149 map a REG_DWORD to an ldap mod
151 static bool map_dword(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
152 struct regval_blob
*value
)
154 char *str_value
= NULL
;
157 if (regval_type(value
) != REG_DWORD
)
159 str_value
= talloc_asprintf(ctx
, "%d", *((uint32
*) regval_data_p(value
)));
163 status
= ads_mod_str(ctx
, mods
, regval_name(value
), str_value
);
164 return ADS_ERR_OK(status
);
168 map a boolean REG_BINARY to an ldap mod
170 static bool map_bool(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
171 struct regval_blob
*value
)
176 if ((regval_type(value
) != REG_BINARY
) || (regval_size(value
) != 1))
178 str_value
= talloc_asprintf(ctx
, "%s",
179 *(regval_data_p(value
)) ? "TRUE" : "FALSE");
183 status
= ads_mod_str(ctx
, mods
, regval_name(value
), str_value
);
184 return ADS_ERR_OK(status
);
188 map a REG_MULTI_SZ to an ldap mod
190 static bool map_multi_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
191 struct regval_blob
*value
)
193 char **str_values
= NULL
;
194 size_t converted_size
;
195 smb_ucs2_t
*cur_str
= (smb_ucs2_t
*) regval_data_p(value
);
196 uint32 size
= 0, num_vals
= 0, i
=0;
199 if (regval_type(value
) != REG_MULTI_SZ
)
202 while(cur_str
&& *cur_str
&& (size
< regval_size(value
))) {
203 size
+= 2 * (strlen_w(cur_str
) + 1);
204 cur_str
+= strlen_w(cur_str
) + 1;
209 str_values
= TALLOC_ARRAY(ctx
, char *, num_vals
+ 1);
213 memset(str_values
, '\0',
214 (num_vals
+ 1) * sizeof(char *));
216 cur_str
= (smb_ucs2_t
*) regval_data_p(value
);
217 for (i
=0; i
< num_vals
; i
++) {
218 cur_str
+= pull_ucs2_talloc(ctx
, &str_values
[i
],
219 cur_str
, &converted_size
) ?
220 converted_size
: (size_t)-1;
223 status
= ads_mod_strlist(ctx
, mods
, regval_name(value
),
224 (const char **) str_values
);
225 return ADS_ERR_OK(status
);
230 struct valmap_to_ads
{
232 bool (*fn
)(TALLOC_CTX
*, ADS_MODLIST
*, struct regval_blob
*);
236 map a REG_SZ to an ldap mod
238 static void map_regval_to_ads(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
239 struct regval_blob
*value
)
241 const struct valmap_to_ads map
[] = {
242 {SPOOL_REG_ASSETNUMBER
, map_sz
},
243 {SPOOL_REG_BYTESPERMINUTE
, map_dword
},
244 {SPOOL_REG_DEFAULTPRIORITY
, map_dword
},
245 {SPOOL_REG_DESCRIPTION
, map_sz
},
246 {SPOOL_REG_DRIVERNAME
, map_sz
},
247 {SPOOL_REG_DRIVERVERSION
, map_dword
},
248 {SPOOL_REG_FLAGS
, map_dword
},
249 {SPOOL_REG_LOCATION
, map_sz
},
250 {SPOOL_REG_OPERATINGSYSTEM
, map_sz
},
251 {SPOOL_REG_OPERATINGSYSTEMHOTFIX
, map_sz
},
252 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK
, map_sz
},
253 {SPOOL_REG_OPERATINGSYSTEMVERSION
, map_sz
},
254 {SPOOL_REG_PORTNAME
, map_multi_sz
},
255 {SPOOL_REG_PRINTATTRIBUTES
, map_dword
},
256 {SPOOL_REG_PRINTBINNAMES
, map_multi_sz
},
257 {SPOOL_REG_PRINTCOLLATE
, map_bool
},
258 {SPOOL_REG_PRINTCOLOR
, map_bool
},
259 {SPOOL_REG_PRINTDUPLEXSUPPORTED
, map_bool
},
260 {SPOOL_REG_PRINTENDTIME
, map_dword
},
261 {SPOOL_REG_PRINTFORMNAME
, map_sz
},
262 {SPOOL_REG_PRINTKEEPPRINTEDJOBS
, map_bool
},
263 {SPOOL_REG_PRINTLANGUAGE
, map_multi_sz
},
264 {SPOOL_REG_PRINTMACADDRESS
, map_sz
},
265 {SPOOL_REG_PRINTMAXCOPIES
, map_sz
},
266 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED
, map_dword
},
267 {SPOOL_REG_PRINTMAXXEXTENT
, map_dword
},
268 {SPOOL_REG_PRINTMAXYEXTENT
, map_dword
},
269 {SPOOL_REG_PRINTMEDIAREADY
, map_multi_sz
},
270 {SPOOL_REG_PRINTMEDIASUPPORTED
, map_multi_sz
},
271 {SPOOL_REG_PRINTMEMORY
, map_dword
},
272 {SPOOL_REG_PRINTMINXEXTENT
, map_dword
},
273 {SPOOL_REG_PRINTMINYEXTENT
, map_dword
},
274 {SPOOL_REG_PRINTNETWORKADDRESS
, map_sz
},
275 {SPOOL_REG_PRINTNOTIFY
, map_sz
},
276 {SPOOL_REG_PRINTNUMBERUP
, map_dword
},
277 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED
, map_multi_sz
},
278 {SPOOL_REG_PRINTOWNER
, map_sz
},
279 {SPOOL_REG_PRINTPAGESPERMINUTE
, map_dword
},
280 {SPOOL_REG_PRINTRATE
, map_dword
},
281 {SPOOL_REG_PRINTRATEUNIT
, map_sz
},
282 {SPOOL_REG_PRINTSEPARATORFILE
, map_sz
},
283 {SPOOL_REG_PRINTSHARENAME
, map_sz
},
284 {SPOOL_REG_PRINTSPOOLING
, map_sz
},
285 {SPOOL_REG_PRINTSTAPLINGSUPPORTED
, map_bool
},
286 {SPOOL_REG_PRINTSTARTTIME
, map_dword
},
287 {SPOOL_REG_PRINTSTATUS
, map_sz
},
288 {SPOOL_REG_PRIORITY
, map_dword
},
289 {SPOOL_REG_SERVERNAME
, map_sz
},
290 {SPOOL_REG_SHORTSERVERNAME
, map_sz
},
291 {SPOOL_REG_UNCNAME
, map_sz
},
292 {SPOOL_REG_URL
, map_sz
},
293 {SPOOL_REG_VERSIONNUMBER
, map_dword
},
298 for (i
=0; map
[i
].valname
; i
++) {
299 if (StrCaseCmp(map
[i
].valname
, regval_name(value
)) == 0) {
300 if (!map
[i
].fn(ctx
, mods
, value
)) {
301 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value
)));
303 DEBUG(7, ("Mapped value %s\n", regval_name(value
)));
311 WERROR
get_remote_printer_publishing_data(struct rpc_pipe_client
*cli
,
318 struct spoolss_PrinterEnumValues
*info
;
321 struct policy_handle pol
;
323 if ((asprintf(&printername
, "%s\\%s", cli
->srv_name_slash
, printer
) == -1)) {
324 DEBUG(3, ("Insufficient memory\n"));
328 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
330 SEC_FLAG_MAXIMUM_ALLOWED
,
332 if (!W_ERROR_IS_OK(result
)) {
333 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
334 printername
, win_errstr(result
)));
335 SAFE_FREE(printername
);
339 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
345 if (!W_ERROR_IS_OK(result
)) {
346 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
347 printername
, win_errstr(result
)));
349 /* Have the data we need now, so start building */
350 for (i
=0; i
< count
; i
++) {
351 struct regval_blob
*v
;
353 v
= regval_compose(mem_ctx
, info
[i
].value_name
,
356 info
[i
].data
->length
);
361 map_regval_to_ads(mem_ctx
, mods
, v
);
366 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
371 if (!W_ERROR_IS_OK(result
)) {
372 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
373 printername
, win_errstr(result
)));
375 for (i
=0; i
< count
; i
++) {
376 struct regval_blob
*v
;
378 v
= regval_compose(mem_ctx
, info
[i
].value_name
,
381 info
[i
].data
->length
);
386 map_regval_to_ads(mem_ctx
, mods
, v
);
391 ads_mod_str(mem_ctx
, mods
, SPOOL_REG_PRINTERNAME
, printer
);
393 rpccli_spoolss_ClosePrinter(cli
, mem_ctx
, &pol
, NULL
);
394 SAFE_FREE(printername
);
399 bool get_local_printer_publishing_data(TALLOC_CTX
*mem_ctx
,
401 NT_PRINTER_DATA
*data
)
405 for (key
=0; key
< data
->num_keys
; key
++) {
406 struct regval_ctr
*ctr
= data
->keys
[key
].values
;
407 for (val
=0; val
< regval_ctr_numvals(ctr
); val
++)
408 map_regval_to_ads(mem_ctx
, mods
, regval_ctr_specific_value(ctr
, val
));