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/>.
25 find a printer given the name and the hostname
26 Note that results "res" may be allocated on return so that the
27 results can be used. It should be freed using ads_msgfree.
29 ADS_STATUS
ads_find_printer_on_server(ADS_STRUCT
*ads
, LDAPMessage
**res
,
31 const char *servername
)
34 char *srv_dn
, **srv_cn
, *s
= NULL
;
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 if (ads_count_replies(ads
, *res
) != 1) {
45 ads_msgfree(ads
, *res
);
48 return ADS_ERROR(LDAP_NO_SUCH_OBJECT
);
50 srv_dn
= ldap_get_dn(ads
->ldap
.ld
, *res
);
53 ads_msgfree(ads
, *res
);
56 return ADS_ERROR(LDAP_NO_MEMORY
);
58 srv_cn
= ldap_explode_dn(srv_dn
, 1);
62 ads_msgfree(ads
, *res
);
65 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX
);
68 ads_msgfree(ads
, *res
);
72 if (asprintf(&s
, "(cn=%s-%s)", srv_cn
[0], printer
) == -1) {
74 return ADS_ERROR(LDAP_NO_MEMORY
);
76 status
= ads_search(ads
, res
, s
, attrs
);
79 ldap_value_free(srv_cn
);
84 ADS_STATUS
ads_find_printers(ADS_STRUCT
*ads
, LDAPMessage
**res
)
86 const char *ldap_expr
;
87 const char *attrs
[] = { "objectClass", "printerName", "location", "driverName",
88 "serverName", "description", NULL
};
90 /* For the moment only display all printers */
92 ldap_expr
= "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
93 "(objectCategory=printQueue))";
95 return ads_search(ads
, res
, ldap_expr
, attrs
);
99 modify a printer entry in the directory
101 ADS_STATUS
ads_mod_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
102 TALLOC_CTX
*ctx
, const ADS_MODLIST
*mods
)
104 return ads_gen_mod(ads
, prt_dn
, *mods
);
108 add a printer to the directory
110 ADS_STATUS
ads_add_printer_entry(ADS_STRUCT
*ads
, char *prt_dn
,
111 TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
)
113 ads_mod_str(ctx
, mods
, "objectClass", "printQueue");
114 return ads_gen_add(ads
, prt_dn
, *mods
);
118 map a REG_SZ to an ldap mod
120 static bool map_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
121 const REGISTRY_VALUE
*value
)
123 char *str_value
= NULL
;
124 size_t converted_size
;
127 if (value
->type
!= REG_SZ
)
130 if (value
->size
&& *((smb_ucs2_t
*) value
->data_p
)) {
131 if (!pull_ucs2_talloc(ctx
, &str_value
,
132 (const smb_ucs2_t
*) value
->data_p
,
137 status
= ads_mod_str(ctx
, mods
, value
->valuename
, str_value
);
138 return ADS_ERR_OK(status
);
145 map a REG_DWORD to an ldap mod
147 static bool map_dword(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
148 const REGISTRY_VALUE
*value
)
150 char *str_value
= NULL
;
153 if (value
->type
!= REG_DWORD
)
155 str_value
= talloc_asprintf(ctx
, "%d", *((uint32
*) value
->data_p
));
159 status
= ads_mod_str(ctx
, mods
, value
->valuename
, str_value
);
160 return ADS_ERR_OK(status
);
164 map a boolean REG_BINARY to an ldap mod
166 static bool map_bool(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
167 const REGISTRY_VALUE
*value
)
172 if ((value
->type
!= REG_BINARY
) || (value
->size
!= 1))
174 str_value
= talloc_asprintf(ctx
, "%s",
175 *(value
->data_p
) ? "TRUE" : "FALSE");
179 status
= ads_mod_str(ctx
, mods
, value
->valuename
, str_value
);
180 return ADS_ERR_OK(status
);
184 map a REG_MULTI_SZ to an ldap mod
186 static bool map_multi_sz(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
187 const REGISTRY_VALUE
*value
)
189 char **str_values
= NULL
;
190 size_t converted_size
;
191 smb_ucs2_t
*cur_str
= (smb_ucs2_t
*) value
->data_p
;
192 uint32 size
= 0, num_vals
= 0, i
=0;
195 if (value
->type
!= REG_MULTI_SZ
)
198 while(cur_str
&& *cur_str
&& (size
< value
->size
)) {
199 size
+= 2 * (strlen_w(cur_str
) + 1);
200 cur_str
+= strlen_w(cur_str
) + 1;
205 str_values
= TALLOC_ARRAY(ctx
, char *, num_vals
+ 1);
209 memset(str_values
, '\0',
210 (num_vals
+ 1) * sizeof(char *));
212 cur_str
= (smb_ucs2_t
*) value
->data_p
;
213 for (i
=0; i
< num_vals
; i
++) {
214 cur_str
+= pull_ucs2_talloc(ctx
, &str_values
[i
],
215 cur_str
, &converted_size
) ?
216 converted_size
: (size_t)-1;
219 status
= ads_mod_strlist(ctx
, mods
, value
->valuename
,
220 (const char **) str_values
);
221 return ADS_ERR_OK(status
);
226 struct valmap_to_ads
{
228 bool (*fn
)(TALLOC_CTX
*, ADS_MODLIST
*, const REGISTRY_VALUE
*);
232 map a REG_SZ to an ldap mod
234 static void map_regval_to_ads(TALLOC_CTX
*ctx
, ADS_MODLIST
*mods
,
235 REGISTRY_VALUE
*value
)
237 const struct valmap_to_ads map
[] = {
238 {SPOOL_REG_ASSETNUMBER
, map_sz
},
239 {SPOOL_REG_BYTESPERMINUTE
, map_dword
},
240 {SPOOL_REG_DEFAULTPRIORITY
, map_dword
},
241 {SPOOL_REG_DESCRIPTION
, map_sz
},
242 {SPOOL_REG_DRIVERNAME
, map_sz
},
243 {SPOOL_REG_DRIVERVERSION
, map_dword
},
244 {SPOOL_REG_FLAGS
, map_dword
},
245 {SPOOL_REG_LOCATION
, map_sz
},
246 {SPOOL_REG_OPERATINGSYSTEM
, map_sz
},
247 {SPOOL_REG_OPERATINGSYSTEMHOTFIX
, map_sz
},
248 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK
, map_sz
},
249 {SPOOL_REG_OPERATINGSYSTEMVERSION
, map_sz
},
250 {SPOOL_REG_PORTNAME
, map_multi_sz
},
251 {SPOOL_REG_PRINTATTRIBUTES
, map_dword
},
252 {SPOOL_REG_PRINTBINNAMES
, map_multi_sz
},
253 {SPOOL_REG_PRINTCOLLATE
, map_bool
},
254 {SPOOL_REG_PRINTCOLOR
, map_bool
},
255 {SPOOL_REG_PRINTDUPLEXSUPPORTED
, map_bool
},
256 {SPOOL_REG_PRINTENDTIME
, map_dword
},
257 {SPOOL_REG_PRINTFORMNAME
, map_sz
},
258 {SPOOL_REG_PRINTKEEPPRINTEDJOBS
, map_bool
},
259 {SPOOL_REG_PRINTLANGUAGE
, map_multi_sz
},
260 {SPOOL_REG_PRINTMACADDRESS
, map_sz
},
261 {SPOOL_REG_PRINTMAXCOPIES
, map_sz
},
262 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED
, map_dword
},
263 {SPOOL_REG_PRINTMAXXEXTENT
, map_dword
},
264 {SPOOL_REG_PRINTMAXYEXTENT
, map_dword
},
265 {SPOOL_REG_PRINTMEDIAREADY
, map_multi_sz
},
266 {SPOOL_REG_PRINTMEDIASUPPORTED
, map_multi_sz
},
267 {SPOOL_REG_PRINTMEMORY
, map_dword
},
268 {SPOOL_REG_PRINTMINXEXTENT
, map_dword
},
269 {SPOOL_REG_PRINTMINYEXTENT
, map_dword
},
270 {SPOOL_REG_PRINTNETWORKADDRESS
, map_sz
},
271 {SPOOL_REG_PRINTNOTIFY
, map_sz
},
272 {SPOOL_REG_PRINTNUMBERUP
, map_dword
},
273 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED
, map_multi_sz
},
274 {SPOOL_REG_PRINTOWNER
, map_sz
},
275 {SPOOL_REG_PRINTPAGESPERMINUTE
, map_dword
},
276 {SPOOL_REG_PRINTRATE
, map_dword
},
277 {SPOOL_REG_PRINTRATEUNIT
, map_sz
},
278 {SPOOL_REG_PRINTSEPARATORFILE
, map_sz
},
279 {SPOOL_REG_PRINTSHARENAME
, map_sz
},
280 {SPOOL_REG_PRINTSPOOLING
, map_sz
},
281 {SPOOL_REG_PRINTSTAPLINGSUPPORTED
, map_bool
},
282 {SPOOL_REG_PRINTSTARTTIME
, map_dword
},
283 {SPOOL_REG_PRINTSTATUS
, map_sz
},
284 {SPOOL_REG_PRIORITY
, map_dword
},
285 {SPOOL_REG_SERVERNAME
, map_sz
},
286 {SPOOL_REG_SHORTSERVERNAME
, map_sz
},
287 {SPOOL_REG_UNCNAME
, map_sz
},
288 {SPOOL_REG_URL
, map_sz
},
289 {SPOOL_REG_VERSIONNUMBER
, map_dword
},
294 for (i
=0; map
[i
].valname
; i
++) {
295 if (StrCaseCmp(map
[i
].valname
, value
->valuename
) == 0) {
296 if (!map
[i
].fn(ctx
, mods
, value
)) {
297 DEBUG(5, ("Add of value %s to modlist failed\n", value
->valuename
));
299 DEBUG(7, ("Mapped value %s\n", value
->valuename
));
307 WERROR
get_remote_printer_publishing_data(struct rpc_pipe_client
*cli
,
314 struct spoolss_PrinterEnumValues
*info
;
319 if ((asprintf(&printername
, "%s\\%s", cli
->srv_name_slash
, printer
) == -1)) {
320 DEBUG(3, ("Insufficient memory\n"));
324 result
= rpccli_spoolss_openprinter_ex(cli
, mem_ctx
,
326 SEC_FLAG_MAXIMUM_ALLOWED
,
328 if (!W_ERROR_IS_OK(result
)) {
329 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
330 printername
, win_errstr(result
)));
331 SAFE_FREE(printername
);
335 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
341 if (!W_ERROR_IS_OK(result
)) {
342 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
343 printername
, win_errstr(result
)));
345 /* Have the data we need now, so start building */
346 for (i
=0; i
< count
; i
++) {
350 result
= push_spoolss_PrinterData(mem_ctx
, &blob
,
353 if (W_ERROR_IS_OK(result
)) {
354 fstrcpy(v
.valuename
, info
[i
].value_name
);
355 v
.type
= info
[i
].type
;
356 v
.data_p
= blob
.data
;
357 v
.size
= blob
.length
;
359 map_regval_to_ads(mem_ctx
, mods
, &v
);
364 result
= rpccli_spoolss_enumprinterdataex(cli
, mem_ctx
, &pol
,
369 if (!W_ERROR_IS_OK(result
)) {
370 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
371 printername
, win_errstr(result
)));
373 for (i
=0; i
< count
; i
++) {
377 result
= push_spoolss_PrinterData(mem_ctx
, &blob
,
380 if (W_ERROR_IS_OK(result
)) {
381 fstrcpy(v
.valuename
, info
[i
].value_name
);
382 v
.type
= info
[i
].type
;
383 v
.data_p
= blob
.data
;
384 v
.size
= blob
.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 REGVAL_CTR
*ctr
= data
->keys
[key
].values
;
407 for (val
=0; val
< ctr
->num_values
; val
++)
408 map_regval_to_ads(mem_ctx
, mods
, ctr
->values
[val
]);