Merge in sogo branch changes r3949-3962
[jelmer/openchange.git] / mapiproxy / libmapistore / mapistore_backend.c
1 /*
2    OpenChange Storage Abstraction Layer library
3
4    OpenChange Project
5
6    Note: init and load functions have been copied from
7    samba4/source4/param/util.c initially wrote by Jelmer.
8
9    Copyright (C) Jelmer Vernooij 2005-2007
10    Copyright (C) Julien Kerihuel 2009
11
12    This program is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 3 of the License, or
15    (at your option) any later version.
16    
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21    
22    You should have received a copy of the GNU General Public License
23    along with this program.  If not, see <http://www.gnu.org/licenses/>.
24  */
25
26 #include <sys/types.h>
27 #include <string.h>
28 #include <dlfcn.h>
29 #include <dirent.h>
30
31 #include "mapistore.h"
32 #include "mapistore_errors.h"
33 #include "mapistore_private.h"
34 #include <dlinklist.h>
35
36 #include <samba_util.h>
37 #include <util/debug.h>
38
39 /**
40    \file mapistore_backend.c
41
42    \brief mapistore backends management API
43  */
44
45
46 static struct mstore_backend {
47         struct mapistore_backend        *backend;
48 } *backends = NULL;
49
50 int                                     num_backends;
51
52
53 /**
54    \details Register mapistore backends
55
56    \param backend pointer to the mapistore backend to register
57
58    \return MAPISTORE_SUCCESS on success
59  */
60 _PUBLIC_ enum mapistore_error mapistore_backend_register(const void *_backend)
61 {
62         const struct mapistore_backend  *backend = _backend;
63         uint32_t                        i;
64
65         /* Sanity checks */
66         MAPISTORE_RETVAL_IF(!backend, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
67
68         for (i = 0; i < num_backends; i++) {
69                 if (backends[i].backend && backend && 
70                     backend->backend.name && backends[i].backend->backend.name &&
71                     !strcmp(backends[i].backend->backend.name, backend->backend.name)) {
72                         DEBUG(3, ("MAPISTORE backend '%s' already registered\n", backend->backend.name));
73                         return MAPISTORE_SUCCESS;
74                 }
75         }
76
77         backends = realloc_p(backends, struct mstore_backend, num_backends + 1);
78         if (!backends) {
79                 smb_panic("out of memory in mapistore_backend_register");
80         }
81
82         backends[num_backends].backend = smb_xmemdup(backend, sizeof (*backend));
83         backends[num_backends].backend->backend.name = smb_xstrdup(backend->backend.name);
84
85         num_backends++;
86
87         DEBUG(3, ("MAPISTORE backend '%s' registered\n", backend->backend.name));
88
89         return MAPISTORE_SUCCESS;
90 }
91
92 /**
93    \details Check if the specified backend is registered given its
94    name.
95
96    \param name backend's name to lookup
97
98    \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
99  */
100 _PUBLIC_ enum mapistore_error mapistore_backend_registered(const char *name)
101 {
102         int     i;
103
104         /* Sanity checks */
105         MAPISTORE_RETVAL_IF(!name, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
106
107         for (i = 0; i < num_backends; i++) {
108                 if (backends[i].backend && !strcmp(backends[i].backend->backend.name, name)) {
109                         return MAPISTORE_SUCCESS;
110                 }
111         }
112
113         return MAPISTORE_ERR_NOT_FOUND;
114 }
115
116
117 /**
118    \details Return the full path where mapistore backends are
119    installed.
120
121    \return Pointer to the full path where backends are installed.
122  */
123 _PUBLIC_ const char *mapistore_backend_get_installdir(void)
124 {
125         return MAPISTORE_BACKEND_INSTALLDIR;
126 }
127
128
129
130 /**
131    \details Obtain the backend init function from a shared library
132    file
133
134    \param path full path to the backend shared library
135
136    \return Pointer to the initialization function on success,
137    otherwise NULL.
138  */
139 static init_backend_fn load_backend(const char *path)
140 {
141         void    *handle;
142         void    *init_fn;
143
144         handle = dlopen(path, RTLD_NOW);
145         if (handle == NULL) {
146                 DEBUG(0, ("Unable to open %s: %s\n", path, dlerror()));
147                 return NULL;
148         }
149
150         init_fn = dlsym(handle, MAPISTORE_INIT_MODULE);
151
152         if (init_fn == NULL) {
153                 DEBUG(0, ("Unable to find %s() in %s: %s\n",
154                           MAPISTORE_INIT_MODULE, path, dlerror()));
155                 DEBUG(1, ("Loading mapistore backend '%s' failed\n", path));
156                 dlclose(handle);
157                 return NULL;
158         }
159
160         return (init_backend_fn) init_fn;
161 }
162
163
164 /**
165    \details Load backends from specified directory
166
167    \param mem_ctx pointer to the memory context
168    \param path name of the backend's shared library folder
169
170    \return allocated array of functions pointers to initialization
171    functions on success, otherwise NULL.
172  */
173 static init_backend_fn *load_backends(TALLOC_CTX *mem_ctx, const char *path)
174 {
175         DIR             *dir;
176         struct dirent   *entry;
177         char            *filename;
178         int             success = 0;
179         init_backend_fn *ret;
180
181         ret = talloc_array(mem_ctx, init_backend_fn, 2);
182         ret[0] = NULL;
183
184         dir = opendir(path);
185         if (dir == NULL) {
186                 talloc_free(ret);
187                 return NULL;
188         }
189
190         while ((entry = readdir(dir))) {
191                 if (ISDOT(entry->d_name) || ISDOTDOT(entry->d_name)) {
192                         continue;
193                 }
194                 
195                 filename = talloc_asprintf(mem_ctx, "%s/%s", path, entry->d_name);
196                 ret[success] = load_backend(filename);
197                 if (ret[success]) {
198                         ret = talloc_realloc(mem_ctx, ret, init_backend_fn, success + 2);
199                         success++;
200                         ret[success] = NULL;
201                 }
202
203                 talloc_free(filename);
204         }
205
206         closedir(dir);
207
208         return ret;
209 }
210
211
212 /**
213    \details Load the initialization functions from backends DSO
214
215    \param mem_ctx pointer to the memory context
216    \param path pointer to the backend's DSO folder
217
218    \return allocated array of functions pointers to initialization
219    functions on success, otherwise NULL.
220  */
221 _PUBLIC_ init_backend_fn *mapistore_backend_load(TALLOC_CTX *mem_ctx, const char *path)
222 {
223         if (!path) {
224                 path = mapistore_backend_get_installdir();
225         }
226
227         return load_backends(mem_ctx, path);
228 }
229
230
231 /**
232    \details Run specified initialization functions.
233
234    \param fns pointer to an array of mapistore backends initialization
235    functions
236
237    \return true on success, otherwise false
238  */
239 _PUBLIC_ bool mapistore_backend_run_init(init_backend_fn *fns)
240 {
241         int                             i;
242         bool                            ret = true;
243
244         if (fns == NULL) {
245                 return true;
246         }
247
248         for (i = 0; fns[i]; i++) {
249                 ret &= (bool)fns[i]();
250         }
251
252         return ret;
253 }
254
255
256 /**
257    \details Initialize mapistore backends
258
259    \param mem_ctx pointer to the memory context
260    \param path pointer to folder where mapistore backends are
261    installed
262
263    \return MAPISTORE_SUCCESS on success, otherwise
264    MAPISTORE_ERR_BACKEND_INIT
265  */
266 enum mapistore_error mapistore_backend_init(TALLOC_CTX *mem_ctx, const char *path)
267 {
268         init_backend_fn                 *ret;
269         bool                            status;
270         int                             retval;
271         int                             i;
272
273         ret = mapistore_backend_load(mem_ctx, path);
274         status = mapistore_backend_run_init(ret);
275         talloc_free(ret);
276
277         for (i = 0; i < num_backends; i++) {
278                 if (backends[i].backend) {
279                         retval = backends[i].backend->backend.init();
280                         if (retval != MAPISTORE_SUCCESS) {
281                                 DEBUG(3, ("[!] MAPISTORE backend '%s' initialization failed\n", backends[i].backend->backend.name));
282                         } else {
283                                 DEBUG(3, ("MAPISTORE backend '%s' loaded\n", backends[i].backend->backend.name));
284                         }
285                 }
286         }
287
288         return (status != true) ? MAPISTORE_SUCCESS : MAPISTORE_ERR_BACKEND_INIT;
289 }
290
291 /**
292    \details List backend contexts for given user
293
294    \param mem_ctx pointer to the memory context
295    \param namespace the backend namespace
296    \param uri the backend parameters which can be passes inline
297
298    \return a valid backend_context pointer on success, otherwise NULL
299  */
300 enum mapistore_error mapistore_backend_list_contexts(const char *username, struct tdb_wrap *tdbwrap, TALLOC_CTX *mem_ctx, struct mapistore_contexts_list **contexts_listP)
301 {
302         enum mapistore_error            retval;
303         int                             i;
304         struct mapistore_contexts_list  *contexts_list = NULL, *current_contexts_list;
305
306         MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
307         MAPISTORE_RETVAL_IF(!contexts_listP, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
308
309         for (i = 0; i < num_backends; i++) {
310                 retval = backends[i].backend->backend.list_contexts(username, tdbwrap, mem_ctx, &current_contexts_list);
311                 if (retval != MAPISTORE_SUCCESS) {
312                         return retval;
313                 }
314                 DLIST_CONCATENATE(contexts_list, current_contexts_list, void);
315         }
316
317         *contexts_listP = contexts_list;
318         (void) talloc_reference(mem_ctx, contexts_list);
319
320         return MAPISTORE_SUCCESS;
321 }
322
323 /**
324    \details Create backend context
325
326    \param mem_ctx pointer to the memory context
327    \param namespace the backend namespace
328    \param uri the backend parameters which can be passes inline
329
330    \return a valid backend_context pointer on success, otherwise NULL
331  */
332 enum mapistore_error mapistore_backend_create_context(TALLOC_CTX *mem_ctx, struct mapistore_connection_info *conn_info, struct tdb_wrap *tdbwrap,
333                                                       const char *namespace, const char *uri, uint64_t fid, struct backend_context **context_p)
334 {
335         struct backend_context          *context;
336         enum mapistore_error            retval;
337         bool                            found = false;
338         void                            *backend_object = NULL;
339         int                             i;
340
341         DEBUG(0, ("namespace is %s and backend_uri is '%s'\n", namespace, uri));
342
343         context = talloc_zero(NULL, struct backend_context);
344
345         for (i = 0; i < num_backends; i++) {
346                 if (backends[i].backend->backend.namespace && 
347                     !strcmp(namespace, backends[i].backend->backend.namespace)) {
348                         found = true;
349                         retval = backends[i].backend->backend.create_context(context, conn_info, tdbwrap, uri, &backend_object);
350                         if (retval != MAPISTORE_SUCCESS) {
351                                 goto end;
352                         }
353
354                         break;
355                 }
356         }
357
358         if (found == false) {
359                 DEBUG(0, ("MAPISTORE: no backend with namespace '%s' is available\n", namespace));
360                 retval = MAPISTORE_ERR_NOT_FOUND; 
361                 goto end;
362         }
363
364         context->backend_object = backend_object;
365         context->backend = backends[i].backend;
366         retval = context->backend->context.get_root_folder(backend_object, context, fid, &context->root_folder_object);
367         if (retval != MAPISTORE_SUCCESS) {
368                 goto end;
369         }
370
371         context->ref_count = 1;
372         context->uri = talloc_asprintf(context, "%s%s", namespace, uri);
373         *context_p = context;
374
375         (void) talloc_reference(mem_ctx, context);
376
377 end:
378         talloc_unlink(NULL, context);
379
380         return retval;
381 }
382
383
384 enum mapistore_error mapistore_backend_create_root_folder(const char *username, enum mapistore_context_role ctx_role, uint64_t fid, const char *name, TALLOC_CTX *mem_ctx, char **mapistore_urip)
385 {
386         enum mapistore_error            retval = MAPISTORE_ERR_NOT_FOUND;
387         int                             i;
388
389         for (i = 0; retval == MAPISTORE_ERR_NOT_FOUND && i < num_backends; i++) {
390                 retval = backends[i].backend->backend.create_root_folder(username, ctx_role, fid, name, mem_ctx, mapistore_urip);
391         }
392
393         return retval;
394 }
395
396 /**
397    \details Increase the ref count associated to a given backend
398
399    \param bctx pointer to the backend context
400
401    \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
402  */
403 _PUBLIC_ enum mapistore_error mapistore_backend_add_ref_count(struct backend_context *bctx)
404 {
405         if (!bctx) {
406                 return MAPISTORE_ERROR;
407         }
408
409         bctx->ref_count += 1;
410
411         return MAPISTORE_SUCCESS;
412 }
413
414
415 /**
416    \details Delete a context from the specified backend
417
418    \param bctx pointer to the backend context
419
420    \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
421  */
422 _PUBLIC_ enum mapistore_error mapistore_backend_delete_context(struct backend_context *bctx)
423 {
424         bctx->ref_count -= 1;
425         if (bctx->ref_count) {
426                 return MAPISTORE_ERR_REF_COUNT;
427         }
428
429         talloc_free(bctx);
430         
431         return MAPISTORE_SUCCESS;
432 }
433
434
435 /**
436    \details find the context matching given context identifier
437
438    \param backend_list_ctx pointer to the backend context list
439    \param context_id the context identifier to search
440
441    \return Pointer to the mapistore_backend context on success, otherwise NULL
442  */
443 _PUBLIC_ struct backend_context *mapistore_backend_lookup(struct backend_context_list *backend_list_ctx,
444                                                           uint32_t context_id)
445 {
446         struct backend_context_list     *el;
447
448         /* Sanity checks */
449         if (!backend_list_ctx) return NULL;
450
451         for (el = backend_list_ctx; el; el = el->next) {
452                 if (el->ctx && el->ctx->context_id == context_id) {
453                         return el->ctx;
454                 }
455         }
456
457         return NULL;
458 }
459
460 /**
461    \details find the context matching given uri string
462
463    \param backend_list_ctx pointer to the backend context list
464    \param uri the uri string to search
465
466    \return Pointer to the mapistore_backend context on success,
467    otherwise NULL
468  */
469 _PUBLIC_ struct backend_context *mapistore_backend_lookup_by_uri(struct backend_context_list *backend_list_ctx,
470                                                                  const char *uri)
471 {
472         struct backend_context_list     *el;
473
474         /* sanity checks */
475         if (!backend_list_ctx) return NULL;
476         if (!uri) return NULL;
477
478         for (el = backend_list_ctx; el; el = el->next) {
479                 if (el->ctx && el->ctx->uri &&
480                     !strcmp(el->ctx->uri, uri)) {
481                         return el->ctx;
482                 }
483         }
484         
485         return NULL;
486 }
487
488 /**
489    \details Return a pointer on backend functions given its name
490
491    \param mem_ctx pointer to the memory context
492    \param name the backend name to lookup
493
494    \return Allocated pointer to the mapistore_backend context on success,
495    otherwise NULL
496  */
497 _PUBLIC_ struct backend_context *mapistore_backend_lookup_by_name(TALLOC_CTX *mem_ctx, const char *name)
498 {
499         struct backend_context  *context = NULL;
500         int                     i;
501
502         /* Sanity checks */
503         if (!name) return NULL;
504
505         for (i = 0; i < num_backends; i++) {
506                 if (backends[i].backend && !strcmp(backends[i].backend->backend.name, name)) {
507                         context = talloc_zero(mem_ctx, struct backend_context);
508                         context->backend = backends[i].backend;
509                         context->ref_count = 0;
510                         context->uri = NULL;
511
512                         return context;
513                 }
514         }
515         return NULL;
516 }
517
518
519 enum mapistore_error mapistore_backend_get_path(struct backend_context *bctx, TALLOC_CTX *mem_ctx, uint64_t fmid, char **path)
520 {
521         enum mapistore_error    ret;
522         char                    *bpath = NULL;
523
524         ret = bctx->backend->context.get_path(bctx->backend_object, mem_ctx, fmid, &bpath);
525
526         if (!ret) {
527                 *path = talloc_asprintf(mem_ctx, "%s%s", bctx->backend->backend.namespace, bpath);
528         } else {
529                 *path = NULL;
530         }
531
532         return ret;
533 }
534
535 enum mapistore_error mapistore_backend_folder_open_folder(struct backend_context *bctx, void *folder, TALLOC_CTX *mem_ctx, uint64_t fid, void **child_folder)
536 {
537         return bctx->backend->folder.open_folder(folder, mem_ctx, fid, child_folder);
538 }
539
540 enum mapistore_error mapistore_backend_folder_create_folder(struct backend_context *bctx, void *folder,
541                                            TALLOC_CTX *mem_ctx, uint64_t fid, struct SRow *aRow, void **child_folder)
542 {
543         return bctx->backend->folder.create_folder(folder, mem_ctx, fid, aRow, child_folder);
544 }
545
546 enum mapistore_error mapistore_backend_folder_delete(struct backend_context *bctx, void *folder)
547 {
548         return bctx->backend->folder.delete(folder);
549 }
550
551 enum mapistore_error mapistore_backend_folder_open_message(struct backend_context *bctx, void *folder,
552                                           TALLOC_CTX *mem_ctx, uint64_t mid, bool read_write, void **messagep)
553 {
554         return bctx->backend->folder.open_message(folder, mem_ctx, mid, read_write, messagep);
555 }
556
557 enum mapistore_error mapistore_backend_folder_create_message(struct backend_context *bctx, void *folder, TALLOC_CTX *mem_ctx, uint64_t mid, uint8_t associated, void **messagep)
558 {
559         return bctx->backend->folder.create_message(folder, mem_ctx, mid, associated, messagep);
560 }
561
562 enum mapistore_error mapistore_backend_folder_delete_message(struct backend_context *bctx, void *folder, uint64_t mid, uint8_t flags)
563 {
564         return bctx->backend->folder.delete_message(folder, mid, flags);
565 }
566
567 enum mapistore_error mapistore_backend_folder_move_copy_messages(struct backend_context *bctx, void *target_folder, void *source_folder, uint32_t mid_count, uint64_t *source_mids, uint64_t *target_mids, struct Binary_r **target_change_keys, uint8_t want_copy)
568 {
569         return bctx->backend->folder.move_copy_messages(target_folder, source_folder, mid_count, source_mids, target_mids, target_change_keys, want_copy);
570 }
571
572 enum mapistore_error mapistore_backend_folder_get_deleted_fmids(struct backend_context *bctx, void *folder, TALLOC_CTX *mem_ctx, enum mapistore_table_type table_type, uint64_t change_num, struct I8Array_r **fmidsp, uint64_t *cnp)
573 {
574         return bctx->backend->folder.get_deleted_fmids(folder, mem_ctx, table_type, change_num, fmidsp, cnp);
575 }
576
577 enum mapistore_error mapistore_backend_folder_get_child_count(struct backend_context *bctx, void *folder, enum mapistore_table_type table_type, uint32_t *RowCount)
578 {
579         return bctx->backend->folder.get_child_count(folder, table_type, RowCount);
580 }
581
582 enum mapistore_error mapistore_backend_folder_get_child_fid_by_name(struct backend_context *bctx, void *folder, const char *name, uint64_t *fidp)
583 {
584         enum mapistore_error            ret = MAPISTORE_SUCCESS;
585         struct mapi_SRestriction        name_restriction;
586         void                            *table;
587         uint8_t                         status;
588         TALLOC_CTX                      *mem_ctx;
589         enum MAPITAGS                   col;
590         struct mapistore_property_data  *data_pointers;
591         uint32_t                        row_count;
592
593         mem_ctx = talloc_zero(NULL, TALLOC_CTX);
594         
595         if (mapistore_backend_folder_open_table(bctx, folder, mem_ctx, MAPISTORE_FOLDER_TABLE, 0, &table, &row_count)) {
596                 talloc_free(mem_ctx);
597                 return MAPISTORE_ERROR;
598         }
599
600         name_restriction.rt = RES_PROPERTY;
601         name_restriction.res.resProperty.relop = RELOP_EQ;
602         name_restriction.res.resProperty.ulPropTag = PR_DISPLAY_NAME_UNICODE;
603         name_restriction.res.resProperty.lpProp.ulPropTag = name_restriction.res.resProperty.ulPropTag;
604         name_restriction.res.resProperty.lpProp.value.lpszW = name;
605
606         col = PR_FID;
607         mapistore_backend_table_set_columns(bctx, table, 1, &col);
608         mapistore_backend_table_set_restrictions(bctx, table, &name_restriction, &status);
609         ret = mapistore_backend_table_get_row(bctx, table, mem_ctx, MAPISTORE_PREFILTERED_QUERY, 0, &data_pointers);
610         if (!ret) {
611                 if (data_pointers[0].error) {
612                         ret = MAPISTORE_ERROR;
613                 }
614                 else {
615                         *fidp = *(uint64_t *) data_pointers[0].data;
616                 }
617         }
618
619         talloc_free(mem_ctx);
620
621         return ret;
622 }
623
624 enum mapistore_error mapistore_backend_folder_open_table(struct backend_context *bctx, void *folder,
625                                                          TALLOC_CTX *mem_ctx, enum mapistore_table_type table_type, uint32_t handle_id, void **table, uint32_t *row_count)
626 {
627         return bctx->backend->folder.open_table(folder, mem_ctx, table_type, handle_id, table, row_count);
628 }
629
630 enum mapistore_error mapistore_backend_folder_modify_permissions(struct backend_context *bctx, void *folder,
631                                                 uint8_t flags, uint16_t pcount, struct PermissionData *permissions)
632 {
633         return bctx->backend->folder.modify_permissions(folder, flags, pcount, permissions);
634 }
635
636 enum mapistore_error mapistore_backend_message_get_message_data(struct backend_context *bctx, void *message, TALLOC_CTX *mem_ctx, struct mapistore_message **msg)
637 {
638         return bctx->backend->message.get_message_data(message, mem_ctx, msg);
639 }
640
641 enum mapistore_error mapistore_backend_message_modify_recipients(struct backend_context *bctx, void *message, struct SPropTagArray *columns, uint16_t count, struct mapistore_message_recipient *recipients)
642 {
643         return bctx->backend->message.modify_recipients(message, columns, count, recipients);
644 }
645
646 enum mapistore_error mapistore_backend_message_set_read_flag(struct backend_context *bctx, void *message, uint8_t flag)
647 {
648         return bctx->backend->message.set_read_flag(message, flag);
649 }
650
651 enum mapistore_error mapistore_backend_message_save(struct backend_context *bctx, void *message)
652 {
653         return bctx->backend->message.save(message);
654 }
655
656 enum mapistore_error mapistore_backend_message_submit(struct backend_context *bctx, void *message, enum SubmitFlags flags)
657 {
658         return bctx->backend->message.submit(message, flags);
659 }
660
661 enum mapistore_error mapistore_backend_message_open_attachment(struct backend_context *bctx, void *message, TALLOC_CTX *mem_ctx, uint32_t aid, void **attachment)
662 {
663         return bctx->backend->message.open_attachment(message, mem_ctx, aid, attachment);
664 }
665
666 enum mapistore_error mapistore_backend_message_create_attachment(struct backend_context *bctx, void *message, TALLOC_CTX *mem_ctx, void **attachment, uint32_t *aid)
667 {
668         return bctx->backend->message.create_attachment(message, mem_ctx, attachment, aid);
669 }
670
671 enum mapistore_error mapistore_backend_message_get_attachment_table(struct backend_context *bctx, void *message, TALLOC_CTX *mem_ctx, void **table, uint32_t *row_count)
672 {
673         return bctx->backend->message.get_attachment_table(message, mem_ctx, table, row_count);
674 }
675
676 enum mapistore_error mapistore_backend_message_attachment_open_embedded_message(struct backend_context *bctx, void *message, TALLOC_CTX *mem_ctx, void **embedded_message, uint64_t *mid, struct mapistore_message **msg)
677 {
678         return bctx->backend->message.open_embedded_message(message, mem_ctx, embedded_message, mid, msg);
679 }
680
681 enum mapistore_error mapistore_backend_table_get_available_properties(struct backend_context *bctx, void *table, TALLOC_CTX *mem_ctx, struct SPropTagArray **propertiesp)
682 {
683         return bctx->backend->table.get_available_properties(table, mem_ctx, propertiesp);
684 }
685
686 enum mapistore_error mapistore_backend_table_set_columns(struct backend_context *bctx, void *table, uint16_t count, enum MAPITAGS *properties)
687 {
688         return bctx->backend->table.set_columns(table, count, properties);
689 }
690
691 enum mapistore_error mapistore_backend_table_set_restrictions(struct backend_context *bctx, void *table, struct mapi_SRestriction *restrictions, uint8_t *table_status)
692 {
693         return bctx->backend->table.set_restrictions(table, restrictions, table_status);
694 }
695
696 enum mapistore_error mapistore_backend_table_set_sort_order(struct backend_context *bctx, void *table, struct SSortOrderSet *sort_order, uint8_t *table_status)
697 {
698         return bctx->backend->table.set_sort_order(table, sort_order, table_status);
699 }
700
701 enum mapistore_error mapistore_backend_table_get_row(struct backend_context *bctx, void *table, TALLOC_CTX *mem_ctx,
702                                                      enum mapistore_query_type query_type, uint32_t rowid,
703                                                      struct mapistore_property_data **data)
704 {
705         return bctx->backend->table.get_row(table, mem_ctx, query_type, rowid, data);
706 }
707
708 enum mapistore_error mapistore_backend_table_get_row_count(struct backend_context *bctx, void *table, enum mapistore_query_type query_type, uint32_t *row_countp)
709 {
710         return bctx->backend->table.get_row_count(table, query_type, row_countp);
711 }
712
713 enum mapistore_error mapistore_backend_table_handle_destructor(struct backend_context *bctx, void *table, uint32_t handle_id)
714 {
715         return bctx->backend->table.handle_destructor(table, handle_id);
716 }
717
718 enum mapistore_error mapistore_backend_properties_get_available_properties(struct backend_context *bctx, void *object, TALLOC_CTX *mem_ctx, struct SPropTagArray **propertiesp)
719 {
720         return bctx->backend->properties.get_available_properties(object, mem_ctx, propertiesp);
721 }
722
723 enum mapistore_error mapistore_backend_properties_get_properties(struct backend_context *bctx,
724                                                 void *object, TALLOC_CTX *mem_ctx,
725                                                 uint16_t count, enum MAPITAGS
726                                                 *properties,
727                                                 struct mapistore_property_data *data)
728 {
729         return bctx->backend->properties.get_properties(object, mem_ctx, count, properties, data);
730 }
731
732 enum mapistore_error mapistore_backend_properties_set_properties(struct backend_context *bctx, void *object, struct SRow *aRow)
733 {
734         return bctx->backend->properties.set_properties(object, aRow);
735 }
736
737 enum mapistore_error mapistore_backend_manager_generate_uri(struct backend_context *bctx, TALLOC_CTX *mem_ctx, 
738                                            const char *username, const char *folder, 
739                                            const char *message, const char *root_uri, char **uri)
740 {
741         return bctx->backend->manager.generate_uri(mem_ctx, username, folder, message, root_uri, uri);
742 }