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