b0a5ceb58486b844f78794f4f990b3e07510f299
[tridge/openchange.git] / branches / plugfest / libmapi / IMsgStore.c
1 /*
2    OpenChange MAPI implementation.
3
4    Copyright (C) Julien Kerihuel 2007-2008.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "libmapi/libmapi.h"
21 #include "libmapi/libmapi_private.h"
22
23
24 /**
25    \file IMsgStore.c
26
27    \brief Folders related operations
28  */
29
30
31 /**
32    \details Open a folder from the store
33  
34    \param obj_store the store to open a folder in (i.e. the parent)
35    \param id_folder the folder identifier
36    \param obj_folder the resulting open folder
37
38    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
39
40    \note Developers may also call GetLastError() to retrieve the last
41    MAPI error code. Possible MAPI error codes are:
42    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
43    - MAPI_E_CALL_FAILED: A network problem was encountered during the
44      transaction
45
46    \sa MAPIInitialize, OpenMsgStore, GetLastError
47  */
48 _PUBLIC_ enum MAPISTATUS OpenFolder(mapi_object_t *obj_store, 
49                                     mapi_id_t id_folder,
50                                     mapi_object_t *obj_folder)
51 {
52         struct mapi_request     *mapi_request;
53         struct mapi_response    *mapi_response;
54         struct EcDoRpc_MAPI_REQ *mapi_req;
55         struct OpenFolder_req   request;
56         struct mapi_session     *session;
57         NTSTATUS                status;
58         enum MAPISTATUS         retval;
59         uint32_t                size = 0;
60         TALLOC_CTX              *mem_ctx;
61         uint8_t                 logon_id;
62
63         /* Sanity checks */
64         OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
65         session = mapi_object_get_session(obj_store);
66         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
67
68         if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS)
69                 return retval;
70
71         mem_ctx = talloc_named(NULL, 0, "OpenFolder");
72
73         /* Fill the OpenFolder operation */
74         request.handle_idx = 0x1;
75         request.folder_id = id_folder;
76         request.OpenModeFlags = OpenModeFlags_Folder;
77         size += sizeof (uint8_t) + sizeof(uint64_t) + sizeof(uint8_t);
78
79         /* Fill the MAPI_REQ request */
80         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
81         mapi_req->opnum = op_MAPI_OpenFolder;
82         mapi_req->logon_id = logon_id;
83         mapi_req->handle_idx = 0;
84         mapi_req->u.mapi_OpenFolder = request;
85         size += 5;
86
87         /* Fill the mapi_request structure */
88         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
89         mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
90         mapi_request->length = size;
91         mapi_request->mapi_req = mapi_req;
92         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
93         mapi_request->handles[0] = mapi_object_get_handle(obj_store);
94         mapi_request->handles[1] = 0xffffffff;
95
96         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
97         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
98         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
99         retval = mapi_response->mapi_repl->error_code;
100         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);  
101
102         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
103
104         /* Set object session, id and handle */
105         mapi_object_set_session(obj_folder, session);
106         mapi_object_set_id(obj_folder, id_folder);
107         mapi_object_set_handle(obj_folder, mapi_response->handles[1]);
108         mapi_object_set_logon_id(obj_folder, logon_id);
109
110         talloc_free(mapi_response);
111         talloc_free(mem_ctx);
112
113         return MAPI_E_SUCCESS;
114 }
115
116
117 /**
118    \details Determine if a public folder is ghosted.
119
120    This function returns whether a public folder is ghosted or not.
121
122    \param obj_store the store of the public folder
123    \param obj_folder the folder we are querying for ghost
124    \param IsGhosted pointer on the boolean value returned
125
126    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
127
128    \note Developers may also call GetLastError() to retrieve the last
129    MAPI error code. Possible MAPI error codes are:
130    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
131    - MAPI_E_CALL_FAILED: A network problem was encountered during the
132      transaction
133 */
134 _PUBLIC_ enum MAPISTATUS PublicFolderIsGhosted(mapi_object_t *obj_store,
135                                                mapi_object_t *obj_folder,
136                                                bool *IsGhosted)
137 {
138         struct mapi_request                     *mapi_request;
139         struct mapi_response                    *mapi_response;
140         struct EcDoRpc_MAPI_REQ                 *mapi_req;
141         struct PublicFolderIsGhosted_req        request;
142         struct mapi_session                     *session[2];
143         NTSTATUS                                status;
144         enum MAPISTATUS                         retval;
145         uint32_t                                size = 0;
146         TALLOC_CTX                              *mem_ctx;
147         mapi_id_t                               folderId;
148         uint8_t                                 logon_id;
149
150         /* Sanity checks */
151         OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
152         OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
153         
154         session[0] = mapi_object_get_session(obj_store);
155         session[1] = mapi_object_get_session(obj_folder);
156         OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
157         OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
158         OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
159
160         if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS)
161                 return retval;
162
163         folderId = mapi_object_get_id(obj_folder);
164         OPENCHANGE_RETVAL_IF(!folderId, MAPI_E_INVALID_PARAMETER, NULL);
165
166         mem_ctx = talloc_named(NULL, 0, "PublicFolderIsGhosted");
167         size = 0;
168
169         /* Fill the PublicFolderIsGhosted operation */
170         request.FolderId = folderId;
171         size += sizeof (uint64_t);
172
173         /* Fill the MAPI_REQ request */
174         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
175         mapi_req->opnum = op_MAPI_PublicFolderIsGhosted;
176         mapi_req->logon_id = logon_id;
177         mapi_req->handle_idx = 0;
178         mapi_req->u.mapi_PublicFolderIsGhosted = request;
179         size += 5;
180
181         /* Fill the mapi_request structure */
182         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
183         mapi_request->mapi_len = size + sizeof (uint32_t);
184         mapi_request->length = size;
185         mapi_request->mapi_req = mapi_req;
186         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
187         mapi_request->handles[0] = mapi_object_get_handle(obj_store);
188
189         status = emsmdb_transaction_wrapper(session[0], mem_ctx, mapi_request, &mapi_response);
190         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
191         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
192         retval = mapi_response->mapi_repl->error_code;
193         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
194
195         OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
196
197         *IsGhosted = mapi_response->mapi_repl->u.mapi_PublicFolderIsGhosted.IsGhosted;
198         
199         talloc_free(mapi_response);
200         talloc_free(mem_ctx);
201         
202         return MAPI_E_SUCCESS;
203 }
204
205
206 /**
207    \details Open a NNTP Public Folder given its name
208
209    \param obj_folder the parent folder
210    \param obj_child the resulting open folder
211    \param name the folder name
212
213    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
214
215    \note Developers may also call GetLastError() to retrieve the last
216    MAPI error code. Possible MAPI error codes are:
217    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
218    - MAPI_E_CALL_FAILED: A network problem was encountered during the
219      transaction
220
221    \sa OpenPublicFolder
222  */
223 _PUBLIC_ enum MAPISTATUS OpenPublicFolderByName(mapi_object_t *obj_folder,
224                                                 mapi_object_t *obj_child,
225                                                 const char *name)
226 {
227         struct mapi_request                     *mapi_request;
228         struct mapi_response                    *mapi_response;
229         struct EcDoRpc_MAPI_REQ                 *mapi_req;
230         struct OpenPublicFolderByName_req       request;
231         struct mapi_session                     *session;
232         NTSTATUS                                status;
233         enum MAPISTATUS                         retval;
234         uint32_t                                size = 0;
235         TALLOC_CTX                              *mem_ctx;
236         uint8_t                                 logon_id;
237
238         /* Sanity checks */
239         OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
240         OPENCHANGE_RETVAL_IF(!obj_child, MAPI_E_INVALID_PARAMETER, NULL);
241         OPENCHANGE_RETVAL_IF(!name, MAPI_E_INVALID_PARAMETER, NULL);
242         session = mapi_object_get_session(obj_folder);
243         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
244
245         if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
246                 return retval;
247
248         mem_ctx = talloc_named(NULL, 0, "OpenPublicFolderByName");
249         size = 0;
250
251         /* Fill the OpenPublicFolderByName operation */
252         request.handle_idx = 0x1;
253         size += sizeof (uint8_t);
254
255         /* name is prefixed with 32 bit [size] */
256         request.name = name;
257         size += strlen(name) + 1 + sizeof (uint32_t);
258         
259         /* Fill the MAPI_REQ request */
260         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
261         mapi_req->opnum = op_MAPI_OpenPublicFolderByName;
262         mapi_req->logon_id = logon_id;
263         mapi_req->handle_idx = 0;
264         mapi_req->u.mapi_OpenPublicFolderByName = request;
265         size += 5;
266
267         /* Fill the mapi_request structure */
268         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
269         mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
270         mapi_request->length = size;
271         mapi_request->mapi_req = mapi_req;
272         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
273         mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
274         mapi_request->handles[1] = 0xffffffff;
275
276         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
277         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
278         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
279         retval = mapi_response->mapi_repl->error_code;
280         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
281
282         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
283
284         /* Set object session and handle */
285         mapi_object_set_session(obj_child, session);
286         mapi_object_set_handle(obj_child, mapi_response->handles[1]);
287         mapi_object_set_logon_id(obj_child, logon_id);
288
289         talloc_free(mapi_response);
290         talloc_free(mem_ctx);
291
292         return MAPI_E_SUCCESS;
293 }
294
295
296 /**
297    \details Sets a folder as the destination for incoming messages of
298    a particular message class.
299
300    \param obj_store the store to set the receive folder for
301    \param obj_folder the destination folder
302    \param lpszMessageClass the message class the folder will receive
303
304    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
305
306    \note Developers may also call GetLastError() to retrieve the last
307    MAPI error code. Possible MAPI error codes are:
308    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
309    - MAPI_E_CALL_FAILED: A network problem was encountered during the
310    transaction
311
312    \sa GetReceiveFolder, GetReceiveFolderTable
313  */
314 _PUBLIC_ enum MAPISTATUS SetReceiveFolder(mapi_object_t *obj_store,
315                                           mapi_object_t *obj_folder,
316                                           const char *lpszMessageClass)
317 {
318         struct mapi_request             *mapi_request;
319         struct mapi_response            *mapi_response;
320         struct EcDoRpc_MAPI_REQ         *mapi_req;
321         struct SetReceiveFolder_req     request;
322         struct mapi_session             *session;
323         NTSTATUS                        status;
324         enum MAPISTATUS                 retval;
325         uint32_t                        size;
326         TALLOC_CTX                      *mem_ctx;
327         uint8_t                         logon_id;
328
329         /* Sanity checks */
330         OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
331         OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
332         OPENCHANGE_RETVAL_IF(!lpszMessageClass, MAPI_E_INVALID_PARAMETER, NULL);
333         session = mapi_object_get_session(obj_store);
334         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
335         if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS)
336                 return retval;
337
338         mem_ctx = talloc_named(NULL, 0, "SetReceiveFolder");
339
340         /* Fill the SetReceiveFolder operation */
341         size = 0;
342         request.fid = mapi_object_get_id(obj_folder);
343         size += sizeof (uint64_t);
344         request.lpszMessageClass = lpszMessageClass;
345         size += strlen(lpszMessageClass) + 1;
346
347         /* Fill the MAPI_REQ request */
348         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
349         mapi_req->opnum = op_MAPI_SetReceiveFolder;
350         mapi_req->logon_id = logon_id;
351         mapi_req->handle_idx = 0;
352         mapi_req->u.mapi_SetReceiveFolder = request;
353         size += 5;
354
355         /* Fill the mapi_request structure */
356         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
357         mapi_request->mapi_len = size + sizeof (uint32_t);
358         mapi_request->length = size;
359         mapi_request->mapi_req = mapi_req;
360         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
361         mapi_request->handles[0] = mapi_object_get_handle(obj_store);
362
363         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
364         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
365         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
366         retval = mapi_response->mapi_repl->error_code;
367         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
368
369         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
370
371         talloc_free(mapi_response);
372         talloc_free(mem_ctx);
373
374         return MAPI_E_SUCCESS;
375 }
376
377
378 /**
379    \details Gets the receive folder for incoming messages of a
380    particular message class.
381
382    This function obtains the folder that was established as the
383    destination for incoming messages of a specified message class, or
384    the default receive folder for the message store.
385
386    \param obj_store the store to get the receiver folder for
387    \param id_folder the resulting folder identification
388    \param MessageClass which message class to find the receivefolder
389    for
390
391    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
392
393    \note Developers may also call GetLastError() to retrieve the last
394    MAPI error code. Possible MAPI error codes are:
395    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
396    - MAPI_E_CALL_FAILED: A network problem was encountered during the
397      transaction
398
399    \sa MAPIInitialize, OpenMsgStore, GetLastError, SetReceiveFolder,
400    GetReceiveFolderTable
401 */
402 _PUBLIC_ enum MAPISTATUS GetReceiveFolder(mapi_object_t *obj_store, 
403                                           mapi_id_t *id_folder,
404                                           const char *MessageClass)
405 {
406         struct mapi_request             *mapi_request;
407         struct mapi_response            *mapi_response;
408         struct EcDoRpc_MAPI_REQ         *mapi_req;
409         struct GetReceiveFolder_req     request;
410         struct mapi_session             *session;
411         NTSTATUS                        status;
412         enum MAPISTATUS                 retval;
413         uint32_t                        size = 0;
414         TALLOC_CTX                      *mem_ctx;
415         uint8_t                         logon_id;
416
417         /* Sanity checks */
418         OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
419         session = mapi_object_get_session(obj_store);
420         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
421         if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS)
422                 return retval;
423
424         mem_ctx = talloc_named(NULL, 0, "GetReceiveFolder");
425
426         *id_folder = 0;
427
428         /* Fill the GetReceiveFolder operation */
429         if (!MessageClass) {
430                 request.MessageClass = "";
431                 size += 1;
432         } else {
433                 request.MessageClass = MessageClass;
434                 size += strlen (MessageClass) + 1;
435         }
436
437         /* Fill the MAPI_REQ request */
438         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
439         mapi_req->opnum = op_MAPI_GetReceiveFolder;
440         mapi_req->logon_id = logon_id;
441         mapi_req->handle_idx = 0;
442         mapi_req->u.mapi_GetReceiveFolder = request;
443         size += 5;
444
445         /* Fill the mapi_request structure */
446         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
447         mapi_request->mapi_len = size + sizeof (uint32_t);
448         mapi_request->length = size;
449         mapi_request->mapi_req = mapi_req;
450         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
451         mapi_request->handles[0] = mapi_object_get_handle(obj_store);
452
453         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
454         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
455         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
456         retval = mapi_response->mapi_repl->error_code;
457         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
458
459         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
460
461         *id_folder = mapi_response->mapi_repl->u.mapi_GetReceiveFolder.folder_id;
462
463         talloc_free(mapi_response);
464         talloc_free(mem_ctx);
465
466         return MAPI_E_SUCCESS;
467 }
468
469
470 /**
471    \details Retrieve the receive folder table which includes all the
472    information about the receive folders for the message store
473
474    \param obj_store the message store object
475    \param SRowSet pointer on a SRowSet structure with
476    GetReceiveFolderTable results.
477
478    Developers are required to call MAPIFreeBuffer(SRowSet.aRow) when
479    they don't need the folder table data anymore.
480
481    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
482
483    \note Developers may also call GetLastError() to retrieve the last
484    MAPI error code. Possible MAPI error codes are:
485    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
486    - MAPI_E_CALL_FAILED: A network problem was encountered during the
487      transaction
488
489    \sa GetReceiveFolder, SetReceiveFolder
490  */
491 _PUBLIC_ enum MAPISTATUS GetReceiveFolderTable(mapi_object_t *obj_store, 
492                                                struct SRowSet *SRowSet)
493 {
494         struct mapi_request                     *mapi_request;
495         struct mapi_response                    *mapi_response;
496         struct EcDoRpc_MAPI_REQ                 *mapi_req;
497         struct GetReceiveFolderTable_repl       *reply;
498         struct mapi_session                     *session;
499         NTSTATUS                                status;
500         enum MAPISTATUS                         retval;
501         uint32_t                                size = 0;
502         TALLOC_CTX                              *mem_ctx;
503         uint32_t                                i;
504         uint8_t                                 logon_id;
505
506         /* Sanity checks */
507         OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
508         session = mapi_object_get_session(obj_store);
509         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
510         if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS)
511                 return retval;
512
513         mem_ctx = talloc_named(NULL, 0, "GetReceiveFolderTable");
514         size = 0;
515
516         /* Fill the MAPI_REQ request */
517         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
518         mapi_req->opnum = op_MAPI_GetReceiveFolderTable;
519         mapi_req->logon_id = logon_id;
520         mapi_req->handle_idx = 0;
521         size += 5;
522
523         /* Fill the mapi_request structure */
524         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
525         mapi_request->mapi_len = size + sizeof (uint32_t);
526         mapi_request->length = size;
527         mapi_request->mapi_req = mapi_req;
528         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
529         mapi_request->handles[0] = mapi_object_get_handle(obj_store);
530
531         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
532         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
533         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
534         retval = mapi_response->mapi_repl->error_code;
535         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
536
537         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
538
539         reply = &mapi_response->mapi_repl->u.mapi_GetReceiveFolderTable;
540
541         /* Retrieve the ReceiveFolderTable entries */
542         SRowSet->cRows = reply->cValues;
543         SRowSet->aRow = talloc_array((TALLOC_CTX *)session, struct SRow, reply->cValues);
544         
545         for (i = 0; i < reply->cValues; i++) {
546                 SRowSet->aRow[i].ulAdrEntryPad = 0;
547                 SRowSet->aRow[i].cValues = 3;
548                 SRowSet->aRow[i].lpProps = talloc_array((TALLOC_CTX *)SRowSet->aRow, struct SPropValue, 
549                                                         SRowSet->aRow[i].cValues);
550
551                 SRowSet->aRow[i].lpProps[0].ulPropTag = PR_FID;
552                 SRowSet->aRow[i].lpProps[0].dwAlignPad = 0x0;
553                 SRowSet->aRow[i].lpProps[0].value.d = reply->entries[i].fid;
554
555                 if (reply->entries[i].lpszMessageClass && strlen(reply->entries[i].lpszMessageClass)) {
556                         SRowSet->aRow[i].lpProps[1].ulPropTag = PR_MESSAGE_CLASS;
557                         SRowSet->aRow[i].lpProps[1].dwAlignPad = 0x0;
558                         SRowSet->aRow[i].lpProps[1].value.lpszA = talloc_strdup((TALLOC_CTX *)SRowSet->aRow[i].lpProps, reply->entries[i].lpszMessageClass);
559                 } else {
560                         SRowSet->aRow[i].lpProps[1].ulPropTag = PR_MESSAGE_CLASS;
561                         SRowSet->aRow[i].lpProps[1].dwAlignPad = 0x0;
562                         SRowSet->aRow[i].lpProps[1].value.lpszA = "";
563                 }
564
565                 SRowSet->aRow[i].lpProps[2].ulPropTag = PR_LAST_MODIFICATION_TIME;
566                 SRowSet->aRow[i].lpProps[2].dwAlignPad = 0x0;
567                 SRowSet->aRow[i].lpProps[2].value.ft.dwLowDateTime = reply->entries[i].modiftime.dwLowDateTime;
568                 SRowSet->aRow[i].lpProps[2].value.ft.dwHighDateTime = reply->entries[i].modiftime.dwHighDateTime;
569         }
570
571         talloc_free(mapi_response);
572         talloc_free(mem_ctx);
573         
574         return MAPI_E_SUCCESS;
575 }
576
577
578 /**
579    \details Retrieves the folder ID of the temporary transport folder.
580
581    \param obj_store the server object
582    \param FolderId pointer on the returning Folder identifier
583
584    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
585
586    \note Developers may also call GetLastError() to retrieve the last
587    MAPI error code. Possible MAPI error codes are:
588    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
589    - MAPI_E_CALL_FAILED: A network problem was encountered during the
590      transaction
591  */
592 _PUBLIC_ enum MAPISTATUS GetTransportFolder(mapi_object_t *obj_store,
593                                             mapi_id_t *FolderId)
594 {
595         struct mapi_request             *mapi_request;
596         struct mapi_response            *mapi_response;
597         struct EcDoRpc_MAPI_REQ         *mapi_req;
598         struct GetTransportFolder_repl  *reply;
599         struct mapi_session             *session;
600         NTSTATUS                        status;
601         enum MAPISTATUS                 retval;
602         uint32_t                        size = 0;
603         TALLOC_CTX                      *mem_ctx;
604         uint8_t                         logon_id;
605
606         /* Sanity checks */
607         OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
608         OPENCHANGE_RETVAL_IF(!FolderId, MAPI_E_INVALID_PARAMETER, NULL);
609         session = mapi_object_get_session(obj_store);
610         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
611         if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS)
612                 return retval;
613
614         mem_ctx = talloc_named(NULL, 0, "GetTransportFolder");
615         size = 0;
616
617         /* Fill the MAPI_REQ request */
618         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
619         mapi_req->opnum = op_MAPI_GetTransportFolder;
620         mapi_req->logon_id = logon_id;
621         mapi_req->handle_idx = 0;
622         size += 5;
623
624         /* Fill the mapi_request structure */
625         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
626         mapi_request->mapi_len = size + sizeof (uint32_t);
627         mapi_request->length = size;
628         mapi_request->mapi_req = mapi_req;
629         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
630         mapi_request->handles[0] = mapi_object_get_handle(obj_store);
631
632         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
633         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
634         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
635         retval = mapi_response->mapi_repl->error_code;
636         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
637
638         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
639
640         /* Retrieve the FolderId parameter */
641         reply = &mapi_response->mapi_repl->u.mapi_GetTransportFolder;
642         *FolderId = reply->FolderId;
643
644         talloc_free(mapi_response);
645         talloc_free(mem_ctx);
646
647         return MAPI_E_SUCCESS;
648 }
649
650
651 /**
652    \details Get the list of servers that host replicas of a given
653    public folder.
654
655    \param obj_store the public folder store object
656    \param obj_folder the folder object we search replica for
657    \param OwningServersCount number of OwningServers
658    \param CheapServersCount number of low-cost servers
659    \param OwningServers pointer on the list of NULL terminated ASCII
660    string representing replica servers
661
662    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
663
664    \note ecNoReplicaAvailable (0x469) can be returned if no replica is
665    available for the folder.
666
667    Developers may also call GetLastError() to retrieve the last
668    MAPI error code. Possible MAPI error codes are:
669    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
670    - MAPI_E_CALL_FAILED: A network problem was encountered during the
671      transaction
672  */
673 _PUBLIC_ enum MAPISTATUS GetOwningServers(mapi_object_t *obj_store,
674                                           mapi_object_t *obj_folder,
675                                           uint16_t *OwningServersCount,
676                                           uint16_t *CheapServersCount,
677                                           char **OwningServers)
678 {
679         struct mapi_request             *mapi_request;
680         struct mapi_response            *mapi_response;
681         struct EcDoRpc_MAPI_REQ         *mapi_req;
682         struct GetOwningServers_req     request;
683         struct GetOwningServers_repl    response;
684         struct mapi_session             *session;
685         NTSTATUS                        status;
686         enum MAPISTATUS                 retval;
687         uint32_t                        size;
688         TALLOC_CTX                      *mem_ctx;
689         mapi_id_t                       FolderId;
690         uint32_t                        i;
691         uint8_t                         logon_id;
692
693         /* Sanity checks */
694         OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
695         OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
696         OPENCHANGE_RETVAL_IF(!OwningServersCount, MAPI_E_INVALID_PARAMETER, NULL);
697         OPENCHANGE_RETVAL_IF(!CheapServersCount, MAPI_E_INVALID_PARAMETER, NULL);
698         OPENCHANGE_RETVAL_IF(!OwningServers, MAPI_E_INVALID_PARAMETER, NULL);
699
700         session = mapi_object_get_session(obj_store);
701         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
702
703         if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS)
704                 return retval;
705
706         FolderId = mapi_object_get_id(obj_folder);
707         OPENCHANGE_RETVAL_IF(!FolderId, MAPI_E_INVALID_PARAMETER, NULL);
708                 
709         mem_ctx = talloc_named(NULL, 0, "GetOwningServers");
710         
711         size = 0;
712
713         /* Fill the GetOwningServers operation */
714         request.FolderId = FolderId;
715         size += sizeof (uint64_t);
716
717         /* Fill the MAPI_REQ request */
718         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
719         mapi_req->opnum = op_MAPI_GetOwningServers;
720         mapi_req->logon_id = logon_id;
721         mapi_req->handle_idx = 0;
722         mapi_req->u.mapi_GetOwningServers = request;
723         size += 5;
724
725         /* Fill the mapi_request structure */
726         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
727         mapi_request->mapi_len = size + sizeof (uint32_t);
728         mapi_request->length = size;
729         mapi_request->mapi_req = mapi_req;
730         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
731         mapi_request->handles[0] = mapi_object_get_handle(obj_store);
732
733         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
734         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
735         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
736         retval = mapi_response->mapi_repl->error_code;
737         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
738
739         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
740
741         /* Retrieve GetOwningServers response */
742         response = mapi_response->mapi_repl->u.mapi_GetOwningServers;
743
744         *OwningServersCount = response.OwningServersCount;
745         *CheapServersCount = response.CheapServersCount;
746         if (*OwningServersCount) {
747                 OwningServers = talloc_array((TALLOC_CTX *)session, char *, *OwningServersCount + 1);
748                 for (i = 0; i != *OwningServersCount; i++) {
749                         OwningServers[i] = talloc_strdup((TALLOC_CTX *)OwningServers, response.OwningServers[i]);
750                 }
751                 OwningServers[i] = NULL;
752         } else {
753                 OwningServers = NULL;
754         }
755
756         talloc_free(mapi_response);
757         talloc_free(mem_ctx);
758
759         return MAPI_E_SUCCESS;
760 }
761
762
763 /**
764    \details Gets the current store state for the logged in user
765
766    This operation must be performed against a user store (not against
767    a Public Folder store). The StoreState will have the 
768    STORE_HAS_SEARCHES flag set if there are any active search folders.
769    There are (currently) no other flags in the StoreState.
770
771    \param obj_store the store object
772    \param StoreState pointer to the store state returned by the server
773
774    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
775
776    \note Developers may also call GetLastError() to retrieve the last
777    MAPI error code. Possible MAPI error codes are:
778    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
779    - MAPI_E_INVALID_PARAMETER: obj_store or StoreState are not valid
780    - MAPI_E_CALL_FAILED: A network problem was encountered during the
781      transaction
782  */
783 _PUBLIC_ enum MAPISTATUS GetStoreState(mapi_object_t *obj_store,
784                                        uint32_t *StoreState)
785 {
786         struct mapi_request             *mapi_request;
787         struct mapi_response            *mapi_response;
788         struct EcDoRpc_MAPI_REQ         *mapi_req;
789         struct mapi_session             *session;
790         NTSTATUS                        status;
791         enum MAPISTATUS                 retval;
792         uint32_t                        size = 0;
793         TALLOC_CTX                      *mem_ctx;
794         uint8_t                         logon_id;
795
796         /* Sanity Checks */
797         OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
798         OPENCHANGE_RETVAL_IF(!StoreState, MAPI_E_INVALID_PARAMETER, NULL);
799
800         session = mapi_object_get_session(obj_store);
801         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
802
803         if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS)
804                 return retval;
805
806         mem_ctx = talloc_named(NULL, 0, "GetStoreState");
807         size = 0;
808
809         /* Fill the MAPI_REQ request */
810         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
811         mapi_req->opnum = op_MAPI_GetStoreState;
812         mapi_req->logon_id = logon_id;
813         mapi_req->handle_idx = 0;
814         size += 5;
815
816         /* Fill the mapi_request structure */
817         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
818         mapi_request->mapi_len = size + sizeof (uint32_t);
819         mapi_request->length = size;
820         mapi_request->mapi_req = mapi_req;
821         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
822         mapi_request->handles[0] = mapi_object_get_handle(obj_store);
823
824         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
825         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
826         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
827         retval = mapi_response->mapi_repl->error_code;
828         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
829
830         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
831
832         /* Retrieve the StoreState */
833         *StoreState = mapi_response->mapi_repl->u.mapi_GetStoreState.StoreState;
834
835         talloc_free(mapi_response);
836         talloc_free(mem_ctx);
837
838         return MAPI_E_SUCCESS;
839 }
840
841
842 /**
843    \details Retrieves the sending folder (OUTBOX) for a given store
844
845    This function obtains the folder that was established as the
846    destination for outgoing messages of a specified message class.
847
848    This function does not result in any network traffic.
849
850    \param obj_store the store to get the outbox folder for
851    \param outbox_id the resulting folder identification
852
853    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
854    
855    \note Developers may also call GetLastError() to retrieve the last
856    MAPI error code. Possible MAPI error codes are:
857    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
858    - MAPI_E_CALL_FAILED: A network problem was encountered during the
859      transaction
860
861    \sa MAPIInitialize, OpenMsgStore, GetLastError, GetDefaultFolder
862 */
863 _PUBLIC_ enum MAPISTATUS GetOutboxFolder(mapi_object_t *obj_store, 
864                                          mapi_id_t *outbox_id)
865 {
866         OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
867
868         *outbox_id = ((mapi_object_store_t *)obj_store->private_data)->fid_outbox;
869
870         return MAPI_E_SUCCESS;
871 }
872
873
874 /**
875    \details Notify the store of a new message to be processed
876
877    \param obj_store the store that the message is in (logon object)
878    \param obj_folder the folder that the message is in
879    \param obj_msg the message to be processed
880    \param MessageClass the message class of the message to be processed
881    \param MessageFlags the message flags on the message
882
883    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
884
885    \note Developers may also call GetLastError() to retrieve the last
886    MAPI error code. Possible MAPI error codes are:
887    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
888    - MAPI_E_INVALID_PARAMETER: one the parameters is invalid
889    - MAPI_E_CALL_FAILED: A network problem was encountered during the
890    transaction
891
892    \sa GetReceiveFolder, GetReceiveFolderTable
893  */
894 _PUBLIC_ enum MAPISTATUS TransportNewMail(mapi_object_t *obj_store, mapi_object_t *obj_folder,
895                                           mapi_object_t *obj_msg,
896                                           const char *MessageClass, uint32_t MessageFlags)
897 {
898         struct mapi_request             *mapi_request;
899         struct mapi_response            *mapi_response;
900         struct EcDoRpc_MAPI_REQ         *mapi_req;
901         struct TransportNewMail_req     request;
902         struct mapi_session             *session;
903         NTSTATUS                        status;
904         enum MAPISTATUS                 retval;
905         uint32_t                        size;
906         TALLOC_CTX                      *mem_ctx;
907         uint8_t                         logon_id;
908
909         /* Sanity checks */
910         OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
911         OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
912         OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
913         OPENCHANGE_RETVAL_IF(!obj_msg, MAPI_E_INVALID_PARAMETER, NULL);
914         OPENCHANGE_RETVAL_IF(!MessageClass, MAPI_E_INVALID_PARAMETER, NULL);
915         session = mapi_object_get_session(obj_folder);
916         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
917
918         if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
919                 return retval;
920
921         mem_ctx = talloc_named(NULL, 0, "TransportNewMail");
922
923         /* Fill the TransportNewMail operation */
924         size = 0;
925         request.MessageId = mapi_object_get_id(obj_msg);
926         size += sizeof (uint64_t);
927         request.FolderId = mapi_object_get_id(obj_folder);
928         size += sizeof (uint64_t);
929         request.MessageClass = MessageClass;
930         size += strlen(MessageClass) + 1;
931         request.MessageFlags = MessageFlags;
932         size += sizeof(uint32_t);
933
934         /* Fill the MAPI_REQ request */
935         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
936         mapi_req->opnum = op_MAPI_TransportNewMail;
937         mapi_req->logon_id = logon_id;
938         mapi_req->handle_idx = 0;
939         mapi_req->u.mapi_TransportNewMail = request;
940         size += 5;
941
942         /* Fill the mapi_request structure */
943         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
944         mapi_request->mapi_len = size + sizeof (uint32_t);
945         mapi_request->length = size;
946         mapi_request->mapi_req = mapi_req;
947         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
948         mapi_request->handles[0] = mapi_object_get_handle(obj_store);
949
950         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
951         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
952         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
953         retval = mapi_response->mapi_repl->error_code;
954         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
955
956         talloc_free(mapi_response);
957         talloc_free(mem_ctx);
958
959         return MAPI_E_SUCCESS;
960 }