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
));
122 status
= ads_mod_str(ctx
, mods
, value
->valuename
, str_value
);
123 return ADS_ERR_OK(status
);
127 map a boolean REG_BINARY to an ldap mod
129 static BOOL
map_bool(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
130 const REGISTRY_VALUE
*value
)
135 if ((value
->type
!= REG_BINARY
) || (value
->size
!= 1))
137 str_value
= talloc_asprintf(ctx
, "%s",
138 *(value
->data_p
) ? "TRUE" : "FALSE");
139 status
= ads_mod_str(ctx
, mods
, value
->valuename
, str_value
);
140 return ADS_ERR_OK(status
);
144 map a REG_MULTI_SZ to an ldap mod
146 static BOOL
map_multi_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
147 const REGISTRY_VALUE
*value
)
149 char **str_values
= NULL
;
150 smb_ucs2_t
*cur_str
= (smb_ucs2_t
*) value
->data_p
;
151 uint32 size
= 0, num_vals
= 0, i
=0;
154 if (value
->type
!= REG_MULTI_SZ
)
157 while(cur_str
&& *cur_str
&& (size
< value
->size
)) {
158 size
+= 2 * (strlen_w(cur_str
) + 1);
159 cur_str
+= strlen_w(cur_str
) + 1;
164 str_values
= TALLOC_ARRAY(ctx
, char *, num_vals
+ 1);
165 memset(str_values
, '\0',
166 (num_vals
+ 1) * sizeof(char *));
168 cur_str
= (smb_ucs2_t
*) value
->data_p
;
169 for (i
=0; i
< num_vals
; i
++)
170 cur_str
+= pull_ucs2_talloc(ctx
, &str_values
[i
],
173 status
= ads_mod_strlist(ctx
, mods
, value
->valuename
,
174 (const char **) str_values
);
175 return ADS_ERR_OK(status
);
180 struct valmap_to_ads
{
182 BOOL (*fn
)(TALLOC_CTX
*, ADS_MODLIST
*, const REGISTRY_VALUE
*);
186 map a REG_SZ to an ldap mod
188 static void map_regval_to_ads(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
189 REGISTRY_VALUE
*value
)
191 const struct valmap_to_ads map
[] = {
192 {SPOOL_REG_ASSETNUMBER
, map_sz
},
193 {SPOOL_REG_BYTESPERMINUTE
, map_dword
},
194 {SPOOL_REG_DEFAULTPRIORITY
, map_dword
},
195 {SPOOL_REG_DESCRIPTION
, map_sz
},
196 {SPOOL_REG_DRIVERNAME
, map_sz
},
197 {SPOOL_REG_DRIVERVERSION
, map_dword
},
198 {SPOOL_REG_FLAGS
, map_dword
},
199 {SPOOL_REG_LOCATION
, map_sz
},
200 {SPOOL_REG_OPERATINGSYSTEM
, map_sz
},
201 {SPOOL_REG_OPERATINGSYSTEMHOTFIX
, map_sz
},
202 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK
, map_sz
},
203 {SPOOL_REG_OPERATINGSYSTEMVERSION
, map_sz
},
204 {SPOOL_REG_PORTNAME
, map_multi_sz
},
205 {SPOOL_REG_PRINTATTRIBUTES
, map_dword
},
206 {SPOOL_REG_PRINTBINNAMES
, map_multi_sz
},
207 {SPOOL_REG_PRINTCOLLATE
, map_bool
},
208 {SPOOL_REG_PRINTCOLOR
, map_bool
},
209 {SPOOL_REG_PRINTDUPLEXSUPPORTED
, map_bool
},
210 {SPOOL_REG_PRINTENDTIME
, map_dword
},
211 {SPOOL_REG_PRINTFORMNAME
, map_sz
},
212 {SPOOL_REG_PRINTKEEPPRINTEDJOBS
, map_bool
},
213 {SPOOL_REG_PRINTLANGUAGE
, map_multi_sz
},
214 {SPOOL_REG_PRINTMACADDRESS
, map_sz
},
215 {SPOOL_REG_PRINTMAXCOPIES
, map_sz
},
216 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED
, map_dword
},
217 {SPOOL_REG_PRINTMAXXEXTENT
, map_dword
},
218 {SPOOL_REG_PRINTMAXYEXTENT
, map_dword
},
219 {SPOOL_REG_PRINTMEDIAREADY
, map_multi_sz
},
220 {SPOOL_REG_PRINTMEDIASUPPORTED
, map_multi_sz
},
221 {SPOOL_REG_PRINTMEMORY
, map_dword
},
222 {SPOOL_REG_PRINTMINXEXTENT
, map_dword
},
223 {SPOOL_REG_PRINTMINYEXTENT
, map_dword
},
224 {SPOOL_REG_PRINTNETWORKADDRESS
, map_sz
},
225 {SPOOL_REG_PRINTNOTIFY
, map_sz
},
226 {SPOOL_REG_PRINTNUMBERUP
, map_dword
},
227 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED
, map_multi_sz
},
228 {SPOOL_REG_PRINTOWNER
, map_sz
},
229 {SPOOL_REG_PRINTPAGESPERMINUTE
, map_dword
},
230 {SPOOL_REG_PRINTRATE
, map_dword
},
231 {SPOOL_REG_PRINTRATEUNIT
, map_sz
},
232 {SPOOL_REG_PRINTSEPARATORFILE
, map_sz
},
233 {SPOOL_REG_PRINTSHARENAME
, map_sz
},
234 {SPOOL_REG_PRINTSPOOLING
, map_sz
},
235 {SPOOL_REG_PRINTSTAPLINGSUPPORTED
, map_bool
},
236 {SPOOL_REG_PRINTSTARTTIME
, map_dword
},
237 {SPOOL_REG_PRINTSTATUS
, map_sz
},
238 {SPOOL_REG_PRIORITY
, map_dword
},
239 {SPOOL_REG_SERVERNAME
, map_sz
},
240 {SPOOL_REG_SHORTSERVERNAME
, map_sz
},
241 {SPOOL_REG_UNCNAME
, map_sz
},
242 {SPOOL_REG_URL
, map_sz
},
243 {SPOOL_REG_VERSIONNUMBER
, map_dword
},
248 for (i
=0; map
[i
].valname
; i
++) {
249 if (StrCaseCmp(map
[i
].valname
, value
->valuename
) == 0) {
250 if (!map
[i
].fn(ctx
, mods
, value
)) {
251 DEBUG(5, ("Add of value %s to modlist failed\n", value
->valuename
));
253 DEBUG(7, ("Mapped value %s\n", value
->valuename
));
261 WERROR
get_remote_printer_publishing_data(struct rpc_pipe_client
*cli
,
267 char *printername
, *servername
;
268 REGVAL_CTR
*dsdriver_ctr
, *dsspooler_ctr
;
272 asprintf(&servername
, "\\\\%s", cli
->cli
->desthost
);
273 asprintf(&printername
, "%s\\%s", servername
, printer
);
274 if (!servername
|| !printername
) {
275 DEBUG(3, ("Insufficient memory\n"));
279 result
= rpccli_spoolss_open_printer_ex(cli
, mem_ctx
, printername
,
280 "", MAXIMUM_ALLOWED_ACCESS
,
281 servername
, cli
->cli
->user_name
, &pol
);
282 if (!W_ERROR_IS_OK(result
)) {
283 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
284 printername
, dos_errstr(result
)));
288 if ( !(dsdriver_ctr
= TALLOC_ZERO_P( mem_ctx
, REGVAL_CTR
)) )
291 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
, SPOOL_DSDRIVER_KEY
, dsdriver_ctr
);
293 if (!W_ERROR_IS_OK(result
)) {
294 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
295 printername
, dos_errstr(result
)));
297 uint32 num_values
= regval_ctr_numvals( dsdriver_ctr
);
299 /* Have the data we need now, so start building */
300 for (i
=0; i
< num_values
; i
++) {
301 map_regval_to_ads(mem_ctx
, mods
, dsdriver_ctr
->values
[i
]);
305 if ( !(dsspooler_ctr
= TALLOC_ZERO_P( mem_ctx
, REGVAL_CTR
)) )
308 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
, SPOOL_DSSPOOLER_KEY
, dsspooler_ctr
);
310 if (!W_ERROR_IS_OK(result
)) {
311 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
312 printername
, dos_errstr(result
)));
314 uint32 num_values
= regval_ctr_numvals( dsspooler_ctr
);
316 for (i
=0; i
<num_values
; i
++) {
317 map_regval_to_ads(mem_ctx
, mods
, dsspooler_ctr
->values
[i
]);
321 ads_mod_str(mem_ctx
, mods
, SPOOL_REG_PRINTERNAME
, printer
);
323 TALLOC_FREE( dsdriver_ctr
);
324 TALLOC_FREE( dsspooler_ctr
);
326 rpccli_spoolss_close_printer(cli
, mem_ctx
, &pol
);
331 BOOL
get_local_printer_publishing_data(TALLOC_CTX
*mem_ctx
,
333 NT_PRINTER_DATA
*data
)
337 for (key
=0; key
< data
->num_keys
; key
++) {
338 REGVAL_CTR
*ctr
= data
->keys
[key
].values
;
339 for (val
=0; val
< ctr
->num_values
; val
++)
340 map_regval_to_ads(mem_ctx
, mods
, ctr
->values
[val
]);