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