s3-build: avoid to globally include printing and spoolss headers.
[vlendec/samba-autobuild/.git] / source3 / libads / ldap_printer.c
1 /* 
2    Unix SMB/CIFS implementation.
3    ads (active directory) printer utility library
4    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "../librpc/gen_ndr/cli_spoolss.h"
22 #include "rpc_client/cli_spoolss.h"
23 #include "registry.h"
24 #include "registry/reg_objects.h"
25 #include "nt_printing.h"
26
27 #ifdef HAVE_ADS
28
29 /*
30   find a printer given the name and the hostname
31     Note that results "res" may be allocated on return so that the
32     results can be used.  It should be freed using ads_msgfree.
33 */
34  ADS_STATUS ads_find_printer_on_server(ADS_STRUCT *ads, LDAPMessage **res,
35                                        const char *printer,
36                                        const char *servername)
37 {
38         ADS_STATUS status;
39         char *srv_dn, **srv_cn, *s = NULL;
40         const char *attrs[] = {"*", "nTSecurityDescriptor", NULL};
41
42         status = ads_find_machine_acct(ads, res, servername);
43         if (!ADS_ERR_OK(status)) {
44                 DEBUG(1, ("ads_find_printer_on_server: cannot find host %s in ads\n",
45                           servername));
46                 return status;
47         }
48         if (ads_count_replies(ads, *res) != 1) {
49                 if (res) {
50                         ads_msgfree(ads, *res);
51                         *res = NULL;
52                 }
53                 return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
54         }
55         srv_dn = ldap_get_dn(ads->ldap.ld, *res);
56         if (srv_dn == NULL) {
57                 if (res) {
58                         ads_msgfree(ads, *res);
59                         *res = NULL;
60                 }
61                 return ADS_ERROR(LDAP_NO_MEMORY);
62         }
63         srv_cn = ldap_explode_dn(srv_dn, 1);
64         if (srv_cn == NULL) {
65                 ldap_memfree(srv_dn);
66                 if (res) {
67                         ads_msgfree(ads, *res);
68                         *res = NULL;
69                 }
70                 return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
71         }
72         if (res) {
73                 ads_msgfree(ads, *res);
74                 *res = NULL;
75         }
76
77         if (asprintf(&s, "(cn=%s-%s)", srv_cn[0], printer) == -1) {
78                 ldap_memfree(srv_dn);
79                 return ADS_ERROR(LDAP_NO_MEMORY);
80         }
81         status = ads_search(ads, res, s, attrs);
82
83         ldap_memfree(srv_dn);
84         ldap_value_free(srv_cn);
85         SAFE_FREE(s);
86         return status;  
87 }
88
89  ADS_STATUS ads_find_printers(ADS_STRUCT *ads, LDAPMessage **res)
90 {
91         const char *ldap_expr;
92         const char *attrs[] = { "objectClass", "printerName", "location", "driverName",
93                                 "serverName", "description", NULL };
94
95         /* For the moment only display all printers */
96
97         ldap_expr = "(&(!(showInAdvancedViewOnly=TRUE))(uncName=*)"
98                 "(objectCategory=printQueue))";
99
100         return ads_search(ads, res, ldap_expr, attrs);
101 }
102
103 /*
104   modify a printer entry in the directory
105 */
106 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
107                                  TALLOC_CTX *ctx, const ADS_MODLIST *mods)
108 {
109         return ads_gen_mod(ads, prt_dn, *mods);
110 }
111
112 /*
113   add a printer to the directory
114 */
115 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
116                                         TALLOC_CTX *ctx, ADS_MODLIST *mods)
117 {
118         ads_mod_str(ctx, mods, "objectClass", "printQueue");
119         return ads_gen_add(ads, prt_dn, *mods);
120 }
121
122 /*
123   map a REG_SZ to an ldap mod
124 */
125 static bool map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
126                    struct regval_blob *value)
127 {
128         char *str_value = NULL;
129         size_t converted_size;
130         ADS_STATUS status;
131
132         if (regval_type(value) != REG_SZ)
133                 return false;
134
135         if (regval_size(value) && *((smb_ucs2_t *) regval_data_p(value))) {
136                 if (!pull_ucs2_talloc(ctx, &str_value,
137                                       (const smb_ucs2_t *) regval_data_p(value),
138                                       &converted_size))
139                 {
140                         return false;
141                 }
142                 status = ads_mod_str(ctx, mods, regval_name(value), str_value);
143                 return ADS_ERR_OK(status);
144         }
145         return true;
146                 
147 }
148
149 /*
150   map a REG_DWORD to an ldap mod
151 */
152 static bool map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
153                       struct regval_blob *value)
154 {
155         char *str_value = NULL;
156         ADS_STATUS status;
157
158         if (regval_type(value) != REG_DWORD)
159                 return False;
160         str_value = talloc_asprintf(ctx, "%d", *((uint32 *) regval_data_p(value)));
161         if (!str_value) {
162                 return False;
163         }
164         status = ads_mod_str(ctx, mods, regval_name(value), str_value);
165         return ADS_ERR_OK(status);
166 }
167
168 /*
169   map a boolean REG_BINARY to an ldap mod
170 */
171 static bool map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
172                      struct regval_blob *value)
173 {
174         char *str_value;
175         ADS_STATUS status;
176
177         if ((regval_type(value) != REG_BINARY) || (regval_size(value) != 1))
178                 return False;
179         str_value =  talloc_asprintf(ctx, "%s", 
180                                      *(regval_data_p(value)) ? "TRUE" : "FALSE");
181         if (!str_value) {
182                 return False;
183         }
184         status = ads_mod_str(ctx, mods, regval_name(value), str_value);
185         return ADS_ERR_OK(status);
186 }
187
188 /*
189   map a REG_MULTI_SZ to an ldap mod
190 */
191 static bool map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
192                          struct regval_blob *value)
193 {
194         char **str_values = NULL;
195         size_t converted_size;
196         smb_ucs2_t *cur_str = (smb_ucs2_t *) regval_data_p(value);
197         uint32 size = 0, num_vals = 0, i=0;
198         ADS_STATUS status;
199
200         if (regval_type(value) != REG_MULTI_SZ)
201                 return False;
202
203         while(cur_str && *cur_str && (size < regval_size(value))) {
204                 size += 2 * (strlen_w(cur_str) + 1);
205                 cur_str += strlen_w(cur_str) + 1;
206                 num_vals++;
207         };
208
209         if (num_vals) {
210                 str_values = TALLOC_ARRAY(ctx, char *, num_vals + 1);
211                 if (!str_values) {
212                         return False;
213                 }
214                 memset(str_values, '\0', 
215                        (num_vals + 1) * sizeof(char *));
216
217                 cur_str = (smb_ucs2_t *) regval_data_p(value);
218                 for (i=0; i < num_vals; i++) {
219                         cur_str += pull_ucs2_talloc(ctx, &str_values[i],
220                                                     cur_str, &converted_size) ?
221                             converted_size : (size_t)-1;
222                 }
223
224                 status = ads_mod_strlist(ctx, mods, regval_name(value),
225                                          (const char **) str_values);
226                 return ADS_ERR_OK(status);
227         } 
228         return True;
229 }
230
231 struct valmap_to_ads {
232         const char *valname;
233         bool (*fn)(TALLOC_CTX *, ADS_MODLIST *, struct regval_blob *);
234 };
235
236 /*
237   map a REG_SZ to an ldap mod
238 */
239 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
240                               struct regval_blob *value)
241 {
242         const struct valmap_to_ads map[] = {
243                 {SPOOL_REG_ASSETNUMBER, map_sz},
244                 {SPOOL_REG_BYTESPERMINUTE, map_dword},
245                 {SPOOL_REG_DEFAULTPRIORITY, map_dword},
246                 {SPOOL_REG_DESCRIPTION, map_sz},
247                 {SPOOL_REG_DRIVERNAME, map_sz},
248                 {SPOOL_REG_DRIVERVERSION, map_dword},
249                 {SPOOL_REG_FLAGS, map_dword},
250                 {SPOOL_REG_LOCATION, map_sz},
251                 {SPOOL_REG_OPERATINGSYSTEM, map_sz},
252                 {SPOOL_REG_OPERATINGSYSTEMHOTFIX, map_sz},
253                 {SPOOL_REG_OPERATINGSYSTEMSERVICEPACK, map_sz},
254                 {SPOOL_REG_OPERATINGSYSTEMVERSION, map_sz},
255                 {SPOOL_REG_PORTNAME, map_multi_sz},
256                 {SPOOL_REG_PRINTATTRIBUTES, map_dword},
257                 {SPOOL_REG_PRINTBINNAMES, map_multi_sz},
258                 {SPOOL_REG_PRINTCOLLATE, map_bool},
259                 {SPOOL_REG_PRINTCOLOR, map_bool},
260                 {SPOOL_REG_PRINTDUPLEXSUPPORTED, map_bool},
261                 {SPOOL_REG_PRINTENDTIME, map_dword},
262                 {SPOOL_REG_PRINTFORMNAME, map_sz},
263                 {SPOOL_REG_PRINTKEEPPRINTEDJOBS, map_bool},
264                 {SPOOL_REG_PRINTLANGUAGE, map_multi_sz},
265                 {SPOOL_REG_PRINTMACADDRESS, map_sz},
266                 {SPOOL_REG_PRINTMAXCOPIES, map_sz},
267                 {SPOOL_REG_PRINTMAXRESOLUTIONSUPPORTED, map_dword},
268                 {SPOOL_REG_PRINTMAXXEXTENT, map_dword},
269                 {SPOOL_REG_PRINTMAXYEXTENT, map_dword},
270                 {SPOOL_REG_PRINTMEDIAREADY, map_multi_sz},
271                 {SPOOL_REG_PRINTMEDIASUPPORTED, map_multi_sz},
272                 {SPOOL_REG_PRINTMEMORY, map_dword},
273                 {SPOOL_REG_PRINTMINXEXTENT, map_dword},
274                 {SPOOL_REG_PRINTMINYEXTENT, map_dword},
275                 {SPOOL_REG_PRINTNETWORKADDRESS, map_sz},
276                 {SPOOL_REG_PRINTNOTIFY, map_sz},
277                 {SPOOL_REG_PRINTNUMBERUP, map_dword},
278                 {SPOOL_REG_PRINTORIENTATIONSSUPPORTED, map_multi_sz},
279                 {SPOOL_REG_PRINTOWNER, map_sz},
280                 {SPOOL_REG_PRINTPAGESPERMINUTE, map_dword},
281                 {SPOOL_REG_PRINTRATE, map_dword},
282                 {SPOOL_REG_PRINTRATEUNIT, map_sz},
283                 {SPOOL_REG_PRINTSEPARATORFILE, map_sz},
284                 {SPOOL_REG_PRINTSHARENAME, map_sz},
285                 {SPOOL_REG_PRINTSPOOLING, map_sz},
286                 {SPOOL_REG_PRINTSTAPLINGSUPPORTED, map_bool},
287                 {SPOOL_REG_PRINTSTARTTIME, map_dword},
288                 {SPOOL_REG_PRINTSTATUS, map_sz},
289                 {SPOOL_REG_PRIORITY, map_dword},
290                 {SPOOL_REG_SERVERNAME, map_sz},
291                 {SPOOL_REG_SHORTSERVERNAME, map_sz},
292                 {SPOOL_REG_UNCNAME, map_sz},
293                 {SPOOL_REG_URL, map_sz},
294                 {SPOOL_REG_VERSIONNUMBER, map_dword},
295                 {NULL, NULL}
296         };
297         int i;
298
299         for (i=0; map[i].valname; i++) {
300                 if (StrCaseCmp(map[i].valname, regval_name(value)) == 0) {
301                         if (!map[i].fn(ctx, mods, value)) {
302                                 DEBUG(5, ("Add of value %s to modlist failed\n", regval_name(value)));
303                         } else {
304                                 DEBUG(7, ("Mapped value %s\n", regval_name(value)));
305                         }
306                         
307                 }
308         }
309 }
310
311
312 WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli, 
313                                           TALLOC_CTX *mem_ctx,
314                                           ADS_MODLIST *mods,
315                                           const char *printer)
316 {
317         WERROR result;
318         char *printername;
319         struct spoolss_PrinterEnumValues *info;
320         uint32_t count;
321         uint32 i;
322         struct policy_handle pol;
323
324         if ((asprintf(&printername, "%s\\%s", cli->srv_name_slash, printer) == -1)) {
325                 DEBUG(3, ("Insufficient memory\n"));
326                 return WERR_NOMEM;
327         }
328
329         result = rpccli_spoolss_openprinter_ex(cli, mem_ctx,
330                                                printername,
331                                                SEC_FLAG_MAXIMUM_ALLOWED,
332                                                &pol);
333         if (!W_ERROR_IS_OK(result)) {
334                 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
335                           printername, win_errstr(result)));
336                 SAFE_FREE(printername);
337                 return result;
338         }
339
340         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
341                                                   SPOOL_DSDRIVER_KEY,
342                                                   0,
343                                                   &count,
344                                                   &info);
345
346         if (!W_ERROR_IS_OK(result)) {
347                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
348                           printername, win_errstr(result)));
349         } else {
350                 /* Have the data we need now, so start building */
351                 for (i=0; i < count; i++) {
352                         struct regval_blob *v;
353
354                         v = regval_compose(mem_ctx, info[i].value_name,
355                                            info[i].type,
356                                            info[i].data->data,
357                                            info[i].data->length);
358                         if (v == NULL) {
359                                 return WERR_NOMEM;
360                         }
361
362                         map_regval_to_ads(mem_ctx, mods, v);
363                         talloc_free(v);
364                 }
365         }
366
367         result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol,
368                                                   SPOOL_DSSPOOLER_KEY,
369                                                   0,
370                                                   &count,
371                                                   &info);
372         if (!W_ERROR_IS_OK(result)) {
373                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
374                           printername, win_errstr(result)));
375         } else {
376                 for (i=0; i < count; i++) {
377                         struct regval_blob *v;
378
379                         v = regval_compose(mem_ctx, info[i].value_name,
380                                            info[i].type,
381                                            info[i].data->data,
382                                            info[i].data->length);
383                         if (v == NULL) {
384                                 return WERR_NOMEM;
385                         }
386
387                         map_regval_to_ads(mem_ctx, mods, v);
388                         talloc_free(v);
389                 }
390         }
391
392         ads_mod_str(mem_ctx, mods, SPOOL_REG_PRINTERNAME, printer);
393
394         rpccli_spoolss_ClosePrinter(cli, mem_ctx, &pol, NULL);
395         SAFE_FREE(printername);
396
397         return result;
398 }
399
400 static bool get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
401                                        ADS_MODLIST *mods,
402                                        NT_PRINTER_DATA *data)
403 {
404         uint32 key,val;
405
406         for (key=0; key < data->num_keys; key++) {
407                 struct regval_ctr *ctr = data->keys[key].values;
408                 for (val=0; val < regval_ctr_numvals(ctr); val++)
409                         map_regval_to_ads(mem_ctx, mods, regval_ctr_specific_value(ctr, val));
410         }
411         return True;
412 }
413
414 #endif