Merge branch 'selftest' of git://git.samba.org/jelmer/samba
[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 event_context *ev_ctx, struct loadparm_context *lp_ctx)
46 {
47         return ldb_wrap_connect(mem_ctx, ev_ctx, lp_ctx, lp_spoolss_url(lp_ctx), system_session(mem_ctx, lp_ctx), 
48                                 NULL, 0, NULL);
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 static WERROR sptr_GetPrintServerData(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
126                                       struct spoolss_GetPrinterData *r)
127 {
128         if (strcmp("W3SvcInstalled", r->in.value_name) == 0) {
129                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
130                 r->out.data.value       = 0;
131                 return WERR_OK;
132         } else if (strcmp("BeepEnabled", r->in.value_name) == 0) {
133                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
134                 r->out.data.value       = 0;
135                 return WERR_OK;
136         } else if (strcmp("EventLog", r->in.value_name) == 0) {
137                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
138                 r->out.data.value       = 0;
139                 return WERR_OK;
140         } else if (strcmp("NetPopup", r->in.value_name) == 0) {
141                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
142                 r->out.data.value       = 0;
143                 return WERR_OK;
144         } else if (strcmp("NetPopupToComputer", r->in.value_name) == 0) {
145                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
146                 r->out.data.value       = 0;
147                 return  WERR_OK;
148         } else if (strcmp("MajorVersion", r->in.value_name) == 0) {
149                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
150                 r->out.data.value       = 3;
151                 return WERR_OK;
152         } else if (strcmp("MinorVersion", r->in.value_name) == 0) {
153                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
154                 r->out.data.value       = 0;
155                 return WERR_OK;
156         } else if (strcmp("DefaultSpoolDirectory", r->in.value_name) == 0) {
157                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_STRING;
158                 r->out.data.string      = "C:\\PRINTERS";
159                 return  WERR_OK;
160         } else if (strcmp("Architecture", r->in.value_name) == 0) {
161                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_STRING;
162                 r->out.data.string      = SPOOLSS_ARCHITECTURE_NT_X86;
163                 return  WERR_OK;
164         } else if (strcmp("DsPresent", r->in.value_name) == 0) {
165                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_UINT32;
166                 r->out.data.value       = 1;
167                 return WERR_OK;
168         } else if (strcmp("OSVersion", r->in.value_name) == 0) {
169                 DATA_BLOB blob;
170                 enum ndr_err_code ndr_err;
171                 struct spoolss_OSVersion os;
172
173                 os.major                = dcesrv_common_get_version_major(mem_ctx, server->ntptr->lp_ctx);
174                 os.minor                = dcesrv_common_get_version_minor(mem_ctx, server->ntptr->lp_ctx);
175                 os.build                = dcesrv_common_get_version_build(mem_ctx, server->ntptr->lp_ctx);
176                 os.extra_string         = "";
177
178                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, lp_iconv_convenience(server->ntptr->lp_ctx), &os, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersion);
179                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
180                         return WERR_GENERAL_FAILURE;
181                 }
182
183                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_BINARY;
184                 r->out.data.binary      = blob;
185                 return WERR_OK;
186         } else if (strcmp("OSVersionEx", r->in.value_name) == 0) {
187                 DATA_BLOB blob;
188                 enum ndr_err_code ndr_err;
189                 struct spoolss_OSVersionEx os_ex;
190
191                 os_ex.major             = dcesrv_common_get_version_major(mem_ctx, server->ntptr->lp_ctx);
192                 os_ex.minor             = dcesrv_common_get_version_minor(mem_ctx, server->ntptr->lp_ctx);
193                 os_ex.build             = dcesrv_common_get_version_build(mem_ctx, server->ntptr->lp_ctx);
194                 os_ex.extra_string              = "";
195                 os_ex.unknown2          = 0;
196                 os_ex.unknown3          = 0;
197
198                 ndr_err = ndr_push_struct_blob(&blob, mem_ctx, lp_iconv_convenience(server->ntptr->lp_ctx), &os_ex, (ndr_push_flags_fn_t)ndr_push_spoolss_OSVersionEx);
199                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
200                         return WERR_GENERAL_FAILURE;
201                 }
202
203                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_BINARY;
204                 r->out.data.binary      = blob;
205                 return WERR_OK;
206         } else if (strcmp("DNSMachineName", r->in.value_name) == 0) {
207                 if (!lp_realm(server->ntptr->lp_ctx)) return WERR_INVALID_PARAM;
208
209                 r->out.type             = SPOOLSS_PRINTER_DATA_TYPE_STRING;
210                 r->out.data.string      = talloc_asprintf(mem_ctx, "%s.%s",
211                                                                    lp_netbios_name(server->ntptr->lp_ctx),
212                                                                    lp_realm(server->ntptr->lp_ctx));
213                 W_ERROR_HAVE_NO_MEMORY(r->out.data.string);
214                 return WERR_OK;
215         }
216
217         return WERR_INVALID_PARAM;
218 }
219
220 /* PrintServer Form functions */
221 static WERROR sptr_EnumPrintServerForms(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
222                                         struct spoolss_EnumForms *r)
223 {
224         struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
225         struct ldb_message **msgs;
226         int count;
227         int i;
228         union spoolss_FormInfo *info;
229
230         count = sptr_db_search(sptr_db, mem_ctx,
231                                 ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"),
232                                 &msgs, NULL, "(&(objectClass=form))");
233
234         if (count == 0) return WERR_OK;
235         if (count < 0) return WERR_GENERAL_FAILURE;
236
237         info = talloc_array(mem_ctx, union spoolss_FormInfo, count);
238         W_ERROR_HAVE_NO_MEMORY(info);
239
240         switch (r->in.level) {
241         case 1:
242                 for (i=0; i < count; i++) {
243                         info[i].info1.flags             = samdb_result_uint(msgs[i], "flags", SPOOLSS_FORM_BUILTIN);
244
245                         info[i].info1.form_name         = samdb_result_string(msgs[i], "form-name", NULL);
246                         W_ERROR_HAVE_NO_MEMORY(info[i].info1.form_name);
247
248                         info[i].info1.size.width        = samdb_result_uint(msgs[i], "size-width", 0);
249                         info[i].info1.size.height       = samdb_result_uint(msgs[i], "size-height", 0);
250
251                         info[i].info1.area.left         = samdb_result_uint(msgs[i], "area-left", 0);
252                         info[i].info1.area.top          = samdb_result_uint(msgs[i], "area-top", 0);
253                         info[i].info1.area.right        = samdb_result_uint(msgs[i], "area-right", 0);
254                         info[i].info1.area.bottom       = samdb_result_uint(msgs[i], "area-bottom", 0);
255                 }
256                 break;
257         default:
258                 return WERR_UNKNOWN_LEVEL;
259         }
260
261         r->out.info     = info;
262         r->out.count    = count;
263         return WERR_OK;
264 }
265
266 static WERROR sptr_AddPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
267                                       struct spoolss_AddForm *r)
268 {
269         struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
270         struct ldb_message *msg,**msgs;
271         const char * const attrs[] = {"flags", NULL };
272         int count, ret;
273
274         /* TODO: do checks access here
275          * if (!(server->access_mask & desired_access)) {
276          *      return WERR_FOOBAR;
277          * }
278          */
279
280         switch (r->in.level) {
281         case 1:
282                 if (!r->in.info.info1) {
283                         return WERR_FOOBAR;
284                 }
285                 count = sptr_db_search(sptr_db, mem_ctx,
286                                        ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"),
287                                        &msgs, attrs, "(&(form-name=%s)(objectClass=form))",
288                                        r->in.info.info1->form_name);
289
290                 if (count == 1) return WERR_FOOBAR;
291                 if (count > 1) return WERR_FOOBAR;
292                 if (count < 0) return WERR_GENERAL_FAILURE;
293
294                 if (r->in.info.info1->flags != SPOOLSS_FORM_USER) {
295                         return WERR_FOOBAR;
296                 }
297
298                 msg = ldb_msg_new(mem_ctx);
299                 W_ERROR_HAVE_NO_MEMORY(msg);
300
301                 /* add core elements to the ldb_message for the Form */
302                 msg->dn = ldb_dn_new_fmt(msg, sptr_db, "form-name=%s,CN=Forms,CN=PrintServer", r->in.info.info1->form_name);
303                 SET_STRING(sptr_db, msg, "objectClass", "form");
304
305                 SET_UINT(sptr_db, msg, "flags", r->in.info.info1->flags);
306
307                 SET_STRING(sptr_db, msg, "form-name", r->in.info.info1->form_name);
308
309                 SET_UINT(sptr_db, msg, "size-width", r->in.info.info1->size.width);
310                 SET_UINT(sptr_db, msg, "size-height", r->in.info.info1->size.height);
311
312                 SET_UINT(sptr_db, msg, "area-left", r->in.info.info1->area.left);
313                 SET_UINT(sptr_db, msg, "area-top", r->in.info.info1->area.top);
314                 SET_UINT(sptr_db, msg, "area-right", r->in.info.info1->area.right);
315                 SET_UINT(sptr_db, msg, "area-bottom", r->in.info.info1->area.bottom);
316                 break;
317         default:
318                 return WERR_UNKNOWN_LEVEL;
319         }
320
321         ret = ldb_add(sptr_db, msg);
322         if (ret != 0) {
323                 return WERR_FOOBAR;
324         }
325
326         return WERR_OK;
327 }
328
329 static WERROR sptr_SetPrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
330                                       struct spoolss_SetForm *r)
331 {
332         struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
333         struct ldb_message *msg,**msgs;
334         const char * const attrs[] = { "flags", NULL};
335         int count, ret;
336         enum spoolss_FormFlags flags;
337
338         /* TODO: do checks access here
339          * if (!(server->access_mask & desired_access)) {
340          *      return WERR_FOOBAR;
341          * }
342          */
343
344         switch (r->in.level) {
345         case 1:
346                 if (!r->in.info.info1) {
347                         return WERR_FOOBAR;
348                 }
349
350                 count = sptr_db_search(sptr_db, mem_ctx,
351                                        ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"),
352                                        &msgs, attrs, "(&(form-name=%s)(objectClass=form))",
353                                        r->in.info.info1->form_name);
354
355                 if (count == 0) return WERR_FOOBAR;
356                 if (count > 1) return WERR_FOOBAR;
357                 if (count < 0) return WERR_GENERAL_FAILURE;
358
359                 flags = samdb_result_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN);
360                 if (flags != SPOOLSS_FORM_USER) {
361                         return WERR_FOOBAR;
362                 }
363
364                 msg = ldb_msg_new(mem_ctx);
365                 W_ERROR_HAVE_NO_MEMORY(msg);
366
367                 /* add core elements to the ldb_message for the user */
368                 msg->dn = msgs[0]->dn;
369
370                 SET_UINT(sptr_db, msg, "flags", r->in.info.info1->flags);
371
372                 SET_STRING(sptr_db, msg, "form-name", r->in.info.info1->form_name);
373
374                 SET_UINT(sptr_db, msg, "size-width", r->in.info.info1->size.width);
375                 SET_UINT(sptr_db, msg, "size-height", r->in.info.info1->size.height);
376
377                 SET_UINT(sptr_db, msg, "area-left", r->in.info.info1->area.left);
378                 SET_UINT(sptr_db, msg, "area-top", r->in.info.info1->area.top);
379                 SET_UINT(sptr_db, msg, "area-right", r->in.info.info1->area.right);
380                 SET_UINT(sptr_db, msg, "area-bottom", r->in.info.info1->area.bottom);
381                 break;
382         default:
383                 return WERR_UNKNOWN_LEVEL;
384         }
385
386         ret = samdb_replace(sptr_db, mem_ctx, msg);
387         if (ret != 0) {
388                 return WERR_FOOBAR;
389         }
390
391         return WERR_OK;
392 }
393
394 static WERROR sptr_DeletePrintServerForm(struct ntptr_GenericHandle *server, TALLOC_CTX *mem_ctx,
395                                          struct spoolss_DeleteForm *r)
396 {
397         struct ldb_context *sptr_db = talloc_get_type(server->ntptr->private_data, struct ldb_context);
398         struct ldb_message **msgs;
399         const char * const attrs[] = { "flags", NULL};
400         int count, ret;
401         enum spoolss_FormFlags flags;
402
403         /* TODO: do checks access here
404          * if (!(server->access_mask & desired_access)) {
405          *      return WERR_FOOBAR;
406          * }
407          */
408
409         if (!r->in.form_name) {
410                 return WERR_FOOBAR;
411         }
412
413         count = sptr_db_search(sptr_db, mem_ctx,
414                                ldb_dn_new(mem_ctx, sptr_db, "CN=Forms,CN=PrintServer"),
415                                &msgs, attrs, "(&(form-name=%s)(objectclass=form))",
416                                r->in.form_name);
417
418         if (count == 0) return WERR_FOOBAR;
419         if (count > 1) return WERR_FOOBAR;
420         if (count < 0) return WERR_GENERAL_FAILURE;
421
422         flags = samdb_result_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN);
423         if (flags != SPOOLSS_FORM_USER) {
424                 return WERR_FOOBAR;
425         }
426
427         ret = ldb_delete(sptr_db, msgs[0]->dn);
428         if (ret != 0) {
429                 return WERR_FOOBAR;
430         }
431
432         return WERR_OK;
433 }
434
435 /* PrintServer Driver functions */
436 static WERROR sptr_EnumPrinterDrivers(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
437                                       struct spoolss_EnumPrinterDrivers *r)
438 {
439         return WERR_OK;
440 }
441
442 static WERROR sptr_GetPrinterDriverDirectory(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
443                                              struct spoolss_GetPrinterDriverDirectory *r)
444 {
445         union spoolss_DriverDirectoryInfo *info;
446         const char *prefix;
447         const char *postfix;
448
449         /*
450          * NOTE: normally r->in.level is 1, but both w2k3 and nt4 sp6a
451          *        are ignoring the r->in.level completely, so we do :-)
452          */
453        
454         /*
455          * TODO: check the server name is ours
456          * - if it's a invalid UNC then return WERR_INVALID_NAME
457          * - if it's the wrong host name return WERR_INVALID_PARAM
458          * - if it's "" then we need to return a local WINDOWS path
459          */
460         if (!r->in.server || !r->in.server[0]) {
461                 prefix = "C:\\DRIVERS";
462         } else {
463                 prefix = talloc_asprintf(mem_ctx, "%s\\print$", r->in.server);
464                 W_ERROR_HAVE_NO_MEMORY(prefix);
465         }
466
467         if (r->in.environment && strcmp(SPOOLSS_ARCHITECTURE_NT_X86, r->in.environment) == 0) {
468                 postfix = "W32X86";
469         } else {
470                 return WERR_INVALID_ENVIRONMENT;
471         }
472
473         info = talloc(mem_ctx, union spoolss_DriverDirectoryInfo);
474         W_ERROR_HAVE_NO_MEMORY(info);
475
476         info->info1.directory_name      = talloc_asprintf(mem_ctx, "%s\\%s", prefix, postfix);
477         W_ERROR_HAVE_NO_MEMORY(info->info1.directory_name);
478
479         r->out.info = info;
480         return WERR_OK;
481 }
482
483 /* Printer functions */
484 static WERROR sptr_EnumPrinters(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
485                                 struct spoolss_EnumPrinters *r)
486 {
487         struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context);
488         struct ldb_message **msgs;
489         int count;
490         int i;
491         union spoolss_PrinterInfo *info;
492
493         count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL,
494                                "(&(objectclass=printer))");
495
496         if (count == 0) return WERR_OK;
497         if (count < 0) return WERR_GENERAL_FAILURE;
498
499         info = talloc_array(mem_ctx, union spoolss_PrinterInfo, count);
500         W_ERROR_HAVE_NO_MEMORY(info);
501
502         switch(r->in.level) {
503         case 1:
504                 for (i = 0; i < count; i++) {
505                         info[i].info1.flags             = samdb_result_uint(msgs[i], "flags", 0);
506
507                         info[i].info1.name              = samdb_result_string(msgs[i], "name", "");
508                         W_ERROR_HAVE_NO_MEMORY(info[i].info1.name);
509
510                         info[i].info1.description       = samdb_result_string(msgs[i], "description", "");
511                         W_ERROR_HAVE_NO_MEMORY(info[i].info1.description);
512
513                         info[i].info1.comment           = samdb_result_string(msgs[i], "comment", NULL);
514                 }
515                 break;
516         case 2:
517                 for (i = 0; i < count; i++) {
518                         info[i].info2.servername        = samdb_result_string(msgs[i], "servername", "");
519                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);
520
521                         info[i].info2.printername       = samdb_result_string(msgs[i], "printername", "");
522                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);
523
524                         info[i].info2.sharename         = samdb_result_string(msgs[i], "sharename", "");
525                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.sharename);
526
527                         info[i].info2.portname          = samdb_result_string(msgs[i], "portname", "");
528                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.portname);
529
530                         info[i].info2.drivername        = samdb_result_string(msgs[i], "drivername", "");
531                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.drivername);
532
533                         info[i].info2.comment           = samdb_result_string(msgs[i], "comment", NULL);
534
535                         info[i].info2.location          = samdb_result_string(msgs[i], "location", NULL);
536
537                         info[i].info2.devmode           = NULL;
538
539                         info[i].info2.sepfile           = samdb_result_string(msgs[i], "sepfile", NULL);
540
541                         info[i].info2.printprocessor    = samdb_result_string(msgs[i], "printprocessor", "");
542                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.printprocessor);
543
544                         info[i].info2.datatype          = samdb_result_string(msgs[i], "datatype", "");
545                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.datatype);
546
547                         info[i].info2.parameters        = samdb_result_string(msgs[i], "parameters", NULL);
548
549                         info[i].info2.secdesc           = NULL;
550
551                         info[i].info2.attributes        = samdb_result_uint(msgs[i], "attributes", 0);
552                         info[i].info2.priority          = samdb_result_uint(msgs[i], "priority", 0);
553                         info[i].info2.defaultpriority   = samdb_result_uint(msgs[i], "defaultpriority", 0);
554                         info[i].info2.starttime         = samdb_result_uint(msgs[i], "starttime", 0);
555                         info[i].info2.untiltime         = samdb_result_uint(msgs[i], "untiltime", 0);
556                         info[i].info2.status            = samdb_result_uint(msgs[i], "status", 0);
557                         info[i].info2.cjobs             = samdb_result_uint(msgs[i], "cjobs", 0);
558                         info[i].info2.averageppm        = samdb_result_uint(msgs[i], "averageppm", 0);
559                 }
560                 break;
561         case 4:
562                 for (i = 0; i < count; i++) {
563                         info[i].info4.printername       = samdb_result_string(msgs[i], "printername", "");
564                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.printername);
565
566                         info[i].info4.servername        = samdb_result_string(msgs[i], "servername", "");
567                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.servername);
568
569                         info[i].info4.attributes        = samdb_result_uint(msgs[i], "attributes", 0);
570                 }
571                 break;
572         case 5:
573                 for (i = 0; i < count; i++) {
574                         info[i].info5.printername       = samdb_result_string(msgs[i], "name", "");
575                         W_ERROR_HAVE_NO_MEMORY(info[i].info5.printername);
576
577                         info[i].info5.portname          = samdb_result_string(msgs[i], "port", "");
578                         W_ERROR_HAVE_NO_MEMORY(info[i].info5.portname);
579
580                         info[i].info5.attributes        = samdb_result_uint(msgs[i], "attributes", 0);
581                         info[i].info5.device_not_selected_timeout = samdb_result_uint(msgs[i], "device_not_selected_timeout", 0);
582                         info[i].info5.transmission_retry_timeout  = samdb_result_uint(msgs[i], "transmission_retry_timeout", 0);
583                 }
584                 break;
585         default:
586                 return WERR_UNKNOWN_LEVEL;
587         }
588
589         r->out.info     = info;
590         r->out.count    = count;
591         return WERR_OK;
592 }
593
594 static WERROR sptr_OpenPrinter(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
595                                struct spoolss_OpenPrinterEx *r,
596                                const char *printer_name,
597                                struct ntptr_GenericHandle **printer)
598 {
599         return WERR_INVALID_PRINTER_NAME;
600 }
601
602 /* port functions */
603 static WERROR sptr_EnumPorts(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
604                              struct spoolss_EnumPorts *r)
605 {
606         struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context);
607         struct ldb_message **msgs;
608         int count;
609         int i;
610         union spoolss_PortInfo *info;
611
612         count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL,
613                                "(&(objectclass=port))");
614
615         if (count == 0) return WERR_OK;
616         if (count < 0) return WERR_GENERAL_FAILURE;
617
618         info = talloc_array(mem_ctx, union spoolss_PortInfo, count);
619         W_ERROR_HAVE_NO_MEMORY(info);
620
621         switch (r->in.level) {
622         case 1:
623                 for (i = 0; i < count; i++) {
624                         info[i].info1.port_name         = samdb_result_string(msgs[i], "port-name", "");
625                         W_ERROR_HAVE_NO_MEMORY(info[i].info1.port_name);
626                 }
627                 break;
628         case 2:
629                 for (i=0; i < count; i++) {
630                         info[i].info2.port_name         = samdb_result_string(msgs[i], "port-name", "");
631                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.port_name);
632
633                         info[i].info2.monitor_name      = samdb_result_string(msgs[i], "monitor-name", "");
634                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name);
635
636                         info[i].info2.description       = samdb_result_string(msgs[i], "description", "");
637                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.description);
638
639                         info[i].info2.port_type         = samdb_result_uint(msgs[i], "port-type", SPOOLSS_PORT_TYPE_WRITE);
640                         info[i].info2.reserved          = samdb_result_uint(msgs[i], "reserved", 0);
641                 }
642                 break;
643         default:
644                 return WERR_UNKNOWN_LEVEL;
645         }
646
647         r->out.info     = info;
648         r->out.count    = count;
649         return WERR_OK;
650 }
651
652 /* monitor functions */
653 static WERROR sptr_EnumMonitors(struct ntptr_context *ntptr, TALLOC_CTX *mem_ctx,
654                                 struct spoolss_EnumMonitors *r)
655 {
656         struct ldb_context *sptr_db = talloc_get_type(ntptr->private_data, struct ldb_context);
657         struct ldb_message **msgs;
658         int count;
659         int i;
660         union spoolss_MonitorInfo *info;
661
662         count = sptr_db_search(sptr_db, mem_ctx, NULL, &msgs, NULL,
663                                "(&(objectclass=monitor))");
664
665         if (count == 0) return WERR_OK;
666         if (count < 0) return WERR_GENERAL_FAILURE;
667
668         info = talloc_array(mem_ctx, union spoolss_MonitorInfo, count);
669         W_ERROR_HAVE_NO_MEMORY(info);
670
671         switch (r->in.level) {
672         case 1:
673                 for (i = 0; i < count; i++) {
674                         info[i].info1.monitor_name      = samdb_result_string(msgs[i], "monitor-name", "");
675                         W_ERROR_HAVE_NO_MEMORY(info[i].info1.monitor_name);
676                 }
677                 break;
678         case 2:
679                 for (i=0; i < count; i++) {
680                         info[i].info2.monitor_name      = samdb_result_string(msgs[i], "monitor-name", "");
681                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.monitor_name);
682
683                         info[i].info2.environment       = samdb_result_string(msgs[i], "environment", "");
684                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.environment);
685
686                         info[i].info2.dll_name          = samdb_result_string(msgs[i], "dll-name", "");
687                         W_ERROR_HAVE_NO_MEMORY(info[i].info2.dll_name);
688                 }
689                 break;
690         default:
691                 return WERR_UNKNOWN_LEVEL;
692         }
693
694         r->out.info     = info;
695         r->out.count    = count;
696         return WERR_OK;
697         return WERR_OK;
698 }
699
700 /* Printer Form functions */
701 static WERROR sptr_GetPrinterForm(struct ntptr_GenericHandle *printer, TALLOC_CTX *mem_ctx,
702                                   struct spoolss_GetForm *r)
703 {
704         struct ldb_context *sptr_db = talloc_get_type(printer->ntptr->private_data, struct ldb_context);
705         struct ldb_message **msgs;
706         struct ldb_dn *base_dn;
707         int count;
708         union spoolss_FormInfo *info;
709
710         /* TODO: do checks access here
711          * if (!(printer->access_mask & desired_access)) {
712          *      return WERR_FOOBAR;
713          * }
714          */
715
716         base_dn = ldb_dn_new_fmt(mem_ctx, sptr_db, "CN=Forms,CN=%s,CN=Printers", printer->object_name);
717         W_ERROR_HAVE_NO_MEMORY(base_dn);
718
719         count = sptr_db_search(sptr_db, mem_ctx, base_dn, &msgs, NULL,
720                                "(&(form-name=%s)(objectClass=form))",
721                                r->in.form_name);
722
723         if (count == 0) return WERR_FOOBAR;
724         if (count > 1) return WERR_FOOBAR;
725         if (count < 0) return WERR_GENERAL_FAILURE;
726
727         info = talloc(mem_ctx, union spoolss_FormInfo);
728         W_ERROR_HAVE_NO_MEMORY(info);
729
730         switch (r->in.level) {
731         case 1:
732                 info->info1.flags       = samdb_result_uint(msgs[0], "flags", SPOOLSS_FORM_BUILTIN);
733
734                 info->info1.form_name   = samdb_result_string(msgs[0], "form-name", NULL);
735                 W_ERROR_HAVE_NO_MEMORY(info->info1.form_name);
736
737                 info->info1.size.width  = samdb_result_uint(msgs[0], "size-width", 0);
738                 info->info1.size.height = samdb_result_uint(msgs[0], "size-height", 0);
739
740                 info->info1.area.left   = samdb_result_uint(msgs[0], "area-left", 0);
741                 info->info1.area.top    = samdb_result_uint(msgs[0], "area-top", 0);
742                 info->info1.area.right  = samdb_result_uint(msgs[0], "area-right", 0);
743                 info->info1.area.bottom = samdb_result_uint(msgs[0], "area-bottom", 0);
744                 break;
745         default:
746                 return WERR_UNKNOWN_LEVEL;
747         }
748
749         r->out.info     = info;
750         return WERR_OK;
751 }
752
753
754 /*
755   initialialise the simble ldb backend, registering ourselves with the ntptr subsystem
756  */
757 static const struct ntptr_ops ntptr_simple_ldb_ops = {
758         .name                           = "simple_ldb",
759         .init_context                   = sptr_init_context,
760
761         /* PrintServer functions */
762         .OpenPrintServer                = sptr_OpenPrintServer,
763 /*      .XcvDataPrintServer             = sptr_XcvDataPrintServer,
764 */
765         /* PrintServer PrinterData functions */
766 /*      .EnumPrintServerData            = sptr_EnumPrintServerData,
767 */      .GetPrintServerData             = sptr_GetPrintServerData,
768 /*      .SetPrintServerData             = sptr_SetPrintServerData,
769         .DeletePrintServerData          = sptr_DeletePrintServerData,
770 */
771         /* PrintServer Form functions */
772         .EnumPrintServerForms           = sptr_EnumPrintServerForms,
773         .AddPrintServerForm             = sptr_AddPrintServerForm,
774         .SetPrintServerForm             = sptr_SetPrintServerForm,
775         .DeletePrintServerForm          = sptr_DeletePrintServerForm,
776
777         /* PrintServer Driver functions */
778         .EnumPrinterDrivers             = sptr_EnumPrinterDrivers,
779 /*      .AddPrinterDriver               = sptr_AddPrinterDriver,
780         .DeletePrinterDriver            = sptr_DeletePrinterDriver,
781 */      .GetPrinterDriverDirectory      = sptr_GetPrinterDriverDirectory,
782
783         /* Port functions */
784         .EnumPorts                      = sptr_EnumPorts,
785 /*      .OpenPort                       = sptr_OpenPort,
786         .XcvDataPort                    = sptr_XcvDataPort,
787 */
788         /* Monitor functions */
789         .EnumMonitors                   = sptr_EnumMonitors,
790 /*      .OpenMonitor                    = sptr_OpenMonitor,
791         .XcvDataMonitor                 = sptr_XcvDataMonitor,
792 */
793         /* PrintProcessor functions */
794 /*      .EnumPrintProcessors            = sptr_EnumPrintProcessors,
795 */
796         /* Printer functions */
797         .EnumPrinters                   = sptr_EnumPrinters,
798         .OpenPrinter                    = sptr_OpenPrinter,
799 /*      .AddPrinter                     = sptr_AddPrinter,
800         .GetPrinter                     = sptr_GetPrinter,
801         .SetPrinter                     = sptr_SetPrinter,
802         .DeletePrinter                  = sptr_DeletePrinter,
803         .XcvDataPrinter                 = sptr_XcvDataPrinter,
804 */
805         /* Printer Driver functions */
806 /*      .GetPrinterDriver               = sptr_GetPrinterDriver,
807 */
808         /* Printer PrinterData functions */
809 /*      .EnumPrinterData                = sptr_EnumPrinterData,
810         .GetPrinterData                 = sptr_GetPrinterData,
811         .SetPrinterData                 = sptr_SetPrinterData,
812         .DeletePrinterData              = sptr_DeletePrinterData,
813 */
814         /* Printer Form functions */
815 /*      .EnumPrinterForms               = sptr_EnumPrinterForms,
816         .AddPrinterForm                 = sptr_AddPrinterForm,
817 */      .GetPrinterForm                 = sptr_GetPrinterForm,
818 /*      .SetPrinterForm                 = sptr_SetPrinterForm,
819         .DeletePrinterForm              = sptr_DeletePrinterForm,
820 */
821         /* Printer Job functions */
822 /*      .EnumJobs                       = sptr_EnumJobs,
823         .AddJob                         = sptr_AddJob,
824         .ScheduleJob                    = sptr_ScheduleJob,
825         .GetJob                         = sptr_GetJob,
826         .SetJob                         = sptr_SetJob,
827 */
828         /* Printer Printing functions */
829 /*      .StartDocPrinter                = sptr_StartDocPrinter,
830         .EndDocPrinter                  = sptr_EndDocPrinter,
831         .StartPagePrinter               = sptr_StartPagePrinter,
832         .EndPagePrinter                 = sptr_EndPagePrinter,
833         .WritePrinter                   = sptr_WritePrinter,
834         .ReadPrinter                    = sptr_ReadPrinter,
835 */};
836
837 NTSTATUS ntptr_simple_ldb_init(void)
838 {
839         NTSTATUS ret;
840
841         ret = ntptr_register(&ntptr_simple_ldb_ops);
842         if (!NT_STATUS_IS_OK(ret)) {
843                 DEBUG(0,("Failed to register NTPTR '%s' backend!\n",
844                          ntptr_simple_ldb_ops.name));
845         }
846
847         return ret;
848 }