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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 find a printer given the name and the hostname
27 Note that results "res" may be allocated on return so that the
28 results can be used. It should be freed using ads_msgfree.
30 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
32 const char *servername)
35 char *srv_dn, **srv_cn, *s;
36 const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
38 status = ads_find_machine_acct(ads, res, servername);
39 if (!ADS_ERR_OK(status)) {
40 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
44 if (ads_count_replies(ads, *res) != 1) {
45 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
47 srv_dn = ldap_get_dn(ads->ld, *res);
49 return ADS_ERROR(LDAP_NO_MEMORY);
51 srv_cn = ldap_explode_dn(srv_dn, 1);
54 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
56 ads_msgfree(ads, *res);
58 asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer);
59 status = ads_search(ads, res, s, attrs);
62 ldap_value_free(srv_cn);
67 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
69 const char *ldap_expr;
70 const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
71 "serverName", "description", NULL };
73 /* For the moment only display all printers */
75 ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
76 "(objectCategory=printQueue))";
78 return ads_search(ads, res, ldap_expr, attrs);
82 modify a printer entry in the directory
84 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
85 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
87 return ads_gen_mod(ads, prt_dn, *mods);
91 add a printer to the directory
93 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
94 TALLOC_CTX *ctx, ADS_MODLIST *mods)
96 ads_mod_str(ctx, mods, "objectClass", "printQueue");
97 return ads_gen_add(ads, prt_dn, *mods);
101 map a REG_SZ to an ldap mod
103 static BOOL map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
104 const REGISTRY_VALUE *value)
106 char *str_value = NULL;
109 if (value->type != REG_SZ)
112 if (value->size && *((smb_ucs2_t *) value->data_p)) {
113 pull_ucs2_talloc(ctx, &str_value, (const smb_ucs2_t *) value->data_p);
114 status = ads_mod_str(ctx, mods, value->valuename, str_value);
115 return ADS_ERR_OK(status);
122 map a REG_DWORD to an ldap mod
124 static BOOL map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
125 const REGISTRY_VALUE *value)
127 char *str_value = NULL;
130 if (value->type != REG_DWORD)
132 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) value->data_p));
136 status = ads_mod_str(ctx, mods, value->valuename, str_value);
137 return ADS_ERR_OK(status);
141 map a boolean REG_BINARY to an ldap mod
143 static BOOL map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
144 const REGISTRY_VALUE *value)
149 if ((value->type != REG_BINARY) || (value->size != 1))
151 str_value = talloc_asprintf(ctx, "%s",
152 *(value->data_p) ? "TRUE" : "FALSE");
156 status = ads_mod_str(ctx, mods, value->valuename, str_value);
157 return ADS_ERR_OK(status);
161 map a REG_MULTI_SZ to an ldap mod
163 static BOOL map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
164 const REGISTRY_VALUE *value)
166 char **str_values = NULL;
167 smb_ucs2_t *cur_str = (smb_ucs2_t *) value->data_p;
168 uint32 size = 0, num_vals = 0, i=0;
171 if (value->type != REG_MULTI_SZ)
174 while(cur_str && *cur_str && (size < value->size)) {
175 size += 2 * (strlen_w(cur_str) + 1);
176 cur_str += strlen_w(cur_str) + 1;
181 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
185 memset(str_values, '\0',
186 (num_vals + 1) * sizeof(char *));
188 cur_str = (smb_ucs2_t *) value->data_p;
189 for (i=0; i < num_vals; i++)
190 cur_str += pull_ucs2_talloc(ctx, &str_values[i],
193 status = ads_mod_strlist(ctx, mods, value->valuename,
194 (const char **) str_values);
195 return ADS_ERR_OK(status);
200 struct valmap_to_ads {
202 BOOL (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *);
206 map a REG_SZ to an ldap mod
208 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
209 REGISTRY_VALUE *value)
211 const struct valmap_to_ads map[] = {
212 {SPOOL_REG_ASSETNUMBER, map_sz},
213 {SPOOL_REG_BYTESPERMINUTE, map_dword},
214 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
215 {SPOOL_REG_DESCRIPTION, map_sz},
216 {SPOOL_REG_DRIVERNAME, map_sz},
217 {SPOOL_REG_DRIVERVERSION, map_dword},
218 {SPOOL_REG_FLAGS, map_dword},
219 {SPOOL_REG_LOCATION, map_sz},
220 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
221 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
222 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
223 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
224 {SPOOL_REG_PORTNAME, map_multi_sz},
225 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
226 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
227 {SPOOL_REG_PRINTCOLLATE, map_bool},
228 {SPOOL_REG_PRINTCOLOR, map_bool},
229 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
230 {SPOOL_REG_PRINTENDTIME, map_dword},
231 {SPOOL_REG_PRINTFORMNAME, map_sz},
232 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
233 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
234 {SPOOL_REG_PRINTMACADDRESS, map_sz},
235 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
236 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
237 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
238 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
239 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
240 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
241 {SPOOL_REG_PRINTMEMORY, map_dword},
242 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
243 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
244 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
245 {SPOOL_REG_PRINTNOTIFY, map_sz},
246 {SPOOL_REG_PRINTNUMBERUP, map_dword},
247 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
248 {SPOOL_REG_PRINTOWNER, map_sz},
249 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
250 {SPOOL_REG_PRINTRATE, map_dword},
251 {SPOOL_REG_PRINTRATEUNIT, map_sz},
252 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
253 {SPOOL_REG_PRINTSHARENAME, map_sz},
254 {SPOOL_REG_PRINTSPOOLING, map_sz},
255 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
256 {SPOOL_REG_PRINTSTARTTIME, map_dword},
257 {SPOOL_REG_PRINTSTATUS, map_sz},
258 {SPOOL_REG_PRIORITY, map_dword},
259 {SPOOL_REG_SERVERNAME, map_sz},
260 {SPOOL_REG_SHORTSERVERNAME, map_sz},
261 {SPOOL_REG_UNCNAME, map_sz},
262 {SPOOL_REG_URL, map_sz},
263 {SPOOL_REG_VERSIONNUMBER, map_dword},
268 for (i=0; map[i].valname; i++) {
269 if (StrCaseCmp(map[i].valname, value->valuename) == 0) {
270 if (!map[i].fn(ctx, mods, value)) {
271 DEBUG(5, ("Add of value %s to modlist failed\n", value->valuename));
273 DEBUG(7, ("Mapped value %s\n", value->valuename));
281 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
287 char *printername, *servername;
288 REGVAL_CTR *dsdriver_ctr, *dsspooler_ctr;
292 asprintf(&servername, "\\\\%s", cli->cli->desthost);
293 asprintf(&printername, "%s\\%s", servername, printer);
294 if (!servername || !printername) {
295 DEBUG(3, ("Insufficient memory\n"));
299 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
300 "", MAXIMUM_ALLOWED_ACCESS,
301 servername, cli->cli->user_name, &pol);
302 if (!W_ERROR_IS_OK(result)) {
303 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
304 printername, dos_errstr(result)));
308 if ( !(dsdriver_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
311 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSDRIVER_KEY, dsdriver_ctr);
313 if (!W_ERROR_IS_OK(result)) {
314 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
315 printername, dos_errstr(result)));
317 uint32 num_values = regval_ctr_numvals( dsdriver_ctr );
319 /* Have the data we need now, so start building */
320 for (i=0; i < num_values; i++) {
321 map_regval_to_ads(mem_ctx, mods, dsdriver_ctr->values[i]);
325 if ( !(dsspooler_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
328 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSSPOOLER_KEY, dsspooler_ctr);
330 if (!W_ERROR_IS_OK(result)) {
331 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
332 printername, dos_errstr(result)));
334 uint32 num_values = regval_ctr_numvals( dsspooler_ctr );
336 for (i=0; i<num_values; i++) {
337 map_regval_to_ads(mem_ctx, mods, dsspooler_ctr->values[i]);
341 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
343 TALLOC_FREE( dsdriver_ctr );
344 TALLOC_FREE( dsspooler_ctr );
346 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
351 BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
353 NT_PRINTER_DATA *data)
357 for (key=0; key < data->num_keys; key++) {
358 REGVAL_CTR *ctr = data->keys[key].values;
359 for (val=0; val < ctr->num_values; val++)
360 map_regval_to_ads(mem_ctx, mods, ctr->values[val]);