Next step of printer publishing.
[nivanova/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 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
83         if (value->type != REG_SZ)
84                 return False;
85
86         if (value->size && *((smb_ucs2_t *) value->data_p)) {
87                 pull_ucs2_talloc(ctx, (void **) &str_value, 
88                                  (const smb_ucs2_t *) value->data_p);
89                 return ADS_ERR_OK(ads_mod_str(ctx, mods, value->valuename, 
90                                               str_value));
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
104         if (value->type != REG_DWORD)
105                 return False;
106         str_value = talloc_asprintf(ctx, "%d", *((uint32 *) value->data_p));
107         return ADS_ERR_OK(ads_mod_str(ctx, mods, value->valuename, str_value));
108 }
109
110 /*
111   map a boolean REG_BINARY to an ldap mod
112 */
113 static BOOL map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
114                      const REGISTRY_VALUE *value)
115 {
116         char *str_value;
117
118         if ((value->type != REG_BINARY) || (value->size != 1))
119                 return False;
120         str_value =  talloc_asprintf(ctx, "%s", 
121                                      *(value->data_p) ? "TRUE" : "FALSE");
122         return ADS_ERR_OK(ads_mod_str(ctx, mods, value->valuename, str_value));
123 }
124
125 /*
126   map a REG_MULTI_SZ to an ldap mod
127 */
128 static BOOL map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
129                          const REGISTRY_VALUE *value)
130 {
131         char **str_values = NULL;
132         smb_ucs2_t *cur_str = (smb_ucs2_t *) value->data_p;
133         uint32 size = 0, num_vals = 0, i=0;
134
135         if (value->type != REG_MULTI_SZ)
136                 return False;
137
138         while(cur_str && *cur_str && (size < value->size)) {            
139                 size += 2 * (strlen_w(cur_str) + 1);
140                 cur_str += strlen_w(cur_str) + 1;
141                 num_vals++;
142         };
143
144         if (num_vals) {
145                 str_values = talloc(ctx, 
146                                     (num_vals + 1) * sizeof(smb_ucs2_t *));
147                 memset(str_values, '\0', 
148                        (num_vals + 1) * sizeof(smb_ucs2_t *));
149
150                 cur_str = (smb_ucs2_t *) value->data_p;
151                 for (i=0; i < num_vals; i++)
152                         cur_str += pull_ucs2_talloc(ctx, 
153                                                     (void **) &str_values[i], 
154                                                     cur_str);
155
156                 return ADS_ERR_OK(ads_mod_strlist(ctx, mods, value->valuename, 
157                                                   (const char **) str_values));
158         } 
159         return True;
160 }
161
162 struct valmap_to_ads {
163         char *valname;
164         BOOL (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *);
165 };
166
167 /*
168   map a REG_SZ to an ldap mod
169 */
170 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods, 
171                               REGISTRY_VALUE *value)
172 {
173         struct valmap_to_ads map[] = {
174                 {"assetNumber", map_sz},
175                 {"bytesPerMinute", map_dword},
176                 {"defaultPriority", map_dword},
177                 {"driverName", map_sz},
178                 {"driverVersion", map_dword},
179                 {"flags", map_dword},
180                 {"location", map_sz},
181                 {"operatingSystem", map_sz},
182                 {"operatingSystemHotfix", map_sz},
183                 {"operatingSystemServicePack", map_sz},
184                 {"operatingSystemVersion", map_sz},
185                 {"portName", map_multi_sz},
186                 {"printAttributes", map_dword},
187                 {"printBinNames", map_multi_sz},
188                 {"printCollate", map_bool},
189                 {"printColor", map_bool},
190                 {"printDuplexSupported", map_bool},
191                 {"printEndTime", map_dword},
192                 {"printFormName", map_sz},
193                 {"printKeepPrintedJobs", map_bool},
194                 {"printLanguage", map_multi_sz},
195                 {"printMACAddress", map_sz},
196                 {"printMaxCopies", map_sz},
197                 {"printMaxResolutionSupported", map_dword},
198                 {"printMaxXExtent", map_dword},
199                 {"printMaxYExtent", map_dword},
200                 {"printMediaReady", map_multi_sz},
201                 {"printMediaSupported", map_multi_sz},
202                 {"printMemory", map_dword},
203                 {"printMinXExtent", map_dword},
204                 {"printMinYExtent", map_dword},
205                 {"printNetworkAddress", map_sz},
206                 {"printNotify", map_sz},
207                 {"printNumberUp", map_dword},
208                 {"printOrientationsSupported", map_multi_sz},
209                 {"printOwner", map_sz},
210                 {"printPagesPerMinute", map_dword},
211                 {"printRate", map_dword},
212                 {"printRateUnit", map_sz},
213                 {"printSeparatorFile", map_sz},
214                 {"printShareName", map_sz},
215                 {"printSpooling", map_sz},
216                 {"printStaplingSupported", map_bool},
217                 {"printStartTime", map_dword},
218                 {"printStatus", map_sz},
219                 {"priority", map_dword},
220                 {"serverName", map_sz},
221                 {"shortServerName", map_sz},
222                 {"uNCName", map_sz},
223                 {"url", map_sz},
224                 {"versionNumber", map_dword},
225                 {NULL, NULL}
226         };
227         int i;
228
229         for (i=0; map[i].valname; i++) {
230                 if (StrCaseCmp(map[i].valname, value->valuename) == 0) {
231                         if (!map[i].fn(ctx, mods, value)) {
232                                 DEBUG(5, ("Add of value %s to modlist failed\n", value->valuename));
233                         } else {
234                                 DEBUG(7, ("Mapped value %s\n", value->valuename));
235                         }
236                         
237                 }
238         }
239 }
240
241
242 WERROR get_remote_printer_publishing_data(struct cli_state *cli, 
243                                           TALLOC_CTX *mem_ctx,
244                                           ADS_MODLIST *mods,
245                                           char *printer)
246 {
247         WERROR result;
248         char *printername, *servername;
249         REGVAL_CTR dsdriver_ctr, dsspooler_ctr;
250         uint32 needed, i;
251         POLICY_HND pol;
252
253         asprintf(&servername, "\\\\%s", cli->desthost);
254         asprintf(&printername, "%s\\%s", servername, printer);
255         if (!servername || !printername) {
256                 DEBUG(3, ("Insufficient memory\n"));
257                 return WERR_NOMEM;
258         }
259         
260         result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, 
261                                              "", MAXIMUM_ALLOWED_ACCESS, 
262                                              servername, cli->user_name, &pol);
263         if (!W_ERROR_IS_OK(result)) {
264                 DEBUG(3, ("Unable to open printer %s, error is %s.\n",
265                           printername, dos_errstr(result)));
266                 return result;
267         }
268         
269         result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 
270                                                &pol, "DsDriver", NULL);
271
272         if (W_ERROR_V(result) == ERRmoredata)
273                 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed, 
274                                                        NULL, &pol, "DsDriver",
275                                                        &dsdriver_ctr);
276
277         if (!W_ERROR_IS_OK(result)) {
278                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
279                           printername, dos_errstr(result)));
280                 cli_spoolss_close_printer(cli, mem_ctx, &pol);
281                 return result;
282         }
283
284         /* Have the data we need now, so start building */
285
286         for (i=0; i < dsdriver_ctr.num_values; i++)
287                 map_regval_to_ads(mem_ctx, mods, dsdriver_ctr.values[i]);
288         
289         result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed, 
290                                                &pol, "DsSpooler", NULL);
291
292         if (W_ERROR_V(result) == ERRmoredata)
293                 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed, 
294                                                        NULL, &pol, "DsSpooler",
295                                                        &dsspooler_ctr);
296
297         if (!W_ERROR_IS_OK(result)) {
298                 DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n",
299                           printername, dos_errstr(result)));
300                 regval_ctr_destroy(&dsdriver_ctr);
301                 cli_spoolss_close_printer(cli, mem_ctx, &pol);
302                 return result;
303         }
304         for (i=0; i < dsspooler_ctr.num_values; i++)
305                 map_regval_to_ads(mem_ctx, mods, dsspooler_ctr.values[i]);
306         
307         ads_mod_str(mem_ctx, mods, "printerName", printername);
308
309         regval_ctr_destroy(&dsdriver_ctr);
310         regval_ctr_destroy(&dsspooler_ctr);
311         cli_spoolss_close_printer(cli, mem_ctx, &pol);
312
313         return result;
314 }
315
316 BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
317                                        ADS_MODLIST *mods,
318                                        NT_PRINTER_DATA *data)
319 {
320         uint32 key,val;
321
322         for (key=0; key < data->num_keys; key++) {
323                 REGVAL_CTR ctr = data->keys[key].values;
324                 for (val=0; val < ctr.num_values; val++)
325                         map_regval_to_ads(mem_ctx, mods, ctr.values[val]);
326         }
327         return True;
328 }
329
330 #endif
331