s4:dsdb - remove "samdb_result_uint", "samdb_result_int64", "samdb_result_uint64...
[sfrench/samba-autobuild/.git] / source4 / ntptr / simple_ldb / ntptr_simple_ldb.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Simple LDB NTPTR backend
5
6    Copyright (C) Stefan (metze) Metzmacher 2005
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21 /*
22   This implements a NTPTR backend that store
23   all objects (Printers, Ports, Monitors, PrinterDrivers ...)
24   in a ldb database, but doesn't do real printing.
25
26   This is just used for testing how some of
27   the SPOOLSS protocol details should work
28 */
29
30 #include "includes.h"
31 #include "ntptr/ntptr.h"
32 #include "librpc/gen_ndr/ndr_spoolss.h"
33 #include "lib/ldb/include/ldb.h"
34 #include "auth/auth.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "ldb_wrap.h"
37 #include "../lib/util/util_ldb.h"
38 #include "rpc_server/common/common.h"
39 #include "param/param.h"
40
41 /*
42   connect to the SPOOLSS database
43   return a ldb_context pointer on success, or NULL on failure
44  */
45 static struct ldb_context *sptr_db_connect(TALLOC_CTX *mem_ctx, struct tevent_context *ev_ctx, struct loadparm_context *lp_ctx)
46 {
47         return ldb_wrap_connect(mem_ctx, ev_ctx, lp_ctx, lpcfg_spoolss_url(lp_ctx), system_session(lp_ctx),
48                                 NULL, 0);
49 }
50
51 static int sptr_db_search(struct ldb_context *ldb,
52                           TALLOC_CTX *mem_ctx,
53                           struct ldb_dn *basedn,
54                           struct ldb_message ***res,
55                           const char * const *attrs,
56                           const char *format, ...) PRINTF_ATTRIBUTE(6,7);
57
58 static int sptr_db_search(struct ldb_context *ldb,
59                           TALLOC_CTX *mem_ctx,
60                           struct ldb_dn *basedn,
61                           struct ldb_message ***res,
62                           const char * const *attrs,
63                           const char *format, ...)
64 {
65         va_list ap;
66         int count;
67
68         va_start(ap, format);
69         count = gendb_search_v(ldb, mem_ctx, basedn, res, attrs, format, ap);
70         va_end(ap);
71
72         return count;
73 }
74
75 #define SET_STRING(ldb, mod, attr, value) do { \
76         if (value == NULL) return WERR_INVALID_PARAM; \
77         if (samdb_msg_add_string(ldb, (TALLOC_CTX *)mod, mod, attr, value) != 0) { \
78                 return WERR_NOMEM; \
79         } \
80 } while (0)
81
82 #define SET_UINT(ldb, mod, attr, value) do { \
83         if (samdb_msg_add_uint(ldb, (TALLOC_CTX *)mod, mod, attr, value) != 0) { \
84                 return WERR_NOMEM; \
85         } \
86 } while (0)
87
88 static NTSTATUS sptr_init_context(struct ntptr_context *ntptr)
89 {
90         struct ldb_context *sptr_db = sptr_db_connect(ntptr, ntptr->ev_ctx, ntptr->lp_ctx);
91         NT_STATUS_HAVE_NO_MEMORY(sptr_db);
92
93         ntptr->private_data = sptr_db;
94
95         return NT_STATUS_OK;
96 }
97
98 /* PrintServer functions */
99 static WERROR sptr_OpenPrintServer(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
100                                    struct spoolss_OpenPrinterEx *r,
101                                    const char *server_name,
102                                    struct ntptr_GenericHandle **_server)
103 {
104         struct ntptr_GenericHandle *server;
105
106         /* TODO: do access check here! */
107
108         server = talloc(mem_ctx, struct ntptr_GenericHandle);
109         W_ERROR_HAVE_NO_MEMORY(server);
110
111         server->type            = NTPTR_HANDLE_SERVER;
112         server->ntptr           = ntptr;
113         server->object_name     = talloc_strdup(server, server_name);
114         W_ERROR_HAVE_NO_MEMORY(server->object_name);
115         server->access_mask     = 0;
116         server->private_data    = NULL;
117
118         *_server = server;
119         return WERR_OK;
120 }
121
122 /*
123  * PrintServer PrinterData functions
124  */
125
126 static WERROR sptr_PrintServerData(struct ntptr_GenericHandle *server,
127                                    TALLOC_CTX *mem_ctx,
128                                    const char *value_name,
129                                    union spoolss_PrinterData *r,
130                                    enum winreg_Type *type)
131 {
132         struct dcerpc_server_info *server_info = lpcfg_dcerpc_server_info(mem_ctx, server->ntptr->lp_ctx);
133         if (strcmp("W3SvcInstalled", value_name) == 0) {
134                 *type           = REG_DWORD;
135                 r->value        = 0;
136                 return WERR_OK;
137         } else if (strcmp("BeepEnabled", value_name) == 0) {
138                 *type           = REG_DWORD;
139                 r->value        = 0;
140                 return WERR_OK;
141         } else if (strcmp("EventLog", value_name) == 0) {
142                 *type           = REG_DWORD;
143                 r->value        = 0;
144                 return WERR_OK;
145         } else if (strcmp("NetPopup", value_name) == 0) {
146                 *type           = REG_DWORD;
147                 r->value        = 0;
148                 return WERR_OK;
149         } else if (strcmp("NetPopupToComputer", value_name) == 0) {
150                 *type           = REG_DWORD;
151                 r->value        = 0;
152                 return  WERR_OK;
153         } else if (strcmp("MajorVersion", value_name) == 0) {
154                 *type           = REG_DWORD;
155                 r->value        = 3;
156                 return WERR_OK;
157         } else if (strcmp("MinorVersion", value_name) == 0) {
158                 *type           = REG_DWORD;
159                 r->value        = 0;
160                 return WERR_OK;
161         } else if (strcmp("DefaultSpoolDirectory", value_name) == 0) {
162                 *type           = REG_SZ;
163                 r->string       = "C:\\PRINTERS";
164                 return  WERR_OK;
165         } else if (strcmp("Architecture", value_name) == 0) {
166                 *type           = REG_SZ;
167                 r->string       = SPOOLSS_ARCHITECTURE_NT_X86;
168                 return  WERR_OK;
169         } else if (strcmp("DsPresent", value_name) == 0) {
170                 *type           = REG_DWORD;
171                 r->value        = 1;
172                 return WERR_OK;
173         } else if (strcmp("OSVersion", value_name) == 0) {
174                 DATA_BLOB blob;
175                 enum ndr_err_code ndr_err;
176                 struct spoolss_OSVersion os;
177
178                 os.major                = server_info->version_major;
179                 os.minor                = server_info->version_minor;
180                 os.build                = server_info->version_build;
181                 os.extra_string         = "";
182
183                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
184                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
185                         return WERR_GENERAL_FAILURE;
186                 }
187
188                 *type           = REG_BINARY;
189                 r->binary       = blob;
190                 return WERR_OK;
191         } else if (strcmp("OSVersionEx", value_name) == 0) {
192                 DATA_BLOB blob;
193                 enum ndr_err_code ndr_err;
194                 struct spoolss_OSVersionEx os_ex;
195
196                 os_ex.major             = server_info->version_major;
197                 os_ex.minor             = server_info->version_minor;
198                 os_ex.build             = server_info->version_build;
199                 os_ex.extra_string      = "";
200                 os_ex.service_pack_major= 0;
201                 os_ex.service_pack_minor= 0;
202                 os_ex.suite_mask        = 0;
203                 os_ex.product_type      = 0;
204                 os_ex.reserved          = 0;
205
206                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &os_ex, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersionEx);
207                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
208                         return WERR_GENERAL_FAILURE;
209                 }
210
211                 *type           = REG_BINARY;
212                 r->binary       = blob;
213                 return WERR_OK;
214         } else if (strcmp("DNSMachineName", value_name) == 0) {
215                 const char *dnsdomain = lpcfg_dnsdomain(server->ntptr->lp_ctx);
216
217                 if (dnsdomain == NULL) return WERR_INVALID_PARAM;
218
219                 *type           = REG_SZ;
220                 r->string       = talloc_asprintf(mem_ctx, "%s.%s",
221                                                           lpcfg_netbios_name(server->ntptr->lp_ctx),
222                                                           dnsdomain);
223                 W_ERROR_HAVE_NO_MEMORY(r->string);
224                 return WERR_OK;
225         }
226
227         return WERR_INVALID_PARAM;
228 }
229
230 static WERROR sptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
231                                       struct spoolss_GetPrinterData *r)
232 {
233         WERROR result;
234         union spoolss_PrinterData data;
235         DATA_BLOB blob;
236         enum ndr_err_code ndr_err;
237
238         result = sptr_PrintServerData(server, mem_ctx, r->in.value_name, &data, r->out.type);
239         if (!W_ERROR_IS_OK(result)) {
240                 return result;
241         }
242
243         ndr_err = ndr_push_union_blob(&blob, mem_ctx, 
244                                       &data, *r->out.type, (ndr_push_flags_fn_t)ndr_push_spoolss_PrinterData);
245         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
246                 return WERR_GENERAL_FAILURE;
247         }
248
249         *r->out.needed = blob.length;
250
251         if (r->in.offered >= *r->out.needed) {
252                 memcpy(r->out.data, blob.data, blob.length);
253         }
254
255         return WERR_OK;
256 }
257
258 /* PrintServer Form functions */
259 static WERROR sptr_EnumPrintServerForms(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
260                                         struct spoolss_EnumForms *r)
261 {
262         struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
263         struct ldb_message **msgs;
264         int count;
265         int i;
266         union spoolss_FormInfo *info;
267
268         count = sptr_db_search(sptr_db, mem_ctx,
269                                 ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"),
270                                 &msgs, NULL, "(&(objectClass=form))");
271
272         if (count == 0) return WERR_OK;
273         if (count < 0) return WERR_GENERAL_FAILURE;
274
275         info = talloc_array(mem_ctx, union spoolss_FormInfo, count);
276         W_ERROR_HAVE_NO_MEMORY(info);
277
278         switch (r->in.level) {
279         case 1:
280                 for (i=0; i < count; i++) {
281                         info[i].info1.flags             = ldb_msg_find_attr_as_uint(msgs[i], "flags", SPOOLSS_FORM_BUILTIN);
282
283                         info[i].info1.form_name         = ldb_msg_find_attr_as_string(msgs[i], "form-name", NULL);
284                         W_ERROR_HAVE_NO_MEMORY(info[i].info1.form_name);
285
286                         info[i].info1.size.width        = ldb_msg_find_attr_as_uint(msgs[i], "size-width", 0);
287                         info[i].info1.size.height       = ldb_msg_find_attr_as_uint(msgs[i], "size-height", 0);
288
289                         info[i].info1.area.left         = ldb_msg_find_attr_as_uint(msgs[i], "area-left", 0);
290                         info[i].info1.area.top          = ldb_msg_find_attr_as_uint(msgs[i], "area-top", 0);
291                         info[i].info1.area.right        = ldb_msg_find_attr_as_uint(msgs[i], "area-right", 0);
292                         info[i].info1.area.bottom       = ldb_msg_find_attr_as_uint(msgs[i], "area-bottom", 0);
293                 }
294                 break;
295         default:
296                 return WERR_UNKNOWN_LEVEL;
297         }
298
299         *r->out.info    = info;
300         *r->out.count   = count;
301         return WERR_OK;
302 }
303
304 static WERROR sptr_AddPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
305                                       struct spoolss_AddForm *r)
306 {
307         struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
308         struct ldb_message *msg,**msgs;
309         const char * const attrs[] = {"flags", NULL };
310         int count, ret;
311
312         /* TODO: do checks access here
313          * if (!(server->access_mask & desired_access)) {
314          *      return WERR_FOOBAR;
315          * }
316          */
317
318         switch (r->in.level) {
319         case 1:
320                 if (!r->in.info.info1) {
321                         return WERR_FOOBAR;
322                 }
323                 count = sptr_db_search(sptr_db, mem_ctx,
324                                        ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"),
325                                        &msgs, attrs, "(&(form-name=%s)(objectClass=form))",
326                                        r->in.info.info1->form_name);
327
328                 if (count == 1) return WERR_FOOBAR;
329                 if (count > 1) return WERR_FOOBAR;
330                 if (count < 0) return WERR_GENERAL_FAILURE;
331
332                 if (r->in.info.info1->flags != SPOOLSS_FORM_USER) {
333                         return WERR_FOOBAR;
334                 }
335
336                 msg = ldb_msg_new(mem_ctx);
337                 W_ERROR_HAVE_NO_MEMORY(msg);
338
339                 /* add core elements to the ldb_message for the Form */
340                 msg->dn = ldb_dn_new_fmt(msg, sptr_db, "form-name=%s,CN=Forms,CN=PrintServer", r->in.info.info1->form_name);
341                 SET_STRING(sptr_db, msg, "objectClass", "form");
342
343                 SET_UINT(sptr_db, msg, "flags", r->in.info.info1->flags);
344
345                 SET_STRING(sptr_db, msg, "form-name", r->in.info.info1->form_name);
346
347                 SET_UINT(sptr_db, msg, "size-width", r->in.info.info1->size.width);
348                 SET_UINT(sptr_db, msg, "size-height", r->in.info.info1->size.height);
349
350                 SET_UINT(sptr_db, msg, "area-left", r->in.info.info1->area.left);
351                 SET_UINT(sptr_db, msg, "area-top", r->in.info.info1->area.top);
352                 SET_UINT(sptr_db, msg, "area-right", r->in.info.info1->area.right);
353                 SET_UINT(sptr_db, msg, "area-bottom", r->in.info.info1->area.bottom);
354                 break;
355         default:
356                 return WERR_UNKNOWN_LEVEL;
357         }
358
359         ret = ldb_add(sptr_db, msg);
360         if (ret != 0) {
361                 return WERR_FOOBAR;
362         }
363
364         return WERR_OK;
365 }
366
367 static WERROR sptr_SetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
368                                       struct spoolss_SetForm *r)
369 {
370         struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
371         struct ldb_message *msg,**msgs;
372         const char * const attrs[] = { "flags", NULL};
373         int count, ret;
374         enum spoolss_FormFlags flags;
375
376         /* TODO: do checks access here
377          * if (!(server->access_mask & desired_access)) {
378          *      return WERR_FOOBAR;
379          * }
380          */
381
382         switch (r->in.level) {
383         case 1:
384                 if (!r->in.info.info1) {
385                         return WERR_FOOBAR;
386                 }
387
388                 count = sptr_db_search(sptr_db, mem_ctx,
389                                        ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"),
390                                        &msgs, attrs, "(&(form-name=%s)(objectClass=form))",
391                                        r->in.info.info1->form_name);
392
393                 if (count == 0) return WERR_FOOBAR;
394                 if (count > 1) return WERR_FOOBAR;
395                 if (count < 0) return WERR_GENERAL_FAILURE;
396
397                 flags = ldb_msg_find_attr_as_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN);
398                 if (flags != SPOOLSS_FORM_USER) {
399                         return WERR_FOOBAR;
400                 }
401
402                 msg = ldb_msg_new(mem_ctx);
403                 W_ERROR_HAVE_NO_MEMORY(msg);
404
405                 /* add core elements to the ldb_message for the user */
406                 msg->dn = msgs[0]->dn;
407
408                 SET_UINT(sptr_db, msg, "flags", r->in.info.info1->flags);
409
410                 SET_STRING(sptr_db, msg, "form-name", r->in.info.info1->form_name);
411
412                 SET_UINT(sptr_db, msg, "size-width", r->in.info.info1->size.width);
413                 SET_UINT(sptr_db, msg, "size-height", r->in.info.info1->size.height);
414
415                 SET_UINT(sptr_db, msg, "area-left", r->in.info.info1->area.left);
416                 SET_UINT(sptr_db, msg, "area-top", r->in.info.info1->area.top);
417                 SET_UINT(sptr_db, msg, "area-right", r->in.info.info1->area.right);
418                 SET_UINT(sptr_db, msg, "area-bottom", r->in.info.info1->area.bottom);
419                 break;
420         default:
421                 return WERR_UNKNOWN_LEVEL;
422         }
423
424         ret = dsdb_replace(sptr_db, msg, 0);
425         if (ret != 0) {
426                 return WERR_FOOBAR;
427         }
428
429         return WERR_OK;
430 }
431
432 static WERROR sptr_DeletePrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
433                                          struct spoolss_DeleteForm *r)
434 {
435         struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
436         struct ldb_message **msgs;
437         const char * const attrs[] = { "flags", NULL};
438         int count, ret;
439         enum spoolss_FormFlags flags;
440
441         /* TODO: do checks access here
442          * if (!(server->access_mask & desired_access)) {
443          *      return WERR_FOOBAR;
444          * }
445          */
446
447         if (!r->in.form_name) {
448                 return WERR_FOOBAR;
449         }
450
451         count = sptr_db_search(sptr_db, mem_ctx,
452                                ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"),
453                                &msgs, attrs, "(&(form-name=%s)(objectclass=form))",
454                                r->in.form_name);
455
456         if (count == 0) return WERR_FOOBAR;
457         if (count > 1) return WERR_FOOBAR;
458         if (count < 0) return WERR_GENERAL_FAILURE;
459
460         flags = ldb_msg_find_attr_as_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN);
461         if (flags != SPOOLSS_FORM_USER) {
462                 return WERR_FOOBAR;
463         }
464
465         ret = ldb_delete(sptr_db, msgs[0]->dn);
466         if (ret != 0) {
467                 return WERR_FOOBAR;
468         }
469
470         return WERR_OK;
471 }
472
473 /* PrintServer Driver functions */
474 static WERROR sptr_EnumPrinterDrivers(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
475                                       struct spoolss_EnumPrinterDrivers *r)
476 {
477         return WERR_OK;
478 }
479
480 static WERROR sptr_GetPrinterDriverDirectory(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
481                                              struct spoolss_GetPrinterDriverDirectory *r)
482 {
483         union spoolss_DriverDirectoryInfo *info;
484         const char *prefix;
485         const char *postfix;
486
487         /*
488          * NOTE: normally r->in.level is 1, but both w2k3 and nt4 sp6a
489          *        are ignoring the r->in.level completely, so we do :-)
490          */
491        
492         /*
493          * TODO: check the server name is ours
494          * - if it's a invalid UNC then return WERR_INVALID_NAME
495          * - if it's the wrong host name return WERR_INVALID_PARAM
496          * - if it's "" then we need to return a local WINDOWS path
497          */
498         if (!r->in.server || !r->in.server[0]) {
499                 prefix = "C:\\DRIVERS";
500         } else {
501                 prefix = talloc_asprintf(mem_ctx, "%s\\print$", r->in.server);
502                 W_ERROR_HAVE_NO_MEMORY(prefix);
503         }
504
505         if (r->in.environment && strcmp(SPOOLSS_ARCHITECTURE_NT_X86, r->in.environment) == 0) {
506                 postfix = "W32X86";
507         } else {
508                 return WERR_INVALID_ENVIRONMENT;
509         }
510
511         info = talloc(mem_ctx, union spoolss_DriverDirectoryInfo);
512         W_ERROR_HAVE_NO_MEMORY(info);
513
514         info->info1.directory_name      = talloc_asprintf(mem_ctx, "%s\\%s", prefix, postfix);
515         W_ERROR_HAVE_NO_MEMORY(info->info1.directory_name);
516
517         r->out.info = info;
518         return WERR_OK;
519 }
520
521 /* Printer functions */
522 static WERROR sptr_EnumPrinters(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
523                                 struct spoolss_EnumPrinters *r)
524 {
525         struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context);
526         struct ldb_message **msgs;
527         int count;
528         int i;
529         union spoolss_PrinterInfo *info;
530
531         count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL,
532                                "(&(objectclass=printer))");
533
534         if (count == 0) return WERR_OK;
535         if (count < 0) return WERR_GENERAL_FAILURE;
536
537         info = talloc_array(mem_ctx, union spoolss_PrinterInfo, count);
538         W_ERROR_HAVE_NO_MEMORY(info);
539
540         switch(r->in.level) {
541         case 1:
542                 for (i = 0; i < count; i++) {
543                         info[i].info1.flags             = ldb_msg_find_attr_as_uint(msgs[i], "flags", 0);
544
545                         info[i].info1.name              = ldb_msg_find_attr_as_string(msgs[i], "name", "");
546                         W_ERROR_HAVE_NO_MEMORY(info[i].info1.name);
547
548                         info[i].info1.description       = ldb_msg_find_attr_as_string(msgs[i], "description", "");
549                         W_ERROR_HAVE_NO_MEMORY(info[i].info1.description);
550
551                         info[i].info1.comment           = ldb_msg_find_attr_as_string(msgs[i], "comment", NULL);
552                 }
553                 break;
554         case 2:
555                 for (i = 0; i < count; i++) {
556                         info[i].info2.servername        = ldb_msg_find_attr_as_string(msgs[i], "servername", "");
557                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);
558
559                         info[i].info2.printername       = ldb_msg_find_attr_as_string(msgs[i], "printername", "");
560                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);
561
562                         info[i].info2.sharename         = ldb_msg_find_attr_as_string(msgs[i], "sharename", "");
563                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.sharename);
564
565                         info[i].info2.portname          = ldb_msg_find_attr_as_string(msgs[i], "portname", "");
566                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.portname);
567
568                         info[i].info2.drivername        = ldb_msg_find_attr_as_string(msgs[i], "drivername", "");
569                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.drivername);
570
571                         info[i].info2.comment           = ldb_msg_find_attr_as_string(msgs[i], "comment", NULL);
572
573                         info[i].info2.location          = ldb_msg_find_attr_as_string(msgs[i], "location", NULL);
574
575                         info[i].info2.devmode           = NULL;
576
577                         info[i].info2.sepfile           = ldb_msg_find_attr_as_string(msgs[i], "sepfile", NULL);
578
579                         info[i].info2.printprocessor    = ldb_msg_find_attr_as_string(msgs[i], "printprocessor", "");
580                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.printprocessor);
581
582                         info[i].info2.datatype          = ldb_msg_find_attr_as_string(msgs[i], "datatype", "");
583                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.datatype);
584
585                         info[i].info2.parameters        = ldb_msg_find_attr_as_string(msgs[i], "parameters", NULL);
586
587                         info[i].info2.secdesc           = NULL;
588
589                         info[i].info2.attributes        = ldb_msg_find_attr_as_uint(msgs[i], "attributes", 0);
590                         info[i].info2.priority          = ldb_msg_find_attr_as_uint(msgs[i], "priority", 0);
591                         info[i].info2.defaultpriority   = ldb_msg_find_attr_as_uint(msgs[i], "defaultpriority", 0);
592                         info[i].info2.starttime         = ldb_msg_find_attr_as_uint(msgs[i], "starttime", 0);
593                         info[i].info2.untiltime         = ldb_msg_find_attr_as_uint(msgs[i], "untiltime", 0);
594                         info[i].info2.status            = ldb_msg_find_attr_as_uint(msgs[i], "status", 0);
595                         info[i].info2.cjobs             = ldb_msg_find_attr_as_uint(msgs[i], "cjobs", 0);
596                         info[i].info2.averageppm        = ldb_msg_find_attr_as_uint(msgs[i], "averageppm", 0);
597                 }
598                 break;
599         case 4:
600                 for (i = 0; i < count; i++) {
601                         info[i].info4.printername       = ldb_msg_find_attr_as_string(msgs[i], "printername", "");
602                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);
603
604                         info[i].info4.servername        = ldb_msg_find_attr_as_string(msgs[i], "servername", "");
605                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);
606
607                         info[i].info4.attributes        = ldb_msg_find_attr_as_uint(msgs[i], "attributes", 0);
608                 }
609                 break;
610         case 5:
611                 for (i = 0; i < count; i++) {
612                         info[i].info5.printername       = ldb_msg_find_attr_as_string(msgs[i], "name", "");
613                         W_ERROR_HAVE_NO_MEMORY(info[i].info5.printername);
614
615                         info[i].info5.portname          = ldb_msg_find_attr_as_string(msgs[i], "port", "");
616                         W_ERROR_HAVE_NO_MEMORY(info[i].info5.portname);
617
618                         info[i].info5.attributes        = ldb_msg_find_attr_as_uint(msgs[i], "attributes", 0);
619                         info[i].info5.device_not_selected_timeout = ldb_msg_find_attr_as_uint(msgs[i], "device_not_selected_timeout", 0);
620                         info[i].info5.transmission_retry_timeout  = ldb_msg_find_attr_as_uint(msgs[i], "transmission_retry_timeout", 0);
621                 }
622                 break;
623         default:
624                 return WERR_UNKNOWN_LEVEL;
625         }
626
627         *r->out.info    = info;
628         *r->out.count   = count;
629         return WERR_OK;
630 }
631
632 static WERROR sptr_OpenPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
633                                struct spoolss_OpenPrinterEx *r,
634                                const char *printer_name,
635                                struct ntptr_GenericHandle **printer)
636 {
637         return WERR_INVALID_PRINTER_NAME;
638 }
639
640 /* port functions */
641 static WERROR sptr_EnumPorts(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
642                              struct spoolss_EnumPorts *r)
643 {
644         struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context);
645         struct ldb_message **msgs;
646         int count;
647         int i;
648         union spoolss_PortInfo *info;
649
650         count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL,
651                                "(&(objectclass=port))");
652
653         if (count == 0) return WERR_OK;
654         if (count < 0) return WERR_GENERAL_FAILURE;
655
656         info = talloc_array(mem_ctx, union spoolss_PortInfo, count);
657         W_ERROR_HAVE_NO_MEMORY(info);
658
659         switch (r->in.level) {
660         case 1:
661                 for (i = 0; i < count; i++) {
662                         info[i].info1.port_name         = ldb_msg_find_attr_as_string(msgs[i], "port-name", "");
663                         W_ERROR_HAVE_NO_MEMORY(info[i].info1.port_name);
664                 }
665                 break;
666         case 2:
667                 for (i=0; i < count; i++) {
668                         info[i].info2.port_name         = ldb_msg_find_attr_as_string(msgs[i], "port-name", "");
669                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.port_name);
670
671                         info[i].info2.monitor_name      = ldb_msg_find_attr_as_string(msgs[i], "monitor-name", "");
672                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name);
673
674                         info[i].info2.description       = ldb_msg_find_attr_as_string(msgs[i], "description", "");
675                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.description);
676
677                         info[i].info2.port_type         = ldb_msg_find_attr_as_uint(msgs[i], "port-type", SPOOLSS_PORT_TYPE_WRITE);
678                         info[i].info2.reserved          = ldb_msg_find_attr_as_uint(msgs[i], "reserved", 0);
679                 }
680                 break;
681         default:
682                 return WERR_UNKNOWN_LEVEL;
683         }
684
685         *r->out.info    = info;
686         *r->out.count   = count;
687         return WERR_OK;
688 }
689
690 /* monitor functions */
691 static WERROR sptr_EnumMonitors(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
692                                 struct spoolss_EnumMonitors *r)
693 {
694         struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context);
695         struct ldb_message **msgs;
696         int count;
697         int i;
698         union spoolss_MonitorInfo *info;
699
700         count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL,
701                                "(&(objectclass=monitor))");
702
703         if (count == 0) return WERR_OK;
704         if (count < 0) return WERR_GENERAL_FAILURE;
705
706         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, count);
707         W_ERROR_HAVE_NO_MEMORY(info);
708
709         switch (r->in.level) {
710         case 1:
711                 for (i = 0; i < count; i++) {
712                         info[i].info1.monitor_name      = ldb_msg_find_attr_as_string(msgs[i], "monitor-name", "");
713                         W_ERROR_HAVE_NO_MEMORY(info[i].info1.monitor_name);
714                 }
715                 break;
716         case 2:
717                 for (i=0; i < count; i++) {
718                         info[i].info2.monitor_name      = ldb_msg_find_attr_as_string(msgs[i], "monitor-name", "");
719                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name);
720
721                         info[i].info2.environment       = ldb_msg_find_attr_as_string(msgs[i], "environment", "");
722                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.environment);
723
724                         info[i].info2.dll_name          = ldb_msg_find_attr_as_string(msgs[i], "dll-name", "");
725                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.dll_name);
726                 }
727                 break;
728         default:
729                 return WERR_UNKNOWN_LEVEL;
730         }
731
732         *r->out.info    = info;
733         *r->out.count   = count;
734         return WERR_OK;
735 }
736
737 /* Printer Form functions */
738 static WERROR sptr_GetPrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
739                                   struct spoolss_GetForm *r)
740 {
741         struct ldb_context *sptr_db = talloc_get_type(printer->ntptr->private_data, struct ldb_context);
742         struct ldb_message **msgs;
743         struct ldb_dn *base_dn;
744         int count;
745         union spoolss_FormInfo *info;
746
747         /* TODO: do checks access here
748          * if (!(printer->access_mask & desired_access)) {
749          *      return WERR_FOOBAR;
750          * }
751          */
752
753         base_dn = ldb_dn_new_fmt(mem_ctx, sptr_db, "CN=Forms,CN=%s,CN=Printers", printer->object_name);
754         W_ERROR_HAVE_NO_MEMORY(base_dn);
755
756         count = sptr_db_search(sptr_db, mem_ctx, base_dn, &msgs, NULL,
757                                "(&(form-name=%s)(objectClass=form))",
758                                r->in.form_name);
759
760         if (count == 0) return WERR_FOOBAR;
761         if (count > 1) return WERR_FOOBAR;
762         if (count < 0) return WERR_GENERAL_FAILURE;
763
764         info = talloc(mem_ctx, union spoolss_FormInfo);
765         W_ERROR_HAVE_NO_MEMORY(info);
766
767         switch (r->in.level) {
768         case 1:
769                 info->info1.flags       = ldb_msg_find_attr_as_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN);
770
771                 info->info1.form_name   = ldb_msg_find_attr_as_string(msgs[0], "form-name", NULL);
772                 W_ERROR_HAVE_NO_MEMORY(info->info1.form_name);
773
774                 info->info1.size.width  = ldb_msg_find_attr_as_uint(msgs[0], "size-width", 0);
775                 info->info1.size.height = ldb_msg_find_attr_as_uint(msgs[0], "size-height", 0);
776
777                 info->info1.area.left   = ldb_msg_find_attr_as_uint(msgs[0], "area-left", 0);
778                 info->info1.area.top    = ldb_msg_find_attr_as_uint(msgs[0], "area-top", 0);
779                 info->info1.area.right  = ldb_msg_find_attr_as_uint(msgs[0], "area-right", 0);
780                 info->info1.area.bottom = ldb_msg_find_attr_as_uint(msgs[0], "area-bottom", 0);
781                 break;
782         default:
783                 return WERR_UNKNOWN_LEVEL;
784         }
785
786         r->out.info     = info;
787         return WERR_OK;
788 }
789
790 static WERROR sptr_GetPrintProcessorDirectory(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
791                                               struct spoolss_GetPrintProcessorDirectory *r)
792 {
793         union spoolss_PrintProcessorDirectoryInfo *info;
794         const char *prefix;
795         const char *postfix;
796
797         /*
798          * NOTE: normally r->in.level is 1, but both w2k3 and nt4 sp6a
799          *        are ignoring the r->in.level completely, so we do :-)
800          */
801
802         /*
803          * TODO: check the server name is ours
804          * - if it's a invalid UNC then return WERR_INVALID_NAME
805          * - if it's the wrong host name return WERR_INVALID_PARAM
806          * - if it's "" then we need to return a local WINDOWS path
807          */
808         if (!r->in.server || !r->in.server[0]) {
809                 prefix = "C:\\PRTPROCS";
810         } else {
811                 prefix = talloc_asprintf(mem_ctx, "%s\\prnproc$", r->in.server);
812                 W_ERROR_HAVE_NO_MEMORY(prefix);
813         }
814
815         if (r->in.environment && strcmp(SPOOLSS_ARCHITECTURE_NT_X86, r->in.environment) == 0) {
816                 postfix = "W32X86";
817         } else {
818                 return WERR_INVALID_ENVIRONMENT;
819         }
820
821         info = talloc(mem_ctx, union spoolss_PrintProcessorDirectoryInfo);
822         W_ERROR_HAVE_NO_MEMORY(info);
823
824         info->info1.directory_name      = talloc_asprintf(mem_ctx, "%s\\%s", prefix, postfix);
825         W_ERROR_HAVE_NO_MEMORY(info->info1.directory_name);
826
827         r->out.info = info;
828         return WERR_OK;
829 }
830
831
832 /*
833   initialialise the simble ldb backend, registering ourselves with the ntptr subsystem
834  */
835 static const struct ntptr_ops ntptr_simple_ldb_ops = {
836         .name                           = "simple_ldb",
837         .init_context                   = sptr_init_context,
838
839         /* PrintServer functions */
840         .OpenPrintServer                = sptr_OpenPrintServer,
841 /*      .XcvDataPrintServer             = sptr_XcvDataPrintServer,
842 */
843         /* PrintServer PrinterData functions */
844 /*      .EnumPrintServerData            = sptr_EnumPrintServerData,
845 */      .GetPrintServerData             = sptr_GetPrintServerData,
846 /*      .SetPrintServerData             = sptr_SetPrintServerData,
847         .DeletePrintServerData          = sptr_DeletePrintServerData,
848 */
849         /* PrintServer Form functions */
850         .EnumPrintServerForms           = sptr_EnumPrintServerForms,
851         .AddPrintServerForm             = sptr_AddPrintServerForm,
852         .SetPrintServerForm             = sptr_SetPrintServerForm,
853         .DeletePrintServerForm          = sptr_DeletePrintServerForm,
854
855         /* PrintServer Driver functions */
856         .EnumPrinterDrivers             = sptr_EnumPrinterDrivers,
857 /*      .AddPrinterDriver               = sptr_AddPrinterDriver,
858         .DeletePrinterDriver            = sptr_DeletePrinterDriver,
859 */      .GetPrinterDriverDirectory      = sptr_GetPrinterDriverDirectory,
860
861         /* Port functions */
862         .EnumPorts                      = sptr_EnumPorts,
863 /*      .OpenPort                       = sptr_OpenPort,
864         .XcvDataPort                    = sptr_XcvDataPort,
865 */
866         /* Monitor functions */
867         .EnumMonitors                   = sptr_EnumMonitors,
868 /*      .OpenMonitor                    = sptr_OpenMonitor,
869         .XcvDataMonitor                 = sptr_XcvDataMonitor,
870 */
871         /* PrintProcessor functions */
872 /*      .EnumPrintProcessors            = sptr_EnumPrintProcessors,
873 */
874         .GetPrintProcessorDirectory     = sptr_GetPrintProcessorDirectory,
875
876         /* Printer functions */
877         .EnumPrinters                   = sptr_EnumPrinters,
878         .OpenPrinter                    = sptr_OpenPrinter,
879 /*      .AddPrinter                     = sptr_AddPrinter,
880         .GetPrinter                     = sptr_GetPrinter,
881         .SetPrinter                     = sptr_SetPrinter,
882         .DeletePrinter                  = sptr_DeletePrinter,
883         .XcvDataPrinter                 = sptr_XcvDataPrinter,
884 */
885         /* Printer Driver functions */
886 /*      .GetPrinterDriver               = sptr_GetPrinterDriver,
887 */
888         /* Printer PrinterData functions */
889 /*      .EnumPrinterData                = sptr_EnumPrinterData,
890         .GetPrinterData                 = sptr_GetPrinterData,
891         .SetPrinterData                 = sptr_SetPrinterData,
892         .DeletePrinterData              = sptr_DeletePrinterData,
893 */
894         /* Printer Form functions */
895 /*      .EnumPrinterForms               = sptr_EnumPrinterForms,
896         .AddPrinterForm                 = sptr_AddPrinterForm,
897 */      .GetPrinterForm                 = sptr_GetPrinterForm,
898 /*      .SetPrinterForm                 = sptr_SetPrinterForm,
899         .DeletePrinterForm              = sptr_DeletePrinterForm,
900 */
901         /* Printer Job functions */
902 /*      .EnumJobs                       = sptr_EnumJobs,
903         .AddJob                         = sptr_AddJob,
904         .ScheduleJob                    = sptr_ScheduleJob,
905         .GetJob                         = sptr_GetJob,
906         .SetJob                         = sptr_SetJob,
907 */
908         /* Printer Printing functions */
909 /*      .StartDocPrinter                = sptr_StartDocPrinter,
910         .EndDocPrinter                  = sptr_EndDocPrinter,
911         .StartPagePrinter               = sptr_StartPagePrinter,
912         .EndPagePrinter                 = sptr_EndPagePrinter,
913         .WritePrinter                   = sptr_WritePrinter,
914         .ReadPrinter                    = sptr_ReadPrinter,
915 */};
916
917 NTSTATUS ntptr_simple_ldb_init(void)
918 {
919         NTSTATUS ret;
920
921         ret = ntptr_register(&ntptr_simple_ldb_ops);
922         if (!NT_STATUS_IS_OK(ret)) {
923                 DEBUG(0,("Failed to register NTPTR '%s' backend!\n",
924                          ntptr_simple_ldb_ops.name));
925         }
926
927         return ret;
928 }