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 2 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, void **res,
31 const char *printer, const char *servername)
34 char *srv_dn, **srv_cn, *s;
35 const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
37 status = ads_find_machine_acct(ads, res, servername);
38 if (!ADS_ERR_OK(status)) {
39 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
43 srv_dn = ldap_get_dn(ads->ld, *res);
44 srv_cn = ldap_explode_dn(srv_dn, 1);
45 ads_msgfree(ads, *res);
47 asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer);
48 status = ads_search(ads, res, s, attrs);
51 ldap_value_free(srv_cn);
56 ADS_STATUS ads_find_printers(ADS_STRUCT *ads, void **res)
58 const char *ldap_expr;
59 const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
60 "serverName", "description", NULL };
62 /* For the moment only display all printers */
64 ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
65 "(objectCategory=printQueue))";
67 return ads_search(ads, res, ldap_expr, attrs);
71 modify a printer entry in the directory
73 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
74 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
76 return ads_gen_mod(ads, prt_dn, *mods);
80 add a printer to the directory
82 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
83 TALLOC_CTX *ctx, ADS_MODLIST *mods)
85 ads_mod_str(ctx, mods, "objectClass", "printQueue");
86 return ads_gen_add(ads, prt_dn, *mods);
90 map a REG_SZ to an ldap mod
92 static BOOL map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
93 const REGISTRY_VALUE *value)
95 char *str_value = NULL;
98 if (value->type != REG_SZ)
101 if (value->size && *((smb_ucs2_t *) value->data_p)) {
102 pull_ucs2_talloc(ctx, &str_value, (const smb_ucs2_t *) value->data_p);
103 status = ads_mod_str(ctx, mods, value->valuename, str_value);
104 return ADS_ERR_OK(status);
111 map a REG_DWORD to an ldap mod
113 static BOOL map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
114 const REGISTRY_VALUE *value)
116 char *str_value = NULL;
119 if (value->type != REG_DWORD)
121 str_value = talloc_asprintf(ctx, "%d", *((uint32 *) value->data_p));
125 status = ads_mod_str(ctx, mods, value->valuename, str_value);
126 return ADS_ERR_OK(status);
130 map a boolean REG_BINARY to an ldap mod
132 static BOOL map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
133 const REGISTRY_VALUE *value)
138 if ((value->type != REG_BINARY) || (value->size != 1))
140 str_value = talloc_asprintf(ctx, "%s",
141 *(value->data_p) ? "TRUE" : "FALSE");
145 status = ads_mod_str(ctx, mods, value->valuename, str_value);
146 return ADS_ERR_OK(status);
150 map a REG_MULTI_SZ to an ldap mod
152 static BOOL map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
153 const REGISTRY_VALUE *value)
155 char **str_values = NULL;
156 smb_ucs2_t *cur_str = (smb_ucs2_t *) value->data_p;
157 uint32 size = 0, num_vals = 0, i=0;
160 if (value->type != REG_MULTI_SZ)
163 while(cur_str && *cur_str && (size < value->size)) {
164 size += 2 * (strlen_w(cur_str) + 1);
165 cur_str += strlen_w(cur_str) + 1;
170 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
174 memset(str_values, '\0',
175 (num_vals + 1) * sizeof(char *));
177 cur_str = (smb_ucs2_t *) value->data_p;
178 for (i=0; i < num_vals; i++)
179 cur_str += pull_ucs2_talloc(ctx, &str_values[i],
182 status = ads_mod_strlist(ctx, mods, value->valuename,
183 (const char **) str_values);
184 return ADS_ERR_OK(status);
189 struct valmap_to_ads {
191 BOOL (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *);
195 map a REG_SZ to an ldap mod
197 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
198 REGISTRY_VALUE *value)
200 const struct valmap_to_ads map[] = {
201 {SPOOL_REG_ASSETNUMBER, map_sz},
202 {SPOOL_REG_BYTESPERMINUTE, map_dword},
203 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
204 {SPOOL_REG_DESCRIPTION, map_sz},
205 {SPOOL_REG_DRIVERNAME, map_sz},
206 {SPOOL_REG_DRIVERVERSION, map_dword},
207 {SPOOL_REG_FLAGS, map_dword},
208 {SPOOL_REG_LOCATION, map_sz},
209 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
210 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
211 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
212 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
213 {SPOOL_REG_PORTNAME, map_multi_sz},
214 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
215 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
216 {SPOOL_REG_PRINTCOLLATE, map_bool},
217 {SPOOL_REG_PRINTCOLOR, map_bool},
218 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
219 {SPOOL_REG_PRINTENDTIME, map_dword},
220 {SPOOL_REG_PRINTFORMNAME, map_sz},
221 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
222 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
223 {SPOOL_REG_PRINTMACADDRESS, map_sz},
224 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
225 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
226 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
227 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
228 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
229 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
230 {SPOOL_REG_PRINTMEMORY, map_dword},
231 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
232 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
233 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
234 {SPOOL_REG_PRINTNOTIFY, map_sz},
235 {SPOOL_REG_PRINTNUMBERUP, map_dword},
236 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
237 {SPOOL_REG_PRINTOWNER, map_sz},
238 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
239 {SPOOL_REG_PRINTRATE, map_dword},
240 {SPOOL_REG_PRINTRATEUNIT, map_sz},
241 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
242 {SPOOL_REG_PRINTSHARENAME, map_sz},
243 {SPOOL_REG_PRINTSPOOLING, map_sz},
244 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
245 {SPOOL_REG_PRINTSTARTTIME, map_dword},
246 {SPOOL_REG_PRINTSTATUS, map_sz},
247 {SPOOL_REG_PRIORITY, map_dword},
248 {SPOOL_REG_SERVERNAME, map_sz},
249 {SPOOL_REG_SHORTSERVERNAME, map_sz},
250 {SPOOL_REG_UNCNAME, map_sz},
251 {SPOOL_REG_URL, map_sz},
252 {SPOOL_REG_VERSIONNUMBER, map_dword},
257 for (i=0; map[i].valname; i++) {
258 if (StrCaseCmp(map[i].valname, value->valuename) == 0) {
259 if (!map[i].fn(ctx, mods, value)) {
260 DEBUG(5, ("Add of value %s to modlist failed\n", value->valuename));
262 DEBUG(7, ("Mapped value %s\n", value->valuename));
270 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli,
276 char *printername, *servername;
277 REGVAL_CTR *dsdriver_ctr, *dsspooler_ctr;
281 asprintf(&servername, "\\\\%s", cli->cli->desthost);
282 asprintf(&printername, "%s\\%s", servername, printer);
283 if (!servername || !printername) {
284 DEBUG(3, ("Insufficient memory\n"));
288 result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername,
289 "", MAXIMUM_ALLOWED_ACCESS,
290 servername, cli->cli->user_name, &pol);
291 if (!W_ERROR_IS_OK(result)) {
292 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
293 printername, dos_errstr(result)));
297 if ( !(dsdriver_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
300 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSDRIVER_KEY, dsdriver_ctr);
302 if (!W_ERROR_IS_OK(result)) {
303 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
304 printername, dos_errstr(result)));
306 uint32 num_values = regval_ctr_numvals( dsdriver_ctr );
308 /* Have the data we need now, so start building */
309 for (i=0; i < num_values; i++) {
310 map_regval_to_ads(mem_ctx, mods, dsdriver_ctr->values[i]);
314 if ( !(dsspooler_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) )
317 result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSSPOOLER_KEY, dsspooler_ctr);
319 if (!W_ERROR_IS_OK(result)) {
320 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
321 printername, dos_errstr(result)));
323 uint32 num_values = regval_ctr_numvals( dsspooler_ctr );
325 for (i=0; i<num_values; i++) {
326 map_regval_to_ads(mem_ctx, mods, dsspooler_ctr->values[i]);
330 ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
332 TALLOC_FREE( dsdriver_ctr );
333 TALLOC_FREE( dsspooler_ctr );
335 rpccli_spoolss_close_printer(cli, mem_ctx, &pol);
340 BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
342 NT_PRINTER_DATA *data)
346 for (key=0; key < data->num_keys; key++) {
347 REGVAL_CTR *ctr = data->keys[key].values;
348 for (val=0; val < ctr->num_values; val++)
349 map_regval_to_ads(mem_ctx, mods, ctr->values[val]);