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