2 Unix SMB/CIFS implementation.
3 ads (active directory) printer utility library
4 Copyright (C) Jim McDonough 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 2 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, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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, void **res,
31 const char *printer, const char *servername)
34 char *srv_dn, **srv_cn, *exp;
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_add_printer: cannot find host %s in ads\n",
43 srv_dn = ldap_get_dn(ads->ld, *res);
44 srv_cn = ldap_explode_dn(srv_dn, 1);
45 ads_msgfree(ads, *res);
47 asprintf(&exp, "(cn=%s-%s)", srv_cn[0], printer);
48 status = ads_search(ads, res, exp, attrs);
51 ldap_value_free(srv_cn);
57 modify a printer entry in the directory
59 ADS_STATUS ads_mod_printer_entry(ADS_STRUCT *ads, char *prt_dn,
60 TALLOC_CTX *ctx, const ADS_MODLIST *mods)
62 return ads_gen_mod(ads, prt_dn, *mods);
66 add a printer to the directory
68 ADS_STATUS ads_add_printer_entry(ADS_STRUCT *ads, char *prt_dn,
69 TALLOC_CTX *ctx, ADS_MODLIST *mods)
71 ads_mod_str(ctx, mods, "objectClass", "printQueue");
72 return ads_gen_add(ads, prt_dn, *mods);
76 map a REG_SZ to an ldap mod
78 static BOOL map_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
79 const REGISTRY_VALUE *value)
81 char *str_value = NULL;
83 if (value->type != REG_SZ)
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,
97 map a REG_DWORD to an ldap mod
99 static BOOL map_dword(TALLOC_CTX *ctx, ADS_MODLIST *mods,
100 const REGISTRY_VALUE *value)
102 char *str_value = NULL;
104 if (value->type != REG_DWORD)
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));
111 map a boolean REG_BINARY to an ldap mod
113 static BOOL map_bool(TALLOC_CTX *ctx, ADS_MODLIST *mods,
114 const REGISTRY_VALUE *value)
118 if ((value->type != REG_BINARY) || (value->size != 1))
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));
126 map a REG_MULTI_SZ to an ldap mod
128 static BOOL map_multi_sz(TALLOC_CTX *ctx, ADS_MODLIST *mods,
129 const REGISTRY_VALUE *value)
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;
135 if (value->type != REG_MULTI_SZ)
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;
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 *));
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],
156 return ADS_ERR_OK(ads_mod_strlist(ctx, mods, value->valuename,
157 (const char **) str_values));
162 struct valmap_to_ads {
164 BOOL (*fn)(TALLOC_CTX *, ADS_MODLIST *, const REGISTRY_VALUE *);
168 map a REG_SZ to an ldap mod
170 static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods,
171 REGISTRY_VALUE *value)
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},
224 {"versionNumber", map_dword},
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));
234 DEBUG(7, ("Mapped value %s\n", value->valuename));
242 WERROR get_remote_printer_publishing_data(struct cli_state *cli,
248 char *printername, *servername;
249 REGVAL_CTR dsdriver_ctr, dsspooler_ctr;
253 asprintf(&servername, "\\\\%s", cli->desthost);
254 asprintf(&printername, "%s\\%s", servername, printer);
255 if (!servername || !printername) {
256 DEBUG(3, ("Insufficient memory\n"));
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)));
269 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed,
270 &pol, "DsDriver", NULL);
272 if (W_ERROR_V(result) == ERRmoredata)
273 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed,
274 NULL, &pol, "DsDriver",
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);
284 /* Have the data we need now, so start building */
286 for (i=0; i < dsdriver_ctr.num_values; i++)
287 map_regval_to_ads(mem_ctx, mods, dsdriver_ctr.values[i]);
289 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, 0, &needed,
290 &pol, "DsSpooler", NULL);
292 if (W_ERROR_V(result) == ERRmoredata)
293 result = cli_spoolss_enumprinterdataex(cli, mem_ctx, needed,
294 NULL, &pol, "DsSpooler",
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);
304 for (i=0; i < dsspooler_ctr.num_values; i++)
305 map_regval_to_ads(mem_ctx, mods, dsspooler_ctr.values[i]);
307 ads_mod_str(mem_ctx, mods, "printerName", printername);
309 regval_ctr_destroy(&dsdriver_ctr);
310 regval_ctr_destroy(&dsspooler_ctr);
311 cli_spoolss_close_printer(cli, mem_ctx, &pol);
316 BOOL get_local_printer_publishing_data(TALLOC_CTX *mem_ctx,
318 NT_PRINTER_DATA *data)
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]);