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