2 OpenChange Server implementation
4 EMSMDBP: EMSMDB Provider implementation
6 Copyright (C) Julien Kerihuel 2009-2011
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.
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.
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/>.
25 \brief Message and Attachment object routines and Rops
30 #include "mapiproxy/dcesrv_mapiproxy.h"
31 #include "mapiproxy/libmapiproxy/libmapiproxy.h"
32 #include "mapiproxy/libmapiserver/libmapiserver.h"
33 #include "dcesrv_exchange_emsmdb.h"
37 \details EcDoRpc OpenMessage (0x03) Rop. This operation opens an
38 existing message in a mailbox.
40 \param mem_ctx pointer to the memory context
41 \param emsmdbp_ctx pointer to the emsmdb provider context
42 \param mapi_req pointer to the OpenMessage EcDoRpc_MAPI_REQ
44 \param mapi_repl pointer to the OpenMessage EcDoRpc_MAPI_REPL
46 \param handles pointer to the MAPI handles array
47 \param size pointer to the mapi_response size to update
49 \return MAPI_E_SUCCESS on success, otherwise MAPI error
51 _PUBLIC_ enum MAPISTATUS EcDoRpc_RopOpenMessage(TALLOC_CTX *mem_ctx,
52 struct emsmdbp_context *emsmdbp_ctx,
53 struct EcDoRpc_MAPI_REQ *mapi_req,
54 struct EcDoRpc_MAPI_REPL *mapi_repl,
55 uint32_t *handles, uint16_t *size)
57 enum MAPISTORE_ERROR retval;
59 struct mapi_handles *parent = NULL;
60 struct mapi_handles *parent_handle = NULL;
61 struct mapi_handles *rec = NULL;
62 struct emsmdbp_object *object = NULL;
63 struct emsmdbp_object *parent_object = NULL;
64 struct mapistore_message msg;
67 uint64_t messageID = 0;
70 bool mapistore = false;
71 struct indexing_folders_list *flist;
72 struct SPropTagArray *SPropTagArray;
77 DEBUG(4, ("exchange_emsmdb: [OXCMSG] OpenMessage (0x03)\n"));
80 OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
81 OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
82 OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
83 OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
84 OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
86 handle = handles[mapi_req->handle_idx];
87 ret = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &parent);
88 OPENCHANGE_RETVAL_IF(ret, ret, NULL);
90 mapi_repl->opnum = mapi_req->opnum;
91 mapi_repl->error_code = MAPI_E_SUCCESS;
92 mapi_repl->handle_idx = mapi_req->u.mapi_OpenMessage.handle_idx;
93 messageID = mapi_req->u.mapi_OpenMessage.MessageId;
94 folderID = mapi_req->u.mapi_OpenMessage.FolderId;
96 /* OpenMessage can only be called for mailbox/folder objects */
97 mapi_handles_get_private_data(parent, &data);
98 object = (struct emsmdbp_object *)data;
100 mapi_repl->error_code = MAPI_E_NO_SUPPORT;
101 *size += libmapiserver_RopOpenMessage_size(NULL);
102 return MAPI_E_SUCCESS;
105 switch (object->type) {
106 case EMSMDBP_OBJECT_MAILBOX:
107 retval = mapistore_indexing_get_folder_list(emsmdbp_ctx->mstore_ctx, emsmdbp_ctx->username,
109 if (retval || !flist->count) {
110 DEBUG(0, ("No parent folder found for 0x%.16"PRIx64"\n", messageID));
112 /* If last element in the list doesn't match folderID, that's incorrect */
113 if (folderID != flist->folderID[flist->count - 1]) {
114 DEBUG(0, ("Last parent folder 0x%.16"PRIx64" doesn't match " \
115 "with expected 0x%.16"PRIx64"\n",
116 flist->folderID[flist->count - 1], folderID));
119 /* Look if we have a parent folder already opened */
120 for (i = flist->count - 1 ; i >= 0; i--) {
121 parent_handle = emsmdbp_object_get_folder_handle_by_fid(emsmdbp_ctx->handles_ctx,
129 /* If we have a parent handle, we have a context_id
130 * and we can call subsequent OpenFolder - this will
131 * increment ref_count whereas needed */
134 for (i = i + 1; i < flist->count; i++) {
135 mapi_handles_get_private_data(parent_handle, &data);
136 parent_object = (struct emsmdbp_object *) data;
137 folderID = parent_object->object.folder->folderID;
138 contextID = parent_object->object.folder->contextID;
139 retval = mapistore_opendir(emsmdbp_ctx->mstore_ctx, contextID, folderID,
141 mapi_handles_add(emsmdbp_ctx->handles_ctx, parent_handle->handle, &rec);
142 object = emsmdbp_object_folder_init((TALLOC_CTX *)emsmdbp_ctx, emsmdbp_ctx,
143 flist->folderID[i], parent_handle);
145 ret = mapi_handles_set_private_data(rec, object);
152 ret = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
153 object = emsmdbp_object_folder_init((TALLOC_CTX *)emsmdbp_ctx, emsmdbp_ctx,
154 flist->folderID[0], parent);
156 ret = mapi_handles_set_private_data(rec, object);
160 /* now we have a context_id, we can use code above to open subfolders subsequently */
164 /* Add this stage our new parent_handle should point to the message */
166 mapi_handles_get_private_data(parent_handle, &data);
167 parent_object = (struct emsmdbp_object *) data;
168 folderID = parent_object->object.folder->folderID;
169 contextID = parent_object->object.folder->contextID;
170 parent = parent_handle;
172 case EMSMDBP_OBJECT_FOLDER:
173 folderID = object->object.folder->folderID;
174 contextID = object->object.folder->contextID;
177 mapi_repl->error_code = MAPI_E_NO_SUPPORT;
178 *size += libmapiserver_RopGetHierarchyTable_size(NULL);
179 return MAPI_E_SUCCESS;
182 mapistore = emsmdbp_is_mapistore(parent);
185 /* system/special folder */
186 DEBUG(0, ("Not implemented yet - shouldn't occur\n"));
189 /* mapistore implementation goes here */
190 mapistore_openmessage(emsmdbp_ctx->mstore_ctx, contextID, folderID, messageID, &msg);
192 /* Build the OpenMessage reply */
193 subject = (char *) find_SPropValue_data(msg.properties, PR_SUBJECT);
195 mapi_repl->u.mapi_OpenMessage.HasNamedProperties = false;
196 mapi_repl->u.mapi_OpenMessage.SubjectPrefix.StringType = StringType_EMPTY;
197 mapi_repl->u.mapi_OpenMessage.NormalizedSubject.StringType = StringType_UNICODE_REDUCED;
198 mapi_repl->u.mapi_OpenMessage.NormalizedSubject.String.lpszW_reduced = talloc_strdup(mem_ctx, subject);
199 mapi_repl->u.mapi_OpenMessage.RecipientCount = msg.recipients->cRows;
201 SPropTagArray = set_SPropTagArray(mem_ctx, 0x4,
204 PR_7BIT_DISPLAY_NAME_UNICODE,
205 PR_SMTP_ADDRESS_UNICODE);
206 mapi_repl->u.mapi_OpenMessage.RecipientColumns.cValues = SPropTagArray->cValues;
207 mapi_repl->u.mapi_OpenMessage.RecipientColumns.aulPropTag = SPropTagArray->aulPropTag;
208 mapi_repl->u.mapi_OpenMessage.RowCount = msg.recipients->cRows;
209 mapi_repl->u.mapi_OpenMessage.recipients = talloc_array(mem_ctx,
210 struct OpenMessage_recipients,
211 msg.recipients->cRows + 1);
212 for (i = 0; i < msg.recipients->cRows; i++) {
213 mapi_repl->u.mapi_OpenMessage.recipients[i].RecipClass = (enum ulRecipClass) msg.recipients->aRow[i].lpProps[0].value.l;
214 mapi_repl->u.mapi_OpenMessage.recipients[i].codepage = CP_USASCII;
215 mapi_repl->u.mapi_OpenMessage.recipients[i].Reserved = 0;
216 emsmdbp_resolve_recipient(mem_ctx, emsmdbp_ctx,
217 (char *)msg.recipients->aRow[i].lpProps[1].value.lpszA,
218 &(mapi_repl->u.mapi_OpenMessage.RecipientColumns),
219 &(mapi_repl->u.mapi_OpenMessage.recipients[i].RecipientRow));
225 /* Initialize Message object */
226 handle = handles[mapi_req->handle_idx];
227 ret = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
228 handles[mapi_repl->handle_idx] = rec->handle;
231 object = emsmdbp_object_message_init((TALLOC_CTX *)rec, emsmdbp_ctx, messageID, parent_handle);
233 ret = mapi_handles_set_private_data(rec, object);
237 *size += libmapiserver_RopOpenMessage_size(mapi_repl);
239 return MAPI_E_SUCCESS;
244 \details EcDoRpc CreateMessage (0x06) Rop. This operation creates a
245 message object in the mailbox.
247 \param mem_ctx pointer to the memory context
248 \param emsmdbp_ctx pointer to the emsmdb provider context
249 \param mapi_req pointer to the CreateMessage EcDoRpc_MAPI_REQ
251 \param mapi_repl pointer to the CreateMessage EcDoRpc_MAPI_REPL
253 \param handles pointer to the MAPI handles array
254 \param size pointer to the mapi_response size to update
256 \return MAPI_E_SUCCESS on success, otherwise MAPI error
258 _PUBLIC_ enum MAPISTATUS EcDoRpc_RopCreateMessage(TALLOC_CTX *mem_ctx,
259 struct emsmdbp_context *emsmdbp_ctx,
260 struct EcDoRpc_MAPI_REQ *mapi_req,
261 struct EcDoRpc_MAPI_REPL *mapi_repl,
262 uint32_t *handles, uint16_t *size)
264 enum MAPISTATUS retval;
265 struct mapi_handles *rec = NULL;
266 struct mapi_handles *parent = NULL;
267 struct mapi_handles *parent_handle = NULL;
268 struct emsmdbp_object *object = NULL;
273 bool mapistore = false;
282 DEBUG(4, ("exchange_emsmdb: [OXCMSG] CreateMessage (0x06)\n"));
285 OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
286 OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
287 OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
288 OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
289 OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
291 mapi_repl->opnum = mapi_req->opnum;
292 mapi_repl->error_code = MAPI_E_SUCCESS;
293 mapi_repl->handle_idx = mapi_req->u.mapi_CreateMessage.handle_idx;
294 mapi_repl->u.mapi_CreateMessage.HasMessageId = 0;
296 folderID = mapi_req->u.mapi_CreateMessage.FolderId;
298 /* CreateMessage can only be called for a mailbox/folder object */
299 handle = handles[mapi_req->handle_idx];
300 retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &parent);
301 OPENCHANGE_RETVAL_IF(retval, retval, NULL);
303 mapi_handles_get_private_data(parent, &data);
304 object = (struct emsmdbp_object *)data;
306 mapi_repl->error_code = MAPI_E_NO_SUPPORT;
310 /* FIXME: we can't assume the folder is already opened */
311 parent_handle = emsmdbp_object_get_folder_handle_by_fid(emsmdbp_ctx->handles_ctx, folderID);
312 if (!parent_handle) {
313 mapi_repl->error_code = MAPI_E_NOT_FOUND;
316 contextID = emsmdbp_get_contextID(parent_handle);
317 mapistore = emsmdbp_is_mapistore(parent_handle);
321 /* system/special folder */
322 DEBUG(0, ("Not implemented yet - shouldn't occur\n"));
325 /* This should be handled differently here: temporary hack */
326 retval = openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, &messageID);
328 mapi_repl->error_code = MAPI_E_NO_SUPPORT;
331 mapi_repl->u.mapi_CreateMessage.HasMessageId = 1;
332 mapi_repl->u.mapi_CreateMessage.MessageId.MessageId = messageID;
333 mapistore_createmessage(emsmdbp_ctx->mstore_ctx, contextID, folderID, messageID);
335 /* Set default properties for message: MS-OXCMSG 3.2.5.2 */
336 aRow.lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
340 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_IMPORTANCE, (const void *)&pt_long);
341 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_MESSAGE_CLASS, (const void *)"IPM.Note");
343 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_SENSITIVITY, (const void *)&pt_long);
345 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_MESSAGE_FLAGS, (const void *)&pt_long);
347 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_HASATTACH, (const void *)&pt_boolean);
348 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_URL_COMP_NAME_SET, (const void *)&pt_boolean);
350 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_TRUST_SENDER, (const void *)&pt_long);
352 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_ACCESS, (const void *)&pt_long);
354 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_ACCESS_LEVEL, (const void *)&pt_long);
355 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_URL_COMP_NAME, (const void *)"No Subject.EML");
357 gettimeofday(&tv, NULL);
358 time = timeval_to_nttime(&tv);
359 ft.dwLowDateTime = (time << 32) >> 32;
360 ft.dwHighDateTime = time >> 32;
361 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_CREATION_TIME, (const void *)&ft);
362 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_LAST_MODIFICATION_TIME, (const void *)&ft);
363 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_LOCAL_COMMIT_TIME, (const void *)&ft);
364 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_MESSAGE_LOCALE_ID, (const void *)&mapi_req->u.mapi_CreateMessage.CodePageId);
365 aRow.lpProps = add_SPropValue(mem_ctx, aRow.lpProps, &aRow.cValues, PR_LOCALE_ID, (const void *)&mapi_req->u.mapi_CreateMessage.CodePageId);
367 mapistore_setprops(emsmdbp_ctx->mstore_ctx, contextID, messageID, MAPISTORE_MESSAGE, &aRow);
371 DEBUG(0, ("CreateMessage: 0x%.16"PRIx64": mapistore = %s\n", folderID,
372 emsmdbp_is_mapistore(parent_handle) == true ? "true" : "false"));
374 /* Initialize Message object */
375 handle = handles[mapi_req->handle_idx];
376 retval = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
377 handles[mapi_repl->handle_idx] = rec->handle;
380 object = emsmdbp_object_message_init((TALLOC_CTX *)rec, emsmdbp_ctx, messageID, parent_handle);
382 /* Add default properties to message MS-OXCMSG 3.2.5.2 */
383 retval = mapi_handles_set_private_data(rec, object);
388 *size += libmapiserver_RopCreateMessage_size(mapi_repl);
390 return MAPI_E_SUCCESS;
395 \details EcDoRpc SaveChangesMessage (0x0c) Rop. This operation
396 operation commits the changes made to a message.
398 \param mem_ctx pointer to the memory context
399 \param emsmdbp_ctx pointer to the emsmdb provider context
400 \param mapi_req pointer to the SaveChangesMessage EcDoRpc_MAPI_REQ
402 \param mapi_repl pointer to the SaveChangesMessage
403 EcDoRpc_MAPI_REPL structure
405 \param handles pointer to the MAPI handles array
406 \param size pointer to the mapi_response size to update
408 \return MAPI_E_SUCCESS on success, otherwise MAPI error
410 _PUBLIC_ enum MAPISTATUS EcDoRpc_RopSaveChangesMessage(TALLOC_CTX *mem_ctx,
411 struct emsmdbp_context *emsmdbp_ctx,
412 struct EcDoRpc_MAPI_REQ *mapi_req,
413 struct EcDoRpc_MAPI_REPL *mapi_repl,
414 uint32_t *handles, uint16_t *size)
416 enum MAPISTATUS retval;
418 struct mapi_handles *rec = NULL;
420 bool mapistore = false;
421 struct emsmdbp_object *object;
426 DEBUG(4, ("exchange_emsmdb: [OXCMSG] SaveChangesMessage (0x0c)\n"));
429 OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
430 OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
431 OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
432 OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
433 OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
435 mapi_repl->opnum = mapi_req->opnum;
436 mapi_repl->error_code = MAPI_E_SUCCESS;
437 mapi_repl->handle_idx = mapi_req->handle_idx;
439 handle = handles[mapi_req->u.mapi_SaveChangesMessage.handle_idx];
440 retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &rec);
442 mapi_repl->error_code = MAPI_E_NOT_FOUND;
446 retval = mapi_handles_get_private_data(rec, &private_data);
447 object = (struct emsmdbp_object *)private_data;
448 if (!object || object->type != EMSMDBP_OBJECT_MESSAGE) {
449 mapi_repl->error_code = MAPI_E_NO_SUPPORT;
453 mapistore = emsmdbp_is_mapistore(rec);
456 DEBUG(0, ("Not implement yet - shouldn't occur\n"));
459 messageID = object->object.message->messageID;
460 contextID = object->object.message->contextID;
461 flags = mapi_req->u.mapi_SaveChangesMessage.SaveFlags;
462 mapistore_savechangesmessage(emsmdbp_ctx->mstore_ctx, contextID, messageID, flags);
463 mapistore_indexing_record_add_mid(emsmdbp_ctx->mstore_ctx, contextID, messageID);
467 mapi_repl->u.mapi_SaveChangesMessage.handle_idx = mapi_req->u.mapi_SaveChangesMessage.handle_idx;
468 mapi_repl->u.mapi_SaveChangesMessage.MessageId = object->object.message->messageID;
471 *size += libmapiserver_RopSaveChangesMessage_size(mapi_repl);
473 return MAPI_E_SUCCESS;
477 \details EcDoRpc ModifyRecipients (0x0e) Rop. This operation modifies an
478 existing message to add recipients (TO, CC, BCC).
480 \param mem_ctx pointer to the memory context
481 \param emsmdbp_ctx pointer to the emsmdb provider context
482 \param mapi_req pointer to the ModifyRecipients EcDoRpc_MAPI_REQ
484 \param mapi_repl pointer to the ModifyRecipients EcDoRpc_MAPI_REPL
486 \param handles pointer to the MAPI handles array
487 \param size pointer to the mapi_response size to update
489 \return MAPI_E_SUCCESS on success, otherwise MAPI error
491 _PUBLIC_ enum MAPISTATUS EcDoRpc_RopModifyRecipients(TALLOC_CTX *mem_ctx,
492 struct emsmdbp_context *emsmdbp_ctx,
493 struct EcDoRpc_MAPI_REQ *mapi_req,
494 struct EcDoRpc_MAPI_REPL *mapi_repl,
495 uint32_t *handles, uint16_t *size)
497 DEBUG(4, ("exchange_emsmdb: [OXCMSG] ModifyRecipients (0x0e)\n"));
500 OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
501 OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
502 OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
503 OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
504 OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
506 mapi_repl->opnum = mapi_req->opnum;
507 mapi_repl->error_code = MAPI_E_SUCCESS;
509 /* TODO: actually implement this */
511 *size += libmapiserver_RopModifyRecipients_size(mapi_repl);
513 return MAPI_E_SUCCESS;
518 \details EcDoRpc ReloadCachedInformation (0x10) Rop. This operation
519 gets message and recipient information from a message.
521 \param mem_ctx pointer to the memory context
522 \param emsmdbp_ctx pointer to the emsmdb provider context
523 \param mapi_req pointer to the ReloadCachedInformation
524 EcDoRpc_MAPI_REQ structure
525 \param mapi_repl pointer to the ReloadCachedInformation
526 EcDoRpc_MAPI_REPL structure
527 \param handles pointer to the MAPI handles array
528 \param size pointer to the mapi_response size to update
530 \return MAPI_E_SUCCESS on success, otherwise MAPI error
532 _PUBLIC_ enum MAPISTATUS EcDoRpc_RopReloadCachedInformation(TALLOC_CTX *mem_ctx,
533 struct emsmdbp_context *emsmdbp_ctx,
534 struct EcDoRpc_MAPI_REQ *mapi_req,
535 struct EcDoRpc_MAPI_REPL *mapi_repl,
536 uint32_t *handles, uint16_t *size)
538 enum MAPISTATUS retval;
540 struct mapi_handles *rec = NULL;
542 bool mapistore = false;
543 struct mapistore_message msg;
544 struct emsmdbp_object *object;
548 struct SPropTagArray *SPropTagArray;
549 char *subject = NULL;
552 DEBUG(4, ("exchange_emsmdb: [OXCMSG] ReloadCachedInformation (0x10)\n"));
555 OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
556 OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
557 OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
558 OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
559 OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
561 mapi_repl->opnum = mapi_req->opnum;
562 mapi_repl->error_code = MAPI_E_SUCCESS;
563 mapi_repl->handle_idx = mapi_req->handle_idx;
565 handle = handles[mapi_req->handle_idx];
566 retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &rec);
568 mapi_repl->error_code = MAPI_E_NOT_FOUND;
572 retval = mapi_handles_get_private_data(rec, &private_data);
573 object = (struct emsmdbp_object *)private_data;
574 if (!object || object->type != EMSMDBP_OBJECT_MESSAGE) {
575 mapi_repl->error_code = MAPI_E_NO_SUPPORT;
579 mapistore = emsmdbp_is_mapistore(rec);
582 DEBUG(0, ("Not implemented yet - shouldn't occur\n"));
585 folderID = object->object.message->folderID;
586 messageID = object->object.message->messageID;
587 contextID = object->object.message->contextID;
588 mapistore_openmessage(emsmdbp_ctx->mstore_ctx, contextID, folderID, messageID, &msg);
590 /* Build the ReloadCachedInformation reply */
591 subject = (char *) find_SPropValue_data(msg.properties, PR_SUBJECT);
592 mapi_repl->u.mapi_ReloadCachedInformation.HasNamedProperties = false;
593 mapi_repl->u.mapi_ReloadCachedInformation.SubjectPrefix.StringType = StringType_EMPTY;
595 mapi_repl->u.mapi_ReloadCachedInformation.NormalizedSubject.StringType = StringType_UNICODE_REDUCED;
596 mapi_repl->u.mapi_ReloadCachedInformation.NormalizedSubject.String.lpszW_reduced = talloc_strdup(mem_ctx, subject);
598 mapi_repl->u.mapi_ReloadCachedInformation.NormalizedSubject.StringType = StringType_EMPTY;
600 mapi_repl->u.mapi_ReloadCachedInformation.RecipientCount = msg.recipients->cRows;
602 SPropTagArray = set_SPropTagArray(mem_ctx, 0x4,
605 PR_7BIT_DISPLAY_NAME_UNICODE,
606 PR_SMTP_ADDRESS_UNICODE);
607 mapi_repl->u.mapi_ReloadCachedInformation.RecipientColumns.cValues = SPropTagArray->cValues;
608 mapi_repl->u.mapi_ReloadCachedInformation.RecipientColumns.aulPropTag = SPropTagArray->aulPropTag;
609 mapi_repl->u.mapi_ReloadCachedInformation.RowCount = msg.recipients->cRows;
610 mapi_repl->u.mapi_ReloadCachedInformation.RecipientRows = talloc_array(mem_ctx,
611 struct OpenRecipientRow,
612 msg.recipients->cRows + 1);
613 for (i = 0; i < msg.recipients->cRows; i++) {
614 mapi_repl->u.mapi_ReloadCachedInformation.RecipientRows[i].RecipientType = (enum ulRecipClass) msg.recipients->aRow[i].lpProps[0].value.l;
615 mapi_repl->u.mapi_ReloadCachedInformation.RecipientRows[i].CodePageId = CP_USASCII;
616 mapi_repl->u.mapi_ReloadCachedInformation.RecipientRows[i].Reserved = 0;
617 emsmdbp_resolve_recipient(mem_ctx, emsmdbp_ctx,
618 (char *)msg.recipients->aRow[i].lpProps[1].value.lpszA,
619 &(mapi_repl->u.mapi_ReloadCachedInformation.RecipientColumns),
620 &(mapi_repl->u.mapi_ReloadCachedInformation.RecipientRows[i].RecipientRow));
626 *size += libmapiserver_RopReloadCachedInformation_size(mapi_repl);
628 return MAPI_E_SUCCESS;
633 \details EcDoRpc SetMessageReadFlag (0x11) Rop. This operation sets
634 or clears the message read flag.
636 \param mem_ctx pointer to the memory context
637 \param emsmdbp_ctx pointer to the emsmdb provider context
638 \param mapi_req pointer to the SetMessageReadFlag EcDoRpc_MAPI_REQ
640 \param mapi_repl pointer to the SetMessageReadFlag
641 EcDoRpc_MAPI_REPL structure
643 \param handles pointer to the MAPI handles array
644 \param size pointer to the mapi_response size to update
646 \return MAPI_E_SUCCESS on success, otherwise MAPI error
648 _PUBLIC_ enum MAPISTATUS EcDoRpc_RopSetMessageReadFlag(TALLOC_CTX *mem_ctx,
649 struct emsmdbp_context *emsmdbp_ctx,
650 struct EcDoRpc_MAPI_REQ *mapi_req,
651 struct EcDoRpc_MAPI_REPL *mapi_repl,
652 uint32_t *handles, uint16_t *size)
654 DEBUG(4, ("exchange_emsmdb: [OXCMSG] SetMessageReadFlag (0x11)\n"));
657 OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
658 OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
659 OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
660 OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
661 OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
663 mapi_repl->opnum = mapi_req->opnum;
664 mapi_repl->error_code = MAPI_E_SUCCESS;
665 mapi_repl->handle_idx = mapi_req->handle_idx;
667 /* TODO: actually implement this */
668 mapi_repl->u.mapi_SetMessageReadFlag.ReadStatusChanged = false;
670 *size += libmapiserver_RopSetMessageReadFlag_size(mapi_repl);
672 return MAPI_E_SUCCESS;
677 \details EcDoRpc GetAttachmentTable (0x21) Rop. This operation gets
678 the attachment table of a message.
680 \param mem_ctx pointer to the memory context
681 \param emsmdbp_ctx pointer to the emsmdb provider context
682 \param mapi_req pointer to the GetAttachmentTable EcDoRpc_MAPI_REQ
684 \param mapi_repl pointer to the GetAttachmentTable
685 EcDoRpc_MAPI_REPL structure
686 \param handles pointer to the MAPI handles array
687 \param size pointer to the mapi_response size to update
689 \return MAPI_E_SUCCESS on success, otherwise MAPI error
691 _PUBLIC_ enum MAPISTATUS EcDoRpc_RopGetAttachmentTable(TALLOC_CTX *mem_ctx,
692 struct emsmdbp_context *emsmdbp_ctx,
693 struct EcDoRpc_MAPI_REQ *mapi_req,
694 struct EcDoRpc_MAPI_REPL *mapi_repl,
695 uint32_t *handles, uint16_t *size)
697 enum MAPISTATUS retval;
698 struct mapi_handles *rec = NULL;
701 DEBUG(4, ("exchange_emsmdb: [OXCMSG] GetAttachmentTable (0x21)\n"));
704 OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
705 OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
706 OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
707 OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
708 OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
710 mapi_repl->opnum = mapi_req->opnum;
711 mapi_repl->error_code = MAPI_E_SUCCESS;
713 /* TODO: actually implement this */
715 *size += libmapiserver_RopGetAttachmentTable_size(mapi_repl);
717 handle = handles[mapi_req->handle_idx];
718 retval = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
719 handles[mapi_repl->handle_idx] = rec->handle;
721 return MAPI_E_SUCCESS;