2 OpenChange MAPI implementation.
4 Copyright (C) Julien Kerihuel 2007-2008.
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.
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.
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/>.
20 #include "libmapi/libmapi.h"
21 #include "libmapi/libmapi_private.h"
27 \brief Folder related functions
32 \details The function creates a message in the specified folder,
33 and returns a pointer on this message.
35 \param obj_folder the folder to create the message in.
36 \param obj_message pointer to the newly created message.
38 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
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
46 \sa OpenFolder, DeleteMessage, GetLastError
48 _PUBLIC_ enum MAPISTATUS CreateMessage(mapi_object_t *obj_folder, mapi_object_t *obj_message)
50 struct mapi_request *mapi_request;
51 struct mapi_response *mapi_response;
52 struct EcDoRpc_MAPI_REQ *mapi_req;
53 struct CreateMessage_req request;
54 struct mapi_session *session;
56 enum MAPISTATUS retval;
62 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
63 session = mapi_object_get_session(obj_folder);
64 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
66 if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
69 mem_ctx = talloc_named(NULL, 0, "CreateMessage");
72 /* Fill the OpenFolder operation */
73 request.handle_idx = 0x1;
74 size += sizeof (uint8_t);
75 request.CodePageId = 0xfff;
76 size += sizeof (uint16_t);
77 request.FolderId = mapi_object_get_id(obj_folder);
78 size += sizeof (uint64_t);
79 request.AssociatedFlag = 0;
80 size += sizeof (uint8_t);
82 /* Fill the MAPI_REQ request */
83 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
84 mapi_req->opnum = op_MAPI_CreateMessage;
85 mapi_req->logon_id = logon_id;
86 mapi_req->handle_idx = 0;
87 mapi_req->u.mapi_CreateMessage = request;
90 /* Fill the mapi_request structure */
91 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
92 mapi_request->mapi_len = size + sizeof(mapi_handle_t) * 2;
93 mapi_request->length = size;
94 mapi_request->mapi_req = mapi_req;
95 mapi_request->handles = talloc_array(mem_ctx, mapi_handle_t, 2);
96 mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
97 mapi_request->handles[1] = 0xffffffff;
99 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
100 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
101 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
102 retval = mapi_response->mapi_repl->error_code;
103 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
105 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
107 /* set object session and handle */
108 mapi_object_set_session(obj_message, session);
109 mapi_object_set_handle(obj_message, mapi_response->handles[1]);
110 mapi_object_set_logon_id(obj_message, logon_id);
112 talloc_free(mapi_response);
113 talloc_free(mem_ctx);
115 return MAPI_E_SUCCESS;
120 \details Delete one or more messages
122 This function deletes one or more messages based on their ids from
125 \param obj_folder the folder to delete messages from
126 \param id_messages the list of ids
127 \param cn_messages the number of messages in the id list.
129 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
131 \note Developers may also call GetLastError() to retrieve the last
132 MAPI error code. Possible MAPI error codes are:
133 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
134 - MAPI_E_CALL_FAILED: A network problem was encountered during the
137 \sa OpenFolder, CreateMessage, GetLastError
139 _PUBLIC_ enum MAPISTATUS DeleteMessage(mapi_object_t *obj_folder, mapi_id_t *id_messages,
140 uint32_t cn_messages)
142 struct mapi_request *mapi_request;
143 struct mapi_response *mapi_response;
144 struct EcDoRpc_MAPI_REQ *mapi_req;
145 struct DeleteMessages_req request;
146 struct mapi_session *session;
148 enum MAPISTATUS retval;
154 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
155 session = mapi_object_get_session(obj_folder);
156 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
157 if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
160 mem_ctx = talloc_named(NULL, 0, "DeleteMessages");
163 /* Fill the DeleteMessages operation */
164 request.WantAsynchronous = 0x0;
165 size += sizeof (uint8_t);
166 request.NotifyNonRead = 0x1;
167 size += sizeof(uint8_t);
168 request.cn_ids = (uint16_t)cn_messages;
169 size += sizeof(uint16_t);
170 request.message_ids = id_messages;
171 size += request.cn_ids * sizeof(mapi_id_t);
173 /* Fill the MAPI_REQ request */
174 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
175 mapi_req->opnum = op_MAPI_DeleteMessages;
176 mapi_req->logon_id = logon_id;
177 mapi_req->handle_idx = 0;
178 mapi_req->u.mapi_DeleteMessages = request;
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_folder);
189 status = emsmdb_transaction_wrapper(session, 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);
195 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
197 talloc_free(mapi_response);
198 talloc_free(mem_ctx);
200 return MAPI_E_SUCCESS;
205 \details Hard delete one or more messages
207 This function hard deletes one or more messages based on their
208 ids from a specified folder.
210 \param obj_folder the folder to hard delete messages from
211 \param id_messages the list of ids
212 \param cn_messages the number of messages in the id list.
214 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
216 \note Developers may also call GetLastError() to retrieve the last
217 MAPI error code. Possible MAPI error codes are:
218 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
219 - MAPI_E_INVALID_PARAMETER: the parent folder was not valid
220 - MAPI_E_CALL_FAILED: A network problem was encountered during the
223 \sa OpenFolder, CreateMessage, GetLastError
225 _PUBLIC_ enum MAPISTATUS HardDeleteMessage(mapi_object_t *obj_folder,
226 mapi_id_t *id_messages,
227 uint16_t cn_messages)
229 struct mapi_request *mapi_request;
230 struct mapi_response *mapi_response;
231 struct EcDoRpc_MAPI_REQ *mapi_req;
232 struct HardDeleteMessages_req request;
233 struct mapi_session *session;
235 enum MAPISTATUS retval;
241 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
242 session = mapi_object_get_session(obj_folder);
243 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
245 if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
248 mem_ctx = talloc_named(NULL, 0, "HardDeleteMessages");
251 /* Fill the HardDeleteMessages operation */
252 request.WantAsynchronous = 0x0;
253 size += sizeof (uint8_t);
254 request.NotifyNonRead = 0x1;
255 size += sizeof(uint8_t);
256 request.MessageIdCount = cn_messages;
257 size += sizeof(uint16_t);
258 request.MessageIds = id_messages;
259 size += request.MessageIdCount * sizeof(mapi_id_t);
261 /* Fill the MAPI_REQ request */
262 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
263 mapi_req->opnum = op_MAPI_HardDeleteMessages;
264 mapi_req->logon_id = logon_id;
265 mapi_req->handle_idx = 0;
266 mapi_req->u.mapi_HardDeleteMessages = request;
269 /* Fill the mapi_request structure */
270 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
271 mapi_request->mapi_len = size + sizeof (uint32_t);
272 mapi_request->length = size;
273 mapi_request->mapi_req = mapi_req;
274 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
275 mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
277 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
278 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
279 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
280 retval = mapi_response->mapi_repl->error_code;
281 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
283 talloc_free(mapi_response);
284 talloc_free(mem_ctx);
286 return MAPI_E_SUCCESS;
291 \details Obtain the status associated with a message
293 This function obtains the status associated with a message in the
296 \param obj_folder the folder where the message is located
297 \param msgid the message ID
298 \param ulStatus the message status
300 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
302 \note Developers may also call GetLastError() to retrieve the last
303 MAPI error code. Possible MAPI error codes are:
304 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
305 - MAPI_E_CALL_FAILED: A network problem was encountered during the
308 _PUBLIC_ enum MAPISTATUS GetMessageStatus(mapi_object_t *obj_folder,
312 struct mapi_request *mapi_request;
313 struct mapi_response *mapi_response;
314 struct EcDoRpc_MAPI_REQ *mapi_req;
315 struct GetMessageStatus_req request;
316 struct mapi_session *session;
318 enum MAPISTATUS retval;
324 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
325 OPENCHANGE_RETVAL_IF(!msgid, MAPI_E_INVALID_PARAMETER, NULL);
326 session = mapi_object_get_session(obj_folder);
327 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
329 if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
332 mem_ctx = talloc_named(NULL, 0, "GetMessageStatus");
335 /* Fill the GetMessageStatus operation */
336 request.msgid = msgid;
337 size += sizeof (uint64_t);
339 /* Fill the MAPI_REQ request */
340 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
341 mapi_req->opnum = op_MAPI_GetMessageStatus;
342 mapi_req->logon_id = logon_id;
343 mapi_req->handle_idx = 0;
344 mapi_req->u.mapi_GetMessageStatus = request;
347 /* Fill the mapi_request structure */
348 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
349 mapi_request->mapi_len = size + sizeof (uint32_t);
350 mapi_request->length = size;
351 mapi_request->mapi_req = mapi_req;
352 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
353 mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
355 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
356 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
357 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
358 retval = mapi_response->mapi_repl->error_code;
359 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
361 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
363 *ulStatus = mapi_response->mapi_repl->u.mapi_SetMessageStatus.ulOldStatus;
365 talloc_free(mapi_response);
366 talloc_free(mem_ctx);
368 return MAPI_E_SUCCESS;
373 \details Set the status associated with a message
375 This function sets the status associated with a message in the
378 \param obj_folder the folder where the message is located
379 \param msgid the message ID
380 \param ulNewStatus the new status to be assigned
381 \param ulNewStatusMask bitmask of flags hat is applied to the new
382 status indicating the flags to be set
383 \param ulOldStatus pointer on the previous status of the message
385 ulNewStatusMask possible values:
386 - MSGSTATUS_DELMARKED: the message is marked for deletion
387 - MSGSTATUS_HIDDEN: the message is not to be displayed
388 - MSGSTATUS_HIGHLIGHTED: the message is to be displayed highlighted
389 - MSGSTATUS_REMOTE_DELETE: the message has been marked for deletion
390 on the remote message store without downloading to the local
392 - MSGSTATUS_REMOTE_DOWNLOAD: the message has been marked for
393 downloading from the remote message store to the local client.
394 - MSGSTATUS_TAGGED: The message has been tagged for a
395 client-defined purpose.
397 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
399 \note Developers may also call GetLastError() to retrieve the last
400 MAPI error code. Possible MAPI error codes are:
401 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
402 - MAPI_E_CALL_FAILED: A network problem was encountered during the
405 _PUBLIC_ enum MAPISTATUS SetMessageStatus(mapi_object_t *obj_folder,
407 uint32_t ulNewStatus,
408 uint32_t ulNewStatusMask,
409 uint32_t *ulOldStatus)
411 struct mapi_request *mapi_request;
412 struct mapi_response *mapi_response;
413 struct EcDoRpc_MAPI_REQ *mapi_req;
414 struct SetMessageStatus_req request;
415 struct mapi_session *session;
417 enum MAPISTATUS retval;
423 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
424 OPENCHANGE_RETVAL_IF(!msgid, MAPI_E_INVALID_PARAMETER, NULL);
425 session = mapi_object_get_session(obj_folder);
426 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
428 if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
431 mem_ctx = talloc_named(NULL, 0, "SetMessageStatus");
434 /* Fill the SetMessageStatus operation */
435 request.msgid = msgid;
436 size += sizeof (uint64_t);
438 request.ulNewStatus = ulNewStatus;
439 size += sizeof (uint32_t);
441 request.ulNewStatusMask = ulNewStatusMask;
442 size += sizeof (uint32_t);
444 /* Fill the MAPI_REQ request */
445 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
446 mapi_req->opnum = op_MAPI_SetMessageStatus;
447 mapi_req->logon_id = logon_id;
448 mapi_req->handle_idx = 0;
449 mapi_req->u.mapi_SetMessageStatus = request;
452 /* Fill the mapi_request structure */
453 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
454 mapi_request->mapi_len = size + sizeof (uint32_t);
455 mapi_request->length = size;
456 mapi_request->mapi_req = mapi_req;
457 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
458 mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
460 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
461 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
462 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
463 retval = mapi_response->mapi_repl->error_code;
464 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
466 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
468 *ulOldStatus = mapi_response->mapi_repl->u.mapi_SetMessageStatus.ulOldStatus;
470 talloc_free(mapi_response);
471 talloc_free(mem_ctx);
473 return MAPI_E_SUCCESS;
478 \details Copy or Move a message from a folder to another
480 \param obj_src The source folder
481 \param obj_dst The destination folder
482 \param message_id pointer to container object for message ids.
483 \param WantCopy boolean value, defines whether the operation is a
486 Possible values for WantCopy:
490 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
492 \note Developers may also call GetLastError() to retrieve the last
493 MAPI error code. Possible MAPI error codes are:
494 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
495 - MAPI_E_CALL_FAILED: A network problem was encountered during the
498 \sa OpenFolder, GetLastError
500 _PUBLIC_ enum MAPISTATUS MoveCopyMessages(mapi_object_t *obj_src,
501 mapi_object_t *obj_dst,
502 mapi_id_array_t *message_id,
507 enum MAPISTATUS retval;
508 struct mapi_request *mapi_request;
509 struct mapi_response *mapi_response;
510 struct EcDoRpc_MAPI_REQ *mapi_req;
511 struct MoveCopyMessages_req request;
512 struct mapi_session *session[2];
517 OPENCHANGE_RETVAL_IF(!obj_src, MAPI_E_INVALID_PARAMETER, NULL);
518 OPENCHANGE_RETVAL_IF(!obj_dst, MAPI_E_INVALID_PARAMETER, NULL);
519 session[0] = mapi_object_get_session(obj_src);
520 session[1] = mapi_object_get_session(obj_dst);
521 OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
522 OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
523 OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
525 if ((retval = mapi_object_get_logon_id(obj_src, &logon_id)) != MAPI_E_SUCCESS)
528 mem_ctx = talloc_named(NULL, 0, "MoveCopyMessages");
531 /* Fill the CopyMessage operation */
532 request.handle_idx = 0x1;
533 size += sizeof (uint8_t);
535 request.count = message_id->count;
536 size += sizeof (uint16_t);
538 retval = mapi_id_array_get(mem_ctx, message_id, &(request.message_id));
539 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
540 size += request.count * sizeof (mapi_id_t);
542 request.WantAsynchronous = 0;
543 size += sizeof (uint8_t);
545 request.WantCopy = WantCopy;
546 size += sizeof (uint8_t);
548 /* Fill the MAPI_REQ request */
549 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
550 mapi_req->opnum = op_MAPI_MoveCopyMessages;
551 mapi_req->logon_id = logon_id;
552 mapi_req->handle_idx = 0;
553 mapi_req->u.mapi_MoveCopyMessages = request;
556 /* Fill the mapi_request structure */
557 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
558 mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
559 mapi_request->length = size;
560 mapi_request->mapi_req = mapi_req;
561 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
562 mapi_request->handles[0] = mapi_object_get_handle(obj_src);
563 mapi_request->handles[1] = mapi_object_get_handle(obj_dst);
565 status = emsmdb_transaction_wrapper(session[0], mem_ctx, mapi_request, &mapi_response);
566 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
567 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
568 retval = mapi_response->mapi_repl->error_code;
569 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
571 OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
573 talloc_free(mapi_response);
574 talloc_free(mem_ctx);
576 return MAPI_E_SUCCESS;
581 \details Create a folder
583 The function creates a folder (defined with its name, comment and type)
584 within a specified folder.
586 \param obj_parent the folder to create the new folder in
587 \param ulFolderType the type of the folder
588 \param name the name of the new folder
589 \param comment the comment associated with the new folder
590 \param ulFlags flags associated with folder creation
591 \param obj_child pointer to the newly created folder
593 ulFlags possible values:
594 - MAPI_UNICODE: use UNICODE folder name and comment
595 - OPEN_IF_EXISTS: open the folder if it already exists
597 ulFolderType possible values:
601 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
603 \note Developers may also call GetLastError() to retrieve the last
604 MAPI error code. Possible MAPI error codes are:
605 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
606 - MAPI_E_CALL_FAILED: A network problem was encountered during the
609 \sa OpenFolder, DeleteFolder, EmptyFolder, GetLastError
611 _PUBLIC_ enum MAPISTATUS CreateFolder(mapi_object_t *obj_parent,
612 enum FOLDER_TYPE ulFolderType,
616 mapi_object_t *obj_child)
618 struct mapi_request *mapi_request;
619 struct mapi_response *mapi_response;
620 struct EcDoRpc_MAPI_REQ *mapi_req;
621 struct CreateFolder_req request;
622 struct mapi_session *session;
624 enum MAPISTATUS retval;
630 OPENCHANGE_RETVAL_IF(!obj_parent, MAPI_E_INVALID_PARAMETER, NULL);
631 OPENCHANGE_RETVAL_IF(!name, MAPI_E_NOT_INITIALIZED, NULL);
632 session = mapi_object_get_session(obj_parent);
633 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
635 if ((retval = mapi_object_get_logon_id(obj_parent, &logon_id)) != MAPI_E_SUCCESS)
638 /* Sanitify check on the folder type */
639 OPENCHANGE_RETVAL_IF((ulFolderType != FOLDER_GENERIC &&
640 ulFolderType != FOLDER_SEARCH),
641 MAPI_E_INVALID_PARAMETER, NULL);
643 mem_ctx = talloc_named(NULL, 0, "CreateFolder");
646 /* Fill the CreateFolder operation */
647 request.handle_idx = 0x1;
648 size+= sizeof(uint8_t);
649 switch (ulFlags & 0xFFFF0000) {
651 request.ulType = MAPI_FOLDER_UNICODE;
654 request.ulType = MAPI_FOLDER_ANSI;
657 request.ulFolderType = ulFolderType;
658 size += sizeof(uint16_t);
659 request.ulFlags = ulFlags & 0xFFFF;
660 size += sizeof(uint16_t);
662 switch (request.ulType) {
663 case MAPI_FOLDER_ANSI:
664 request.FolderName.lpszA = name;
665 size += strlen(name) + 1;
667 case MAPI_FOLDER_UNICODE:
668 request.FolderName.lpszW = name;
669 size += get_utf8_utf16_conv_length(name);
674 switch(request.ulType) {
675 case MAPI_FOLDER_ANSI:
676 request.FolderComment.lpszA = comment;
677 size += strlen(comment) + 1;
679 case MAPI_FOLDER_UNICODE:
680 request.FolderComment.lpszW = comment;
681 size += get_utf8_utf16_conv_length(comment);
685 switch(request.ulType) {
686 case MAPI_FOLDER_ANSI:
687 request.FolderComment.lpszA = "";
690 case MAPI_FOLDER_UNICODE:
691 request.FolderComment.lpszW = "";
697 /* Fill the MAPI_REQ request */
698 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
699 mapi_req->opnum = op_MAPI_CreateFolder;
700 mapi_req->logon_id = logon_id;
701 mapi_req->handle_idx = 0;
702 mapi_req->u.mapi_CreateFolder = request;
705 /* Fill the mapi_request structure */
706 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
707 mapi_request->mapi_len = size + (2 * sizeof(uint32_t));
708 mapi_request->length = size;
709 mapi_request->mapi_req = mapi_req;
710 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
711 mapi_request->handles[0] = mapi_object_get_handle(obj_parent);
712 mapi_request->handles[1] = 0xffffffff;
714 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
715 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
716 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
717 retval = mapi_response->mapi_repl->error_code;
718 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
720 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
722 /* Set object session, handle and id */
723 mapi_object_init(obj_child);
724 mapi_object_set_session(obj_child, session);
725 mapi_object_set_handle(obj_child, mapi_response->handles[1]);
726 mapi_object_set_id(obj_child, mapi_response->mapi_repl->u.mapi_CreateFolder.folder_id);
727 mapi_object_set_logon_id(obj_child, logon_id);
729 talloc_free(mapi_response);
730 talloc_free(mem_ctx);
732 return MAPI_E_SUCCESS;
737 \details Empty the contents of a folder
739 This function empties (clears) the contents of a specified folder.
741 \param obj_folder the folder to empty
743 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
745 \note Developers may also call GetLastError() to retrieve the last
746 MAPI error code. Possible MAPI error codes are:
747 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
748 - MAPI_E_CALL_FAILED: A network problem was encountered during the
751 \sa OpenFolder, CreateFolder, DeleteFolder, GetLastError
753 _PUBLIC_ enum MAPISTATUS EmptyFolder(mapi_object_t *obj_folder)
755 struct mapi_request *mapi_request;
756 struct mapi_response *mapi_response;
757 struct EcDoRpc_MAPI_REQ *mapi_req;
758 struct EmptyFolder_req request;
759 struct mapi_session *session;
761 enum MAPISTATUS retval;
767 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
768 session = mapi_object_get_session(obj_folder);
769 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
771 if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
774 mem_ctx = talloc_named(NULL, 0, "EmptyFolder");
777 /* Fill the EmptyFolder operation */
778 request.WantAsynchronous = 0x0;
779 size += sizeof (uint8_t);
781 request.WantDeleteAssociated = 0x0;
782 size += sizeof (uint8_t);
784 /* Fill the MAPI_REQ request */
785 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
786 mapi_req->opnum = op_MAPI_EmptyFolder;
787 mapi_req->logon_id = logon_id;
788 mapi_req->handle_idx = 0;
789 mapi_req->u.mapi_EmptyFolder = request;
792 /* Fill the mapi_request structure */
793 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
794 mapi_request->mapi_len = size + sizeof(uint32_t);
795 mapi_request->length = size;
796 mapi_request->mapi_req = mapi_req;
797 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
798 mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
800 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
801 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
802 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
803 retval = mapi_response->mapi_repl->error_code;
804 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
806 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
808 talloc_free(mapi_response);
809 talloc_free(mem_ctx);
811 return MAPI_E_SUCCESS;
816 \details Delete a folder
818 The function deletes a specified folder.
820 \param obj_parent the folder containing the folder to be deleted
821 \param FolderId the ID of the folder to delete
822 \param DeleteFolderFlags control DeleteFolder operation behavior
823 \param PartialCompletion pointer on a boolean value which specify
824 whether the operation was partially completed or not
826 Possible values for DeleteFolderFlags are:
827 -# DEL_MESSAGES Delete all the messages in the folder
828 -# DEL_FOLDERS Delete the subfolder and all of its subfolders
829 -# DELETE_HARD_DELETE Hard delete the folder
831 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
833 \note Developers may also call GetLastError() to retrieve the last
834 MAPI error code. Possible MAPI error codes are:
835 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
836 - MAPI_E_CALL_FAILED: A network problem was encountered during the
839 \sa OpenFolder, CreateFolder, EmptyFolder, GetLastError
841 _PUBLIC_ enum MAPISTATUS DeleteFolder(mapi_object_t *obj_parent,
843 uint8_t DeleteFolderFlags,
844 bool *PartialCompletion)
846 struct mapi_request *mapi_request;
847 struct mapi_response *mapi_response;
848 struct EcDoRpc_MAPI_REQ *mapi_req;
849 struct DeleteFolder_req request;
850 struct mapi_session *session;
852 enum MAPISTATUS retval;
858 OPENCHANGE_RETVAL_IF(!obj_parent, MAPI_E_INVALID_PARAMETER, NULL);
859 session = mapi_object_get_session(obj_parent);
860 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
861 OPENCHANGE_RETVAL_IF((!(DeleteFolderFlags & 0x1)) &&
862 (!(DeleteFolderFlags & 0x4)) &&
863 (!(DeleteFolderFlags & 0x10)),
864 MAPI_E_INVALID_PARAMETER, NULL);
866 if ((retval = mapi_object_get_logon_id(obj_parent, &logon_id)) != MAPI_E_SUCCESS)
869 mem_ctx = talloc_named(NULL, 0, "DeleteFolder");
872 /* Fill the DeleteFolder operation */
873 request.DeleteFolderFlags = DeleteFolderFlags;
874 size += sizeof (uint8_t);
875 request.FolderId = FolderId;
876 size += sizeof (uint64_t);
878 /* Fill the MAPI_REQ request */
879 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
880 mapi_req->opnum = op_MAPI_DeleteFolder;
881 mapi_req->logon_id = logon_id;
882 mapi_req->handle_idx = 0;
883 mapi_req->u.mapi_DeleteFolder = request;
886 /* Fill the mapi_request structure */
887 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
888 mapi_request->mapi_len = size + sizeof(uint32_t);
889 mapi_request->length = size;
890 mapi_request->mapi_req = mapi_req;
891 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
892 mapi_request->handles[0] = mapi_object_get_handle(obj_parent);
894 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
895 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
896 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
897 retval = mapi_response->mapi_repl->error_code;
898 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
900 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
902 if (PartialCompletion) {
903 *PartialCompletion = mapi_response->mapi_repl->u.mapi_DeleteFolder.PartialCompletion;
906 talloc_free(mapi_response);
907 talloc_free(mem_ctx);
909 return MAPI_E_SUCCESS;
914 \details Moves a folder
916 \param obj_folder the folder to move
917 \param obj_src source object where the folder to move is stored
918 \param obj_dst destination object where the folder will be moved
919 \param NewFolderName the new folder name in the destination folder
920 \param UseUnicode whether the folder name is unicode encoded or not
922 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
924 \note Developers may also call GetLastError() to retrieve the last
925 MAPI error code. Possible MAPI error codes are:
926 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
927 - MAPI_E_CALL_FAILED: A network problem was encountered during the
930 \sa OpenFolder, CopyFolder
932 _PUBLIC_ enum MAPISTATUS MoveFolder(mapi_object_t *obj_folder,
933 mapi_object_t *obj_src,
934 mapi_object_t *obj_dst,
938 struct mapi_request *mapi_request;
939 struct mapi_response *mapi_response;
940 struct EcDoRpc_MAPI_REQ *mapi_req;
941 struct MoveFolder_req request;
942 struct mapi_session *session[3];
944 enum MAPISTATUS retval;
950 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
951 OPENCHANGE_RETVAL_IF(!obj_src, MAPI_E_INVALID_PARAMETER, NULL);
952 OPENCHANGE_RETVAL_IF(!obj_dst, MAPI_E_INVALID_PARAMETER, NULL);
953 OPENCHANGE_RETVAL_IF(!NewFolderName, MAPI_E_INVALID_PARAMETER, NULL);
955 session[0] = mapi_object_get_session(obj_folder);
956 session[1] = mapi_object_get_session(obj_src);
957 session[2] = mapi_object_get_session(obj_dst);
958 OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
959 OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
960 OPENCHANGE_RETVAL_IF(!session[2], MAPI_E_INVALID_PARAMETER, NULL);
962 if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
965 mem_ctx = talloc_named(NULL, 0, "MoveFolder");
968 /* Fill the MoveFolder operation */
969 request.handle_idx = 0x1;
970 size += sizeof (uint8_t);
972 request.WantAsynchronous = 0;
973 size += sizeof (uint8_t);
975 request.UseUnicode = UseUnicode;
976 size += sizeof (uint8_t);
978 request.FolderId = mapi_object_get_id(obj_folder);
979 size += sizeof (uint64_t);
981 if (!request.UseUnicode) {
982 request.NewFolderName.lpszA = NewFolderName;
983 size += strlen(NewFolderName) + 1;
985 request.NewFolderName.lpszW = NewFolderName;
986 size += get_utf8_utf16_conv_length(NewFolderName);
990 /* Fill the MAPI_REQ request */
991 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
992 mapi_req->opnum = op_MAPI_MoveFolder;
993 mapi_req->logon_id = logon_id;
994 mapi_req->handle_idx = 0;
995 mapi_req->u.mapi_MoveFolder = request;
998 /* Fill the mapi_request structure */
999 mapi_request = talloc(mem_ctx, struct mapi_request);
1000 mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
1001 mapi_request->length = size;
1002 mapi_request->mapi_req = mapi_req;
1003 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
1004 mapi_request->handles[0] = mapi_object_get_handle(obj_src);
1005 mapi_request->handles[1] = mapi_object_get_handle(obj_dst);
1007 status = emsmdb_transaction_wrapper(session[0], mem_ctx, mapi_request, &mapi_response);
1008 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
1009 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
1010 retval = mapi_response->mapi_repl->error_code;
1011 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
1013 OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
1015 talloc_free(mapi_response);
1016 talloc_free(mem_ctx);
1018 return MAPI_E_SUCCESS;
1023 \details Copy a folder
1025 \param obj_folder the folder to copy
1026 \param obj_src source object where the folder to copy is stored
1027 \param obj_dst destination object where the folder will be copied
1028 \param NewFolderName the new folder name in the destination folder
1029 \param UseUnicode whether the folder name is unicode encoded or not
1030 \param WantRecursive whether we should copy folder's subdirectories
1033 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
1035 \note Developer may also call GetLastError() to retrieve the last
1036 MAPI error code. Possible MAPI error codes are:
1037 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
1038 - MAPI_E_CALL_FAILED: A network problem was encountered during the
1041 \sa OpenFolder, MoveFolder
1043 _PUBLIC_ enum MAPISTATUS CopyFolder(mapi_object_t *obj_folder,
1044 mapi_object_t *obj_src,
1045 mapi_object_t *obj_dst,
1046 char *NewFolderName,
1050 struct mapi_request *mapi_request;
1051 struct mapi_response *mapi_response;
1052 struct EcDoRpc_MAPI_REQ *mapi_req;
1053 struct CopyFolder_req request;
1054 struct mapi_session *session[3];
1056 enum MAPISTATUS retval;
1058 TALLOC_CTX *mem_ctx;
1062 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
1063 OPENCHANGE_RETVAL_IF(!obj_src, MAPI_E_INVALID_PARAMETER, NULL);
1064 OPENCHANGE_RETVAL_IF(!obj_dst, MAPI_E_INVALID_PARAMETER, NULL);
1065 OPENCHANGE_RETVAL_IF(!NewFolderName, MAPI_E_INVALID_PARAMETER, NULL);
1067 session[0] = mapi_object_get_session(obj_folder);
1068 session[1] = mapi_object_get_session(obj_src);
1069 session[2] = mapi_object_get_session(obj_dst);
1070 OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
1071 OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
1072 OPENCHANGE_RETVAL_IF(!session[2], MAPI_E_INVALID_PARAMETER, NULL);
1074 if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
1077 mem_ctx = talloc_named(NULL, 0, "CopyFolder");
1081 /* Fill the CopyFolder operation */
1082 request.handle_idx = 0x1;
1083 size += sizeof (uint8_t);
1085 request.WantAsynchronous = 0x0;
1086 size += sizeof (uint8_t);
1088 request.WantRecursive = WantRecursive;
1089 size += sizeof (uint8_t);
1091 request.UseUnicode = UseUnicode;
1092 size += sizeof (uint8_t);
1094 request.FolderId = mapi_object_get_id(obj_folder);
1095 size += sizeof (uint64_t);
1097 if (!request.UseUnicode) {
1098 request.NewFolderName.lpszA = NewFolderName;
1099 size += strlen(NewFolderName) + 1;
1101 request.NewFolderName.lpszW = NewFolderName;
1102 size += get_utf8_utf16_conv_length(NewFolderName);
1105 /* Fill the MAPI_REQ request */
1106 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
1107 mapi_req->opnum = op_MAPI_CopyFolder;
1108 mapi_req->logon_id = logon_id;
1109 mapi_req->handle_idx = 0;
1110 mapi_req->u.mapi_CopyFolder = request;
1113 /* Fill the mapi_request structure */
1114 mapi_request = talloc(mem_ctx, struct mapi_request);
1115 mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
1116 mapi_request->length = size;
1117 mapi_request->mapi_req = mapi_req;
1118 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
1119 mapi_request->handles[0] = mapi_object_get_handle(obj_src);
1120 mapi_request->handles[1] = mapi_object_get_handle(obj_dst);
1122 status = emsmdb_transaction_wrapper(session[0], mem_ctx, mapi_request, &mapi_response);
1123 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
1124 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
1125 retval = mapi_response->mapi_repl->error_code;
1126 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
1128 OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
1130 talloc_free(mapi_response);
1131 talloc_free(mem_ctx);
1133 return MAPI_E_SUCCESS;
1138 \details Set the Read Flags on one or more messages
1140 \param obj_folder the folder containing the messages to change
1141 \param ReadFlags a bitmap of flags controlling the changes to
1143 \param MessageIdCount the number of messages in the MessageIds array
1144 \param MessageIds an array of message ids to set Read flags for
1146 Note that the obj_folder argument is the object corresponding to the
1147 folder containing the messages (e.g. the result of CreateFolder() or
1148 OpenFolder(). It is \em not the content table of that folder (unlike
1149 SetMessageReadFlag().)
1151 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
1153 \note Developers may also call GetLastError() to retrieve the last
1154 MAPI error code. Possible MAPI error codes are:
1155 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
1156 - MAPI_E_CALL_FAILED: A network problem was encountered during the
1159 \sa SetMessageReadFlags for a slightly different version, working on
1162 _PUBLIC_ enum MAPISTATUS SetReadFlags(mapi_object_t *obj_folder,
1164 uint16_t MessageIdCount,
1165 uint64_t *MessageIds)
1167 TALLOC_CTX *mem_ctx;
1169 struct SetReadFlags_req request;
1170 struct EcDoRpc_MAPI_REQ *mapi_req;
1171 struct mapi_request *mapi_request;
1172 struct mapi_session *session;
1174 struct mapi_response *mapi_response;
1175 enum MAPISTATUS retval;
1179 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
1180 session = mapi_object_get_session(obj_folder);
1181 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
1183 if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
1186 mem_ctx = talloc_named(NULL, 0, "SetReadFlags");
1190 /* Fill the SetReadFlags operation */
1191 request.WantAsynchronous = 0;
1192 size += sizeof(uint8_t);
1193 request.ReadFlags = ReadFlags;
1194 size += sizeof(uint8_t);
1195 request.MessageIdCount = MessageIdCount;
1196 size += sizeof(uint16_t);
1197 request.MessageIds = MessageIds;
1198 size += sizeof(uint64_t) * MessageIdCount;
1201 /* Fill the MAPI_REQ request */
1202 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
1203 mapi_req->opnum = op_MAPI_SetReadFlags;
1204 mapi_req->logon_id = logon_id;
1205 mapi_req->handle_idx = 0;
1206 mapi_req->u.mapi_SetReadFlags = request;
1209 /* Fill the mapi_request structure */
1210 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
1211 mapi_request->mapi_len = size + sizeof(uint32_t);
1212 mapi_request->length = size;
1213 mapi_request->mapi_req = mapi_req;
1214 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
1215 mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
1217 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
1218 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
1219 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
1220 retval = mapi_response->mapi_repl->error_code;
1221 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
1223 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
1225 /* TODO: parse response */
1227 talloc_free(mapi_response);
1228 talloc_free(mem_ctx);
1230 return MAPI_E_SUCCESS;
1234 \details Hard delete the contents of a folder, including subfolders
1236 This function empties (clears) the contents of a specified folder.
1238 \param obj_folder the folder to empty
1240 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
1242 \note Developers may also call GetLastError() to retrieve the last
1243 MAPI error code. Possible MAPI error codes are:
1244 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
1245 - MAPI_E_INVALID_PARAMETER: obj_folder is not valid
1246 - MAPI_E_CALL_FAILED: A network problem was encountered during the
1249 \sa DeleteFolder, EmptyFolder
1251 _PUBLIC_ enum MAPISTATUS HardDeleteMessagesAndSubfolders(mapi_object_t *obj_folder)
1253 struct mapi_request *mapi_request;
1254 struct mapi_response *mapi_response;
1255 struct EcDoRpc_MAPI_REQ *mapi_req;
1256 struct HardDeleteMessagesAndSubfolders_req request;
1257 struct mapi_session *session;
1259 enum MAPISTATUS retval;
1261 TALLOC_CTX *mem_ctx;
1265 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
1266 session = mapi_object_get_session(obj_folder);
1267 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
1269 if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
1272 mem_ctx = talloc_named(NULL, 0, "HardDeleteMessagesAndSubfolders");
1275 /* Fill the EmptyFolder operation */
1276 request.WantAsynchronous = 0x0;
1277 size += sizeof (uint8_t);
1279 request.WantDeleteAssociated = 0x0;
1280 size += sizeof (uint8_t);
1282 /* Fill the MAPI_REQ request */
1283 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
1284 mapi_req->opnum = op_MAPI_HardDeleteMessagesAndSubfolders;
1285 mapi_req->logon_id = logon_id;
1286 mapi_req->handle_idx = 0;
1287 mapi_req->u.mapi_HardDeleteMessagesAndSubfolders = request;
1290 /* Fill the mapi_request structure */
1291 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
1292 mapi_request->mapi_len = size + sizeof(uint32_t);
1293 mapi_request->length = size;
1294 mapi_request->mapi_req = mapi_req;
1295 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
1296 mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
1298 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
1299 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
1300 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
1301 retval = mapi_response->mapi_repl->error_code;
1302 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
1304 talloc_free(mapi_response);
1305 talloc_free(mem_ctx);
1307 return MAPI_E_SUCCESS;