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