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"
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
= NULL
;
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) {
46 ads_msgfree(ads
, *res
);
49 return ADS_ERROR(LDAP_NO_SUCH_OBJECT
);
51 srv_dn
= ldap_get_dn(ads
->ldap
.ld
, *res
);
54 ads_msgfree(ads
, *res
);
57 return ADS_ERROR(LDAP_NO_MEMORY
);
59 srv_cn
= ldap_explode_dn(srv_dn
, 1);
63 ads_msgfree(ads
, *res
);
66 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX
);
69 ads_msgfree(ads
, *res
);
73 if (asprintf(&s
, "(cn=%s-%s)", srv_cn
[0], printer
) == -1) {
75 return ADS_ERROR(LDAP_NO_MEMORY
);
77 status
= ads_search(ads
, res
, s
, attrs
);
80 ldap_value_free(srv_cn
);
85 ADS_STATUS
ads_find_printers(ADS_STRUCT
*ads
, LDAPMessage
**res
)
87 const char *ldap_expr
;
88 const char *attrs
[] = { "objectClass", "printerName", "location", "driverName",
89 "serverName", "description", NULL
};
91 /* For the moment only display all printers */
93 ldap_expr
= "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
94 "(objectCategory=printQueue))";
96 return ads_search(ads
, res
, ldap_expr
, attrs
);
100 modify a printer entry in the directory
102 ADS_STATUS
ads_mod_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
103 TALLOC_CTX
*ctx
, const ADS_MODLIST
*mods
)
105 return ads_gen_mod(ads
, prt_dn
, *mods
);
109 add a printer to the directory
111 ADS_STATUS
ads_add_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
112 TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
)
114 ads_mod_str(ctx
, mods
, "objectClass", "printQueue");
115 return ads_gen_add(ads
, prt_dn
, *mods
);
119 map a REG_SZ to an ldap mod
121 static bool map_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
122 const struct regval_blob
*value
)
124 char *str_value
= NULL
;
125 size_t converted_size
;
128 if (value
->type
!= REG_SZ
)
131 if (value
->size
&& *((smb_ucs2_t
*) value
->data_p
)) {
132 if (!pull_ucs2_talloc(ctx
, &str_value
,
133 (const smb_ucs2_t
*) value
->data_p
,
138 status
= ads_mod_str(ctx
, mods
, value
->valuename
, str_value
);
139 return ADS_ERR_OK(status
);
146 map a REG_DWORD to an ldap mod
148 static bool map_dword(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
149 const struct regval_blob
*value
)
151 char *str_value
= NULL
;
154 if (value
->type
!= REG_DWORD
)
156 str_value
= talloc_asprintf(ctx
, "%d", *((uint32
*) value
->data_p
));
160 status
= ads_mod_str(ctx
, mods
, value
->valuename
, str_value
);
161 return ADS_ERR_OK(status
);
165 map a boolean REG_BINARY to an ldap mod
167 static bool map_bool(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
168 const struct regval_blob
*value
)
173 if ((value
->type
!= REG_BINARY
) || (value
->size
!= 1))
175 str_value
= talloc_asprintf(ctx
, "%s",
176 *(value
->data_p
) ? "TRUE" : "FALSE");
180 status
= ads_mod_str(ctx
, mods
, value
->valuename
, str_value
);
181 return ADS_ERR_OK(status
);
185 map a REG_MULTI_SZ to an ldap mod
187 static bool map_multi_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
188 const struct regval_blob
*value
)
190 char **str_values
= NULL
;
191 size_t converted_size
;
192 smb_ucs2_t
*cur_str
= (smb_ucs2_t
*) value
->data_p
;
193 uint32 size
= 0, num_vals
= 0, i
=0;
196 if (value
->type
!= REG_MULTI_SZ
)
199 while(cur_str
&& *cur_str
&& (size
< value
->size
)) {
200 size
+= 2 * (strlen_w(cur_str
) + 1);
201 cur_str
+= strlen_w(cur_str
) + 1;
206 str_values
= TALLOC_ARRAY(ctx
, char *, num_vals
+ 1);
210 memset(str_values
, '\0',
211 (num_vals
+ 1) * sizeof(char *));
213 cur_str
= (smb_ucs2_t
*) value
->data_p
;
214 for (i
=0; i
< num_vals
; i
++) {
215 cur_str
+= pull_ucs2_talloc(ctx
, &str_values
[i
],
216 cur_str
, &converted_size
) ?
217 converted_size
: (size_t)-1;
220 status
= ads_mod_strlist(ctx
, mods
, value
->valuename
,
221 (const char **) str_values
);
222 return ADS_ERR_OK(status
);
227 struct valmap_to_ads
{
229 bool (*fn
)(TALLOC_CTX
*, ADS_MODLIST
*, const struct regval_blob
*);
233 map a REG_SZ to an ldap mod
235 static void map_regval_to_ads(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
236 struct regval_blob
*value
)
238 const struct valmap_to_ads map
[] = {
239 {SPOOL_REG_ASSETNUMBER
, map_sz
},
240 {SPOOL_REG_BYTESPERMINUTE
, map_dword
},
241 {SPOOL_REG_DEFAULTPRIORITY
, map_dword
},
242 {SPOOL_REG_DESCRIPTION
, map_sz
},
243 {SPOOL_REG_DRIVERNAME
, map_sz
},
244 {SPOOL_REG_DRIVERVERSION
, map_dword
},
245 {SPOOL_REG_FLAGS
, map_dword
},
246 {SPOOL_REG_LOCATION
, map_sz
},
247 {SPOOL_REG_OPERATINGSYSTEM
, map_sz
},
248 {SPOOL_REG_OPERATINGSYSTEMHOTFIX
, map_sz
},
249 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK
, map_sz
},
250 {SPOOL_REG_OPERATINGSYSTEMVERSION
, map_sz
},
251 {SPOOL_REG_PORTNAME
, map_multi_sz
},
252 {SPOOL_REG_PRINTATTRIBUTES
, map_dword
},
253 {SPOOL_REG_PRINTBINNAMES
, map_multi_sz
},
254 {SPOOL_REG_PRINTCOLLATE
, map_bool
},
255 {SPOOL_REG_PRINTCOLOR
, map_bool
},
256 {SPOOL_REG_PRINTDUPLEXSUPPORTED
, map_bool
},
257 {SPOOL_REG_PRINTENDTIME
, map_dword
},
258 {SPOOL_REG_PRINTFORMNAME
, map_sz
},
259 {SPOOL_REG_PRINTKEEPPRINTEDJOBS
, map_bool
},
260 {SPOOL_REG_PRINTLANGUAGE
, map_multi_sz
},
261 {SPOOL_REG_PRINTMACADDRESS
, map_sz
},
262 {SPOOL_REG_PRINTMAXCOPIES
, map_sz
},
263 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED
, map_dword
},
264 {SPOOL_REG_PRINTMAXXEXTENT
, map_dword
},
265 {SPOOL_REG_PRINTMAXYEXTENT
, map_dword
},
266 {SPOOL_REG_PRINTMEDIAREADY
, map_multi_sz
},
267 {SPOOL_REG_PRINTMEDIASUPPORTED
, map_multi_sz
},
268 {SPOOL_REG_PRINTMEMORY
, map_dword
},
269 {SPOOL_REG_PRINTMINXEXTENT
, map_dword
},
270 {SPOOL_REG_PRINTMINYEXTENT
, map_dword
},
271 {SPOOL_REG_PRINTNETWORKADDRESS
, map_sz
},
272 {SPOOL_REG_PRINTNOTIFY
, map_sz
},
273 {SPOOL_REG_PRINTNUMBERUP
, map_dword
},
274 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED
, map_multi_sz
},
275 {SPOOL_REG_PRINTOWNER
, map_sz
},
276 {SPOOL_REG_PRINTPAGESPERMINUTE
, map_dword
},
277 {SPOOL_REG_PRINTRATE
, map_dword
},
278 {SPOOL_REG_PRINTRATEUNIT
, map_sz
},
279 {SPOOL_REG_PRINTSEPARATORFILE
, map_sz
},
280 {SPOOL_REG_PRINTSHARENAME
, map_sz
},
281 {SPOOL_REG_PRINTSPOOLING
, map_sz
},
282 {SPOOL_REG_PRINTSTAPLINGSUPPORTED
, map_bool
},
283 {SPOOL_REG_PRINTSTARTTIME
, map_dword
},
284 {SPOOL_REG_PRINTSTATUS
, map_sz
},
285 {SPOOL_REG_PRIORITY
, map_dword
},
286 {SPOOL_REG_SERVERNAME
, map_sz
},
287 {SPOOL_REG_SHORTSERVERNAME
, map_sz
},
288 {SPOOL_REG_UNCNAME
, map_sz
},
289 {SPOOL_REG_URL
, map_sz
},
290 {SPOOL_REG_VERSIONNUMBER
, map_dword
},
295 for (i
=0; map
[i
].valname
; i
++) {
296 if (StrCaseCmp(map
[i
].valname
, value
->valuename
) == 0) {
297 if (!map
[i
].fn(ctx
, mods
, value
)) {
298 DEBUG(5, ("Add of value %s to modlist failed\n", value
->valuename
));
300 DEBUG(7, ("Mapped value %s\n", value
->valuename
));
308 WERROR
get_remote_printer_publishing_data(struct rpc_pipe_client
*cli
,
315 struct spoolss_PrinterEnumValues
*info
;
318 struct policy_handle pol
;
320 if ((asprintf(&printername
, "%s\\%s", cli
->srv_name_slash
, printer
) == -1)) {
321 DEBUG(3, ("Insufficient memory\n"));
325 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
327 SEC_FLAG_MAXIMUM_ALLOWED
,
329 if (!W_ERROR_IS_OK(result
)) {
330 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
331 printername
, win_errstr(result
)));
332 SAFE_FREE(printername
);
336 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
342 if (!W_ERROR_IS_OK(result
)) {
343 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
344 printername
, win_errstr(result
)));
346 /* Have the data we need now, so start building */
347 for (i
=0; i
< count
; i
++) {
348 struct regval_blob v
;
351 result
= push_spoolss_PrinterData(mem_ctx
, &blob
,
354 if (W_ERROR_IS_OK(result
)) {
355 fstrcpy(v
.valuename
, info
[i
].value_name
);
356 v
.type
= info
[i
].type
;
357 v
.data_p
= blob
.data
;
358 v
.size
= blob
.length
;
360 map_regval_to_ads(mem_ctx
, mods
, &v
);
365 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
370 if (!W_ERROR_IS_OK(result
)) {
371 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
372 printername
, win_errstr(result
)));
374 for (i
=0; i
< count
; i
++) {
375 struct regval_blob v
;
376 DATA_BLOB blob
= data_blob_null
;
378 result
= push_spoolss_PrinterData(mem_ctx
, &blob
,
381 if (W_ERROR_IS_OK(result
)) {
382 fstrcpy(v
.valuename
, info
[i
].value_name
);
383 v
.type
= info
[i
].type
;
384 v
.data_p
= blob
.data
;
385 v
.size
= blob
.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 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
< ctr
->num_values
; val
++)
409 map_regval_to_ads(mem_ctx
, mods
, ctr
->values
[val
]);