This commit was generated by cvs2svn to compensate for changes in r30,
[samba.git] / source4 / libads / ldap_printer.c
1 /* 
2    Unix SMB/CIFS implementation.
3    ads (active directory) printer utility library
4    Copyright (C) Jim McDonough 2002
5    
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.
10    
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.
15    
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.
19 */
20
21 #include "includes.h"
22
23 #ifdef HAVE_ADS
24
25 /*
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.
29 */
30 ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, void **res,
31                                       const char *printer, const char *servername)
32 {
33         ADS_STATUS status;
34         char *srv_dn, **srv_cn, *exp;
35         const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
36
37         status = ads_find_machine_acct(ads, res, servername);
38         if (!ADS_ERR_OK(status)) {
39                 DEBUG(1, ("ads_add_printer: cannot find host %s in ads\n",
40                           servername));
41                 return status;
42         }
43         srv_dn = ldap_get_dn(ads->ld, *res);
44         srv_cn = ldap_explode_dn(srv_dn, 1);
45         ads_msgfree(ads, *res);
46
47         asprintf(&exp, "(cn=%s-%s)", srv_cn[0], printer);
48         status = ads_search(ads, res, exp, attrs);
49
50         ldap_memfree(srv_dn);
51         ldap_value_free(srv_cn);
52         free(exp);
53         return status;  
54 }
55
56 /*
57   modify a printer entry in the directory
58 */
59 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
60                                  TALLOC_CTX *ctx, const ADS_MODLIST *mods)
61 {
62         return ads_gen_mod(ads, prt_dn, *mods);
63 }
64
65 /*
66   add a printer to the directory
67 */
68 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
69                                         TALLOC_CTX *ctx, ADS_MODLIST *mods)
70 {
71         ads_mod_str(ctx, mods, "objectClass", "printQueue");
72         return ads_gen_add(ads, prt_dn, *mods);
73 }
74
75 /*
76   map a REG_SZ to an ldap mod
77 */
78 static BOOL map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
79                             const REGISTRY_VALUE *value)
80 {
81         char *str_value = NULL;
82         ADS_STATUS status;
83
84         if (value->type != REG_SZ)
85                 return False;
86
87         if (value->size && *((smb_ucs2_t *) value->data_p)) {
88                 pull_ucs2_talloc(ctx, &str_value, (const smb_ucs2_t *) value->data_p);
89                 status = ads_mod_str(ctx, mods, value->valuename, str_value);
90                 return ADS_ERR_OK(status);
91         }
92         return True;
93                 
94 }
95
96 /*
97   map a REG_DWORD to an ldap mod
98 */
99 static BOOL map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
100                       const REGISTRY_VALUE *value)
101 {
102         char *str_value = NULL;
103         ADS_STATUS status;
104
105         if (value->type != REG_DWORD)
106                 return False;
107         str_value = talloc_asprintf(ctx, "%d", *((uint32 *) value->data_p));
108         status = ads_mod_str(ctx, mods, value->valuename, str_value);
109         return ADS_ERR_OK(status);
110 }
111
112 /*
113   map a boolean REG_BINARY to an ldap mod
114 */
115 static BOOL map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
116                      const REGISTRY_VALUE *value)
117 {
118         char *str_value;
119         ADS_STATUS status;
120
121         if ((value->type != REG_BINARY) || (value->size != 1))
122                 return False;
123         str_value =  talloc_asprintf(ctx, "%s", 
124                                      *(value->data_p) ? "TRUE" : "FALSE");
125         status = ads_mod_str(ctx, mods, value->valuename, str_value);
126         return ADS_ERR_OK(status);
127 }
128
129 /*
130   map a REG_MULTI_SZ to an ldap mod
131 */
132 static BOOL map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
133                          const REGISTRY_VALUE *value)
134 {
135         char **str_values = NULL;
136         smb_ucs2_t *cur_str = (smb_ucs2_t *) value->data_p;
137         uint32 size = 0, num_vals = 0, i=0;
138         ADS_STATUS status;
139
140         if (value->type != REG_MULTI_SZ)
141                 return False;
142
143         while(cur_str && *cur_str && (size < value->size)) {            
144                 size += 2 * (strlen_w(cur_str) + 1);
145                 cur_str += strlen_w(cur_str) + 1;
146                 num_vals++;
147         };
148
149         if (num_vals) {
150                 str_values = talloc(ctx, 
151                                     (num_vals + 1) * sizeof(smb_ucs2_t *));
152                 memset(str_values, '\0', 
153                        (num_vals + 1) * sizeof(smb_ucs2_t *));
154
155                 cur_str = (smb_ucs2_t *) value->data_p;
156                 for (i=0; i < num_vals; i++)
157                         cur_str += pull_ucs2_talloc(ctx, &str_values[i],
158                                                     cur_str);
159
160                 status = ads_mod_strlist(ctx, mods, value->valuename, 
161                                          (const char **) str_values);
162                 return ADS_ERR_OK(status);
163         } 
164         return True;
165 }
166
167 struct valmap_to_ads {
168         const char *valname;
169         BOOL (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *);
170 };
171
172 /*
173   map a REG_SZ to an ldap mod
174 */
175 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
176                               REGISTRY_VALUE *value)
177 {
178         const struct valmap_to_ads map[] = {
179                 {SPOOL_REG_ASSETNUMBER, map_sz},
180                 {SPOOL_REG_BYTESPERMINUTE, map_dword},
181                 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
182                 {SPOOL_REG_DESCRIPTION, map_sz},
183                 {SPOOL_REG_DRIVERNAME, map_sz},
184                 {SPOOL_REG_DRIVERVERSION, map_dword},
185                 {SPOOL_REG_FLAGS, map_dword},
186                 {SPOOL_REG_LOCATION, map_sz},
187                 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
188                 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
189                 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
190                 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
191                 {SPOOL_REG_PORTNAME, map_multi_sz},
192                 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
193                 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
194                 {SPOOL_REG_PRINTCOLLATE, map_bool},
195                 {SPOOL_REG_PRINTCOLOR, map_bool},
196                 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
197                 {SPOOL_REG_PRINTENDTIME, map_dword},
198                 {SPOOL_REG_PRINTFORMNAME, map_sz},
199                 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
200                 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
201                 {SPOOL_REG_PRINTMACADDRESS, map_sz},
202                 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
203                 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
204                 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
205                 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
206                 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
207                 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
208                 {SPOOL_REG_PRINTMEMORY, map_dword},
209                 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
210                 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
211                 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
212                 {SPOOL_REG_PRINTNOTIFY, map_sz},
213                 {SPOOL_REG_PRINTNUMBERUP, map_dword},
214                 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
215                 {SPOOL_REG_PRINTOWNER, map_sz},
216                 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
217                 {SPOOL_REG_PRINTRATE, map_dword},
218                 {SPOOL_REG_PRINTRATEUNIT, map_sz},
219                 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
220                 {SPOOL_REG_PRINTSHARENAME, map_sz},
221                 {SPOOL_REG_PRINTSPOOLING, map_sz},
222                 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
223                 {SPOOL_REG_PRINTSTARTTIME, map_dword},
224                 {SPOOL_REG_PRINTSTATUS, map_sz},
225                 {SPOOL_REG_PRIORITY, map_dword},
226                 {SPOOL_REG_SERVERNAME, map_sz},
227                 {SPOOL_REG_SHORTSERVERNAME, map_sz},
228                 {SPOOL_REG_UNCNAME, map_sz},
229                 {SPOOL_REG_URL, map_sz},
230                 {SPOOL_REG_VERSIONNUMBER, map_dword},
231                 {NULL, NULL}
232         };
233         int i;
234
235         for (i=0; map[i].valname; i++) {
236                 if (StrCaseCmp(map[i].valname, value->valuename) == 0) {
237                         if (!map[i].fn(ctx, mods, value)) {
238                                 DEBUG(5, ("Add of value %s to modlist failed\n", value->valuename));
239                         } else {
240                                 DEBUG(7, ("Mapped value %s\n", value->valuename));
241                         }
242                         
243                 }
244         }
245 }
246
247
248 WERROR get_remote_printer_publishing_data(struct cli_state *cli, 
249                                           TALLOC_CTX *mem_ctx,
250                                           ADS_MODLIST *mods,
251                                           const char *printer)
252 {
253         WERROR result;
254         char *printername, *servername;
255         REGVAL_CTR dsdriver_ctr, dsspooler_ctr;
256         BOOL got_dsdriver = False, got_dsspooler = False;
257         uint32 needed, i;
258         POLICY_HND pol;
259
260         asprintf(&servername, "\\\\%s", cli->desthost);
261         asprintf(&printername, "%s\\%s", servername, printer);
262         if (!servername || !printername) {
263                 DEBUG(3, ("Insufficient memory\n"));
264                 return WERR_NOMEM;
265         }
266         
267         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
268                                              "", MAXIMUM_ALLOWED_ACCESS, 
269                                              servername, cli->user_name, &pol);
270         if (!W_ERROR_IS_OK(result)) {
271                 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
272                           printername, dos_errstr(result)));
273                 return result;
274         }
275         
276         result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 
277                                                &pol, SPOOL_DSDRIVER_KEY, NULL);
278
279         if (W_ERROR_V(result) == ERRmoredata)
280                 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed, 
281                                                        NULL, &pol, 
282                                                        SPOOL_DSDRIVER_KEY,
283                                                        &dsdriver_ctr);
284
285         if (!W_ERROR_IS_OK(result)) {
286                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
287                           printername, dos_errstr(result)));
288         } else {
289
290                 /* Have the data we need now, so start building */
291                 got_dsdriver = True;
292                 for (i=0; i < dsdriver_ctr.num_values; i++)
293                         map_regval_to_ads(mem_ctx, mods, 
294                                           dsdriver_ctr.values[i]);
295         }
296         
297         result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 
298                                                &pol, SPOOL_DSSPOOLER_KEY, 
299                                                NULL);
300
301         if (W_ERROR_V(result) == ERRmoredata)
302                 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed, 
303                                                        NULL, &pol, 
304                                                        SPOOL_DSSPOOLER_KEY,
305                                                        &dsspooler_ctr);
306
307         if (!W_ERROR_IS_OK(result)) {
308                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
309                           printername, dos_errstr(result)));
310         } else {
311                 got_dsspooler = True;
312                 for (i=0; i < dsspooler_ctr.num_values; i++)
313                         map_regval_to_ads(mem_ctx, mods, 
314                                           dsspooler_ctr.values[i]);
315         }
316         
317         ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
318
319         if (got_dsdriver) regval_ctr_destroy(&dsdriver_ctr);
320         if (got_dsspooler) regval_ctr_destroy(&dsspooler_ctr);
321         cli_spoolss_close_printer(cli, mem_ctx, &pol);
322
323         return result;
324 }
325
326 BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
327                                        ADS_MODLIST *mods,
328                                        NT_PRINTER_DATA *data)
329 {
330         uint32 key,val;
331
332         for (key=0; key < data->num_keys; key++) {
333                 REGVAL_CTR ctr = data->keys[key].values;
334                 for (val=0; val < ctr.num_values; val++)
335                         map_regval_to_ads(mem_ctx, mods, ctr.values[val]);
336         }
337         return True;
338 }
339
340 #endif
341