2 OpenChange MAPI implementation.
4 Copyright (C) Julien Kerihuel 2007-2011.
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 Convenience functions.
32 \details Retrieve the folder id for the specified default folder in
35 \param obj_store the store to search
36 \param id the type of folder to search for
37 \param folder the resulting folder reference
39 The following types of folders are supported:
40 - olFolderPublicRoot - the parent (directly or indirectly) for the folders below
41 - olFolderPublicIPMSubtree - Interpersonal Messages (IPM) folders
42 - olFolderPublicNonIPMSubtree - Non-interpersonal message folders
43 - olFolderPublicEFormsRoot - EForms Registry Root Folder
44 - olFolderPublicFreeBusyRoot - Free/busy root folder
45 - olFolderPublicOfflineAB - Offline address book root folder
46 - olFolderPublicEFormsRegistry - EForms Registry for the users locale
47 - olFolderPublicLocalFreeBusy - Site local free/busy folders
48 - olFolderPublicLocalOfflineAB - Site local Offline address book
49 - olFolderPublicNNTPArticle - NNTP article index folder
51 \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
54 \note Developers may also call GetLastError() to retrieve the last
55 MAPI error code. Possible MAPI error codes are:
56 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
57 - MAPI_E_INVALID_PARAMETER: obj_store is undefined
58 - MAPI_E_NOT_FOUND: The specified folder could not be found or is
61 \sa MAPIInitialize, OpenPublicFolder, GetLastError
63 _PUBLIC_ enum MAPISTATUS GetDefaultPublicFolder(mapi_object_t *obj_store,
67 OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
70 case olFolderPublicRoot:
71 *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_public_root;
73 case olFolderPublicIPMSubtree:
74 *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_ipm_subtree;
76 case olFolderPublicNonIPMSubtree:
77 *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_non_ipm_subtree;
79 case olFolderPublicEFormsRoot:
80 *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_EFormsRegistryRoot;
82 case olFolderPublicFreeBusyRoot:
83 *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_FreeBusyRoot;
85 case olFolderPublicOfflineAB:
86 *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_OfflineAB;
88 case olFolderPublicEFormsRegistry:
89 *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_EFormsRegistry;
91 case olFolderPublicLocalFreeBusy:
92 *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_LocalSiteFreeBusy;
94 case olFolderPublicLocalOfflineAB:
95 *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_LocalSiteOfflineAB;
97 case olFolderPublicNNTPArticle:
98 *folder = ((mapi_object_store_t *)obj_store->private_data)->fid_pf_NNTPArticle;
101 OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, NULL);
104 return MAPI_E_SUCCESS;
108 static enum MAPISTATUS CacheDefaultFolders(mapi_object_t *obj_store)
110 enum MAPISTATUS retval;
112 mapi_object_store_t *store;
113 mapi_object_t obj_inbox;
115 struct SPropTagArray *SPropTagArray = NULL;
117 struct SPropValue *lpProps;
119 const struct Binary_r *entryid;
122 OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
124 store = (mapi_object_store_t *)obj_store->private_data;
125 OPENCHANGE_RETVAL_IF(!store, MAPI_E_NOT_INITIALIZED, NULL);
127 mem_ctx = talloc_named(mapi_object_get_session(obj_store), 0, "CacheDefaultFolders");
129 mapi_object_init(&obj_inbox);
130 retval = GetReceiveFolder(obj_store, &id_inbox, NULL);
131 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
133 retval = OpenFolder(obj_store, id_inbox, &obj_inbox);
134 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
136 SPropTagArray = set_SPropTagArray(mem_ctx, 0x6,
137 PR_IPM_APPOINTMENT_ENTRYID,
138 PR_IPM_CONTACT_ENTRYID,
139 PR_IPM_JOURNAL_ENTRYID,
142 PR_IPM_DRAFTS_ENTRYID);
144 retval = GetProps(&obj_inbox, 0, SPropTagArray, &lpProps, &count);
145 MAPIFreeBuffer(SPropTagArray);
146 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
148 aRow.cValues = count;
149 aRow.lpProps = lpProps;
151 /* set cached calendar FID */
152 entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_APPOINTMENT_ENTRYID);
153 OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
154 retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_calendar);
155 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
157 /* set cached contact FID */
158 entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_CONTACT_ENTRYID);
159 OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
160 retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_contact);
161 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
163 /* set cached journal FID */
164 entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_JOURNAL_ENTRYID);
165 OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
166 retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_journal);
167 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
169 /* set cached note FID */
170 entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_NOTE_ENTRYID);
171 OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
172 retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_note);
173 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
175 /* set cached task FID */
176 entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_TASK_ENTRYID);
177 OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
178 retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_task);
179 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
181 /* set cached drafts FID */
182 entryid = (const struct Binary_r *)find_SPropValue_data(&aRow, PR_IPM_DRAFTS_ENTRYID);
183 OPENCHANGE_RETVAL_IF(!entryid, MAPI_E_NOT_FOUND, mem_ctx);
184 retval = GetFIDFromEntryID(entryid->cb, entryid->lpb, id_inbox, &store->fid_drafts);
185 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
187 store->store_type = PrivateFolderWithCachedFids;
189 mapi_object_release(&obj_inbox);
190 talloc_free(mem_ctx);
192 return MAPI_E_SUCCESS;
197 \details Retrieves the folder id for the specified default folder
200 \param obj_store the store to search
201 \param id the type of folder to search for
202 \param folder the resulting folder reference
204 The following types of folders are supported:
205 - olFolderTopInformationStore
206 - olFolderDeletedItems
220 Note that this function will cache FID values for common accessed
221 folders such as calendar, contact, journal, note, task and drafts
222 until the store object got released.
224 \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
225 indicating the error.
227 \note Developers may also call GetLastError() to retrieve the last
228 MAPI error code. Possible MAPI error codes are:
229 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
230 - MAPI_E_INVALID_PARAMETER: obj_store is undefined
231 - MAPI_E_NOT_FOUND: The specified folder could not be found or is
234 \sa MAPIInitialize, OpenMsgStore, GetLastError
236 _PUBLIC_ enum MAPISTATUS GetDefaultFolder(mapi_object_t *obj_store,
240 enum MAPISTATUS retval;
241 mapi_object_store_t *store;
244 OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
245 OPENCHANGE_RETVAL_IF(!folder, MAPI_E_INVALID_PARAMETER, NULL);
247 store = (mapi_object_store_t *)obj_store->private_data;
248 OPENCHANGE_RETVAL_IF(!store, MAPI_E_NOT_INITIALIZED, NULL);
250 if ((id > 6) && (store->store_type == PrivateFolderWithoutCachedFids)) {
251 retval = CacheDefaultFolders(obj_store);
252 OPENCHANGE_RETVAL_IF(retval, retval, NULL);
256 case olFolderMailboxRoot:
257 *folder = store->fid_mailbox_root;
258 return MAPI_E_SUCCESS;
259 case olFolderTopInformationStore:
260 *folder = store->fid_top_information_store;
261 return MAPI_E_SUCCESS;
262 case olFolderDeletedItems:
263 *folder = store->fid_deleted_items;
264 return MAPI_E_SUCCESS;
266 *folder = store->fid_outbox;
267 return MAPI_E_SUCCESS;
268 case olFolderSentMail:
269 *folder = store->fid_sent_items;
270 return MAPI_E_SUCCESS;
272 *folder = store->fid_inbox;
273 return MAPI_E_SUCCESS;
274 case olFolderCommonView:
275 *folder = store->fid_common_views;
276 return MAPI_E_SUCCESS;
277 case olFolderCalendar:
278 *folder = store->fid_calendar;
279 return MAPI_E_SUCCESS;
280 case olFolderContacts:
281 *folder = store->fid_contact;
282 return MAPI_E_SUCCESS;
283 case olFolderJournal:
284 *folder = store->fid_journal;
285 return MAPI_E_SUCCESS;
287 *folder = store->fid_note;
288 return MAPI_E_SUCCESS;
290 *folder = store->fid_task;
291 return MAPI_E_SUCCESS;
293 *folder = store->fid_drafts;
294 return MAPI_E_SUCCESS;
296 *folder = store->fid_search;
297 return MAPI_E_SUCCESS;
300 OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, 0);
306 \details Check if a given folder identifier matches with a
307 system/default one and optionally returns the olFolder type
309 \param obj_store pointer to the store object
310 \param fid reference to the folder identifier to check
311 \param olFolder pointer to the returned olFolder
313 \return true on success, otherwise false
315 _PUBLIC_ bool IsMailboxFolder(mapi_object_t *obj_store,
319 enum MAPISTATUS retval;
320 mapi_object_store_t *store;
321 uint32_t olFolderNum = 0;
327 store = (mapi_object_store_t *) obj_store->private_data;
336 if (store->store_type == PrivateFolderWithoutCachedFids) {
337 retval = CacheDefaultFolders(obj_store);
343 if(fid == store->fid_top_information_store) {
344 olFolderNum = olFolderTopInformationStore;
345 } else if (fid == store->fid_deleted_items) {
346 olFolderNum = olFolderDeletedItems;
347 } else if (fid == store->fid_outbox) {
348 olFolderNum = olFolderOutbox;
349 } else if (fid == store->fid_sent_items) {
350 olFolderNum = olFolderSentMail;
351 } else if (fid == store->fid_inbox) {
352 olFolderNum = olFolderInbox;
353 } else if (fid == store->fid_common_views) {
354 olFolderNum = olFolderCommonView;
355 } else if (fid == store->fid_calendar) {
356 olFolderNum = olFolderCalendar;
357 } else if (fid == store->fid_contact) {
358 olFolderNum = olFolderContacts;
359 } else if (fid == store->fid_journal) {
360 olFolderNum = olFolderJournal;
361 } else if (fid == store->fid_note) {
362 olFolderNum = olFolderNotes;
363 } else if (fid == store->fid_task) {
364 olFolderNum = olFolderTasks;
365 } else if (fid == store->fid_drafts) {
366 olFolderNum = olFolderDrafts;
367 } else if (fid == store->fid_search) {
368 olFolderNum = olFolderFinder;
369 } else if (fid == store->fid_pf_OfflineAB) {
370 olFolderNum = olFolderPublicOfflineAB;
371 } else if (fid == store->fid_pf_FreeBusyRoot) {
372 olFolderNum = olFolderPublicFreeBusyRoot;
373 } else if (fid == store->fid_pf_EFormsRegistryRoot) {
374 olFolderNum = olFolderPublicEFormsRoot;
375 } else if (fid == store->fid_pf_EFormsRegistry) {
376 olFolderNum = olFolderPublicEFormsRegistry;
377 } else if (fid == store->fid_pf_public_root) {
378 olFolderNum = olFolderPublicRoot;
379 } else if (fid == store->fid_pf_ipm_subtree) {
380 olFolderNum = olFolderPublicIPMSubtree;
381 } else if (fid == store->fid_pf_non_ipm_subtree) {
382 olFolderNum = olFolderPublicNonIPMSubtree;
383 } else if (fid == store->fid_pf_LocalSiteFreeBusy) {
384 olFolderNum = olFolderPublicLocalFreeBusy;
385 } else if (fid == store->fid_pf_LocalSiteOfflineAB) {
386 olFolderNum = olFolderPublicLocalOfflineAB;
387 } else if (fid == store->fid_pf_NNTPArticle) {
388 olFolderNum = olFolderPublicNNTPArticle;
390 olFolderNum = 0xFFFFFFFF;
394 if (olFolder) *olFolder = olFolderNum;
399 \details Retrieves the total and unread number of items for a
402 \param obj_folder the folder to get item counts for
403 \param unread the number of items in the folder (result)
404 \param total the number of items in the folder, including unread
407 \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
408 indicating the error.
410 \note Developers may also call GetLastError() to retrieve the last
411 MAPI error code. Possible MAPI error codes are:
412 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
413 - MAPI_E_INVALID_PARAMETER: obj_folder is undefined
414 - MAPI_E_NOT_FOUND: The specified folder could not be found or is
417 \sa MAPIInitialize, OpenFolder, GetLastError
419 _PUBLIC_ enum MAPISTATUS GetFolderItemsCount(mapi_object_t *obj_folder,
423 enum MAPISTATUS retval;
425 struct SPropTagArray *SPropTagArray;
426 struct SPropValue *lpProps;
429 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
430 OPENCHANGE_RETVAL_IF(!unread, MAPI_E_INVALID_PARAMETER, NULL);
431 OPENCHANGE_RETVAL_IF(!total, MAPI_E_INVALID_PARAMETER, NULL);
433 mem_ctx = talloc_named(mapi_object_get_session(obj_folder), 0, "GetFolderItemsCount");
435 SPropTagArray = set_SPropTagArray(mem_ctx, 0x2,
439 retval = GetProps(obj_folder, 0, SPropTagArray, &lpProps, &count);
440 MAPIFreeBuffer(SPropTagArray);
441 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
443 *unread = lpProps[0].value.l;
444 *total = lpProps[1].value.l;
446 talloc_free(mem_ctx);
448 return MAPI_E_SUCCESS;
453 \details Adds permissions for a user on a given folder
455 \param obj_folder the folder we add permission for
456 \param username the Exchange username we add permissions for
457 \param role the permission mask value
459 The following permissions and rights are supported:
467 - RightsCreateSubfolders
469 - RightsFolderContact
473 - RoleNoneditingAuthor
481 \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
482 indicating the error.
484 \note Developers may also call GetLastError() to retrieve the last
485 MAPI error code. Possible MAPI error codes are:
486 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
487 - MAPI_E_INVALID_PARAMETER: username is NULL
489 \sa ResolveNames, ModifyPermissions
491 _PUBLIC_ enum MAPISTATUS AddUserPermission(mapi_object_t *obj_folder, const char *username, enum ACLRIGHTS role)
493 enum MAPISTATUS retval;
495 struct SPropTagArray *SPropTagArray;
496 const char *names[2];
497 struct SRowSet *rows = NULL;
498 struct PropertyTagArray_r *flaglist = NULL;
499 struct mapi_PermissionsData rowList;
502 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
503 OPENCHANGE_RETVAL_IF(!username, MAPI_E_INVALID_PARAMETER, NULL);
505 rowList.ModifyFlags = 0;
507 mem_ctx = talloc_named(mapi_object_get_session(obj_folder), 0, "AddUserPermission");
509 /* query Address book */
511 SPropTagArray = set_SPropTagArray(mem_ctx, 2, PR_ENTRYID, PR_DISPLAY_NAME);
514 retval = ResolveNames(mapi_object_get_session(obj_folder), (const char **)names,
515 SPropTagArray, &rows, &flaglist, 0);
516 MAPIFreeBuffer(SPropTagArray);
517 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
520 OPENCHANGE_RETVAL_IF(!flaglist, MAPI_E_NOT_FOUND, mem_ctx);
521 OPENCHANGE_RETVAL_IF(!rows, MAPI_E_NOT_FOUND, mem_ctx);
522 /* Check if the username was found */
523 OPENCHANGE_RETVAL_IF((flaglist->aulPropTag[0] != MAPI_RESOLVED), MAPI_E_NOT_FOUND, mem_ctx);
525 rowList.ModifyCount = 1;
526 rowList.PermissionsData = talloc_array(mem_ctx, struct PermissionData, 1);
527 rowList.PermissionsData[0].PermissionDataFlags = ROW_ADD;
528 rowList.PermissionsData[0].lpProps.cValues = 2;
529 rowList.PermissionsData[0].lpProps.lpProps = talloc_array(mem_ctx, struct mapi_SPropValue, 2);
530 cast_mapi_SPropValue((TALLOC_CTX *)rowList.PermissionsData[0].lpProps.lpProps,
531 &rowList.PermissionsData[0].lpProps.lpProps[0], &rows->aRow[0].lpProps[0]);
532 rowList.PermissionsData[0].lpProps.lpProps[1].ulPropTag = PR_MEMBER_RIGHTS;
533 rowList.PermissionsData[0].lpProps.lpProps[1].value.l = role;
535 retval = ModifyPermissions(obj_folder, 0, &rowList);
536 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
538 talloc_free(mem_ctx);
540 return MAPI_E_SUCCESS;
545 \details Modify permissions for a user on a given folder
547 \param obj_folder the folder to modify permissions for
548 \param username the Exchange username to modify permissions for
549 \param role the permission mask value (see AddUserPermission)
551 \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
552 indicating the error.
554 \note Developers may also call GetLastError() to retrieve the last
555 MAPI error code. Possible MAPI error codes are:
556 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
557 - MAPI_E_INVALID_PARAMETER: username is NULL
558 - MAPI_E_NOT_FOUND: couldn't find or change permissions for the
561 \sa AddUserPermission, ResolveNames, GetPermissionsTable, ModifyPermissions
563 _PUBLIC_ enum MAPISTATUS ModifyUserPermission(mapi_object_t *obj_folder,
564 const char *username,
567 enum MAPISTATUS retval;
569 struct SPropTagArray *SPropTagArray;
570 const char *names[2];
571 const char *user = NULL;
572 struct SRowSet *rows = NULL;
573 struct SRowSet rowset;
574 struct PropertyTagArray_r *flaglist = NULL;
575 struct mapi_PermissionsData rowList;
576 struct SPropValue *lpProp;
577 mapi_object_t obj_table;
579 uint32_t Denominator;
583 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
584 OPENCHANGE_RETVAL_IF(!username, MAPI_E_INVALID_PARAMETER, NULL);
586 rowList.ModifyFlags = 0;
588 mem_ctx = talloc_named(mapi_object_get_session(obj_folder), 0, "ModifyUserPermission");
590 SPropTagArray = set_SPropTagArray(mem_ctx, 2, PR_ENTRYID, PR_DISPLAY_NAME);
593 retval = ResolveNames(mapi_object_get_session(obj_folder), (const char **)names,
594 SPropTagArray, &rows, &flaglist, 0);
595 MAPIFreeBuffer(SPropTagArray);
596 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
598 if (flaglist->aulPropTag[0] == MAPI_RESOLVED) {
599 user = (const char *) find_SPropValue_data(&(rows->aRow[0]), PR_DISPLAY_NAME);
601 /* Special case: Not a AD user account but Default or
602 * Anonymous. Since names are language specific, we
608 mapi_object_init(&obj_table);
609 retval = GetPermissionsTable(obj_folder, 0x00, &obj_table);
611 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
613 SPropTagArray = set_SPropTagArray(mem_ctx, 4,
618 retval = SetColumns(&obj_table, SPropTagArray);
619 MAPIFreeBuffer(SPropTagArray);
620 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
622 retval = QueryPosition(&obj_table, &Numerator, &Denominator);
623 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
625 retval = QueryRows(&obj_table, Denominator, TBL_ADVANCE, &rowset);
626 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
628 for (i = 0; i < rowset.cRows; i++) {
629 lpProp = get_SPropValue_SRow(&rowset.aRow[i], PR_MEMBER_NAME);
630 if (lpProp && lpProp->value.lpszA) {
631 if (!strcmp(lpProp->value.lpszA, user)) {
632 rowList.ModifyCount = 1;
633 rowList.PermissionsData = talloc_array(mem_ctx, struct PermissionData, 1);
634 rowList.PermissionsData[0].PermissionDataFlags = ROW_MODIFY;
635 rowList.PermissionsData[0].lpProps.cValues = 2;
636 rowList.PermissionsData[0].lpProps.lpProps = talloc_array(mem_ctx, struct mapi_SPropValue, 2);
637 lpProp = get_SPropValue_SRow(&(rowset.aRow[i]), PR_MEMBER_ID);
641 rowList.PermissionsData[0].lpProps.lpProps[0].ulPropTag = PR_MEMBER_ID;
642 rowList.PermissionsData[0].lpProps.lpProps[0].value.d = lpProp->value.d;
643 rowList.PermissionsData[0].lpProps.lpProps[1].ulPropTag = PR_MEMBER_RIGHTS;
644 rowList.PermissionsData[0].lpProps.lpProps[1].value.l = role;
646 retval = ModifyPermissions(obj_folder, 0, &rowList);
647 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
655 mapi_object_release(&obj_table);
656 talloc_free(mem_ctx);
658 OPENCHANGE_RETVAL_IF((!found), MAPI_E_NOT_FOUND, 0);
660 return MAPI_E_SUCCESS;
665 \details Remove permissions for a user on a given folder
667 \param obj_folder the folder to remove permission from
668 \param username the Exchange username to remove permissions for
670 \return MAPI_E_SUCCESS on success, otherwise a failure code (MAPISTATUS)
671 indicating the error.
673 \note Developers may also call GetLastError() to retrieve the last
674 MAPI error code. Possible MAPI error codes are:
675 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized.
676 - MAPI_E_INVALID_PARAMETER: username or obj_folder are NULL
677 - MAPI_E_NOT_FOUND: couldn't find or remove permissions for the
680 \sa ResolveNames, GetPermissionsTable, ModifyPermissions
682 _PUBLIC_ enum MAPISTATUS RemoveUserPermission(mapi_object_t *obj_folder,
683 const char *username)
685 enum MAPISTATUS retval;
687 struct SPropTagArray *SPropTagArray;
688 const char *names[2];
689 const char *user = NULL;
690 struct SRowSet *rows = NULL;
691 struct SRowSet rowset;
692 struct PropertyTagArray_r *flaglist = NULL;
693 struct mapi_PermissionsData rowList;
694 struct SPropValue *lpProp;
695 mapi_object_t obj_table;
697 uint32_t Denominator;
701 OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
702 OPENCHANGE_RETVAL_IF(!username, MAPI_E_INVALID_PARAMETER, NULL);
704 mem_ctx = talloc_named(mapi_object_get_session(obj_folder), 0, "RemoveUserPermission");
706 SPropTagArray = set_SPropTagArray(mem_ctx, 2, PR_ENTRYID, PR_DISPLAY_NAME);
709 retval = ResolveNames(mapi_object_get_session(obj_folder), (const char **)names,
710 SPropTagArray, &rows, &flaglist, 0);
711 MAPIFreeBuffer(SPropTagArray);
712 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
714 /* Check if the username was found */
715 OPENCHANGE_RETVAL_IF((flaglist->aulPropTag[0] != MAPI_RESOLVED), MAPI_E_NOT_FOUND, mem_ctx);
717 user = (const char *)find_SPropValue_data(&(rows->aRow[0]), PR_DISPLAY_NAME);
719 mapi_object_init(&obj_table);
720 retval = GetPermissionsTable(obj_folder, 0x00, &obj_table);
721 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
723 SPropTagArray = set_SPropTagArray(mem_ctx, 4,
728 retval = SetColumns(&obj_table, SPropTagArray);
729 MAPIFreeBuffer(SPropTagArray);
730 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
732 retval = QueryPosition(&obj_table, &Numerator, &Denominator);
733 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
735 retval = QueryRows(&obj_table, Denominator, TBL_ADVANCE, &rowset);
736 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
738 for (i = 0; i < rowset.cRows; i++) {
739 lpProp = get_SPropValue_SRow(&rowset.aRow[i], PR_MEMBER_NAME);
740 if (lpProp && lpProp->value.lpszA) {
741 if (!strcmp(lpProp->value.lpszA, user)) {
742 rowList.ModifyCount = 1;
743 rowList.PermissionsData = talloc_array(mem_ctx, struct PermissionData, 1);
744 rowList.PermissionsData[0].PermissionDataFlags = ROW_REMOVE;
745 rowList.PermissionsData[0].lpProps.cValues = 1;
746 rowList.PermissionsData[0].lpProps.lpProps = talloc_array(mem_ctx, struct mapi_SPropValue, 1);
747 lpProp = get_SPropValue_SRow(&(rowset.aRow[i]), PR_MEMBER_ID);
751 rowList.PermissionsData[0].lpProps.lpProps[0].ulPropTag = PR_MEMBER_ID;
752 rowList.PermissionsData[0].lpProps.lpProps[0].value.d = lpProp->value.d;
754 retval = ModifyPermissions(obj_folder, 0, &rowList);
755 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
762 mapi_object_release(&obj_table);
763 talloc_free(mem_ctx);
765 OPENCHANGE_RETVAL_IF((found != true), MAPI_E_NOT_FOUND, 0);
767 return MAPI_E_SUCCESS;
772 \details Implement the BestBody algorithm and return the best body
773 content type for a given message.
775 \param obj_message the message we find the best body for
776 \param format the format - see below.
778 \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND. If
779 MAPI_E_NOT_FOUND is returned then format is set to 0x0
780 (undefined). If MAPI_E_SUCCESS is returned, then format can have
781 one of the following values:
782 - olEditorText: format is plain text
783 - olEditorHTML: format is HTML
784 - olEditorRTF: format is RTF
786 _PUBLIC_ enum MAPISTATUS GetBestBody(mapi_object_t *obj_message,
789 struct mapi_context *mapi_ctx;
790 struct mapi_session *session;
791 enum MAPISTATUS retval;
792 struct SPropTagArray *SPropTagArray = NULL;
793 struct SPropValue *lpProps;
797 uint32_t PlainStatus;
800 const uint32_t *err_code;
803 OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL);
804 OPENCHANGE_RETVAL_IF(!format, MAPI_E_INVALID_PARAMETER, NULL);
806 session = mapi_object_get_session(obj_message);
807 mapi_ctx = session->mapi_ctx;
809 /* Step 1. Retrieve properties needed by the BestBody algorithm */
810 SPropTagArray = set_SPropTagArray(mapi_ctx->mem_ctx, 0x4,
815 retval = GetProps(obj_message, 0, SPropTagArray, &lpProps, &count);
816 MAPIFreeBuffer(SPropTagArray);
817 if (retval != MAPI_E_SUCCESS) {
819 OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, 0);
822 aRow.ulAdrEntryPad = 0;
823 aRow.cValues = count;
824 aRow.lpProps = lpProps;
826 /* Step 2. Retrieve properties values and map errors */
827 err_code = (const uint32_t *)find_SPropValue_data(&aRow, PR_RTF_IN_SYNC);
828 RtfInSync = (err_code) ? *err_code : 0;
830 err_code = (const uint32_t *)find_SPropValue_data(&aRow, PR_BODY_ERROR);
831 PlainStatus = (err_code) ? *err_code : 0;
833 err_code = (const uint32_t *)find_SPropValue_data(&aRow, PR_RTF_COMPRESSED_ERROR);
834 RtfStatus = (err_code) ? *err_code : 0;
836 err_code = (const uint32_t *)find_SPropValue_data(&aRow, PR_BODY_HTML_ERROR);
837 HtmlStatus = (err_code) ? *err_code : 0;
839 /* Step 3. Determine the body format (9 possible cases) */
842 if ((PlainStatus == MAPI_E_NOT_FOUND) && (RtfStatus == MAPI_E_NOT_FOUND) &&
843 (HtmlStatus == MAPI_E_NOT_FOUND)) {
845 OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, 0);
849 if (((PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY) || (PlainStatus == 0)) &&
850 (RtfStatus == MAPI_E_NOT_FOUND) && (HtmlStatus == MAPI_E_NOT_FOUND)) {
851 *format = olEditorText;
852 return MAPI_E_SUCCESS;
856 if ((PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
857 (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
858 (HtmlStatus == MAPI_E_NOT_FOUND)) {
859 *format = olEditorRTF;
860 return MAPI_E_SUCCESS;
864 if ((PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
865 (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
866 (HtmlStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
868 *format = olEditorRTF;
869 return MAPI_E_SUCCESS;
873 if ((PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
874 (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
875 (HtmlStatus == MAPI_E_NOT_ENOUGH_MEMORY) &&
877 *format = olEditorHTML;
878 return MAPI_E_SUCCESS;
882 if (((RtfStatus == 0) || (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
883 ((HtmlStatus == 0) || (HtmlStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
885 *format = olEditorRTF;
886 return MAPI_E_SUCCESS;
890 if (((RtfStatus == 0) || (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
891 ((HtmlStatus == 0) || (HtmlStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
893 *format = olEditorHTML;
894 return MAPI_E_SUCCESS;
898 if (((PlainStatus == 0) || (PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
899 ((RtfStatus == 0) || (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
901 *format = olEditorRTF;
902 return MAPI_E_SUCCESS;
906 if (((PlainStatus == 0) || (PlainStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
907 ((RtfStatus == 0) || (RtfStatus == MAPI_E_NOT_ENOUGH_MEMORY)) &&
909 *format = olEditorText;
910 return MAPI_E_SUCCESS;
913 OPENCHANGE_RETVAL_ERR(MAPI_E_NOT_FOUND, 0);