2 OpenChange MAPI implementation.
4 Copyright (C) Julien Kerihuel 2007-2008.
5 Copyright (C) Brad Hards 2008.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "libmapi/libmapi.h"
22 #include "libmapi/mapi_nameid.h"
23 #include "libmapi/libmapi_private.h"
29 \brief Properties and named properties operations.
34 \details Returns values of one or more properties for an object
36 The function takes a pointer on the object obj, a MAPITAGS array
37 specified in mapitags, and the count of properties. The function
38 returns associated values within the SPropValue values pointer.
40 The array of MAPI property tags can be filled with both known and
43 \param obj the object to get properties on
44 \param flags Flags for behaviour; can be bit-OR of MAPI_UNICODE and
45 MAPI_PROPS_SKIP_NAMEDID_CHECK constants
46 \param SPropTagArray an array of MAPI property tags
47 \param lpProps the result of the query
48 \param PropCount the count of property tags
50 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
52 \note Developers may also call GetLastError() to retrieve the last
53 MAPI error code. Possible MAPI error codes are:
54 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
55 - MAPI_E_INVALID_PARAMETER: obj or SPropTagArray are null, or the
56 session context could not be obtained
57 - MAPI_E_CALL_FAILED: A network problem was encountered during the
60 \sa SetProps, GetPropList, GetPropsAll, DeleteProps, GetLastError
62 _PUBLIC_ enum MAPISTATUS GetProps(mapi_object_t *obj,
64 struct SPropTagArray *SPropTagArray,
65 struct SPropValue **lpProps,
68 struct mapi_context *mapi_ctx;
69 struct mapi_request *mapi_request;
70 struct mapi_response *mapi_response;
71 struct EcDoRpc_MAPI_REQ *mapi_req;
72 struct GetProps_req request;
73 struct mapi_session *session;
74 struct mapi_nameid *nameid;
75 struct SPropTagArray properties;
76 struct SPropTagArray *SPropTagArray2 = NULL;
78 enum MAPISTATUS retval;
79 enum MAPISTATUS mapistatus;
86 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
87 OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
89 session = mapi_object_get_session(obj);
90 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
92 mapi_ctx = session->mapi_ctx;
93 OPENCHANGE_RETVAL_IF(!mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
95 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
98 mem_ctx = talloc_named(NULL, 0, "GetProps");
100 /* Named property mapping */
101 nameid = mapi_nameid_new(mem_ctx);
102 if (!(flags & MAPI_PROPS_SKIP_NAMEDID_CHECK)) {
103 retval = mapi_nameid_lookup_SPropTagArray(nameid, SPropTagArray);
104 if (retval == MAPI_E_SUCCESS) {
106 SPropTagArray2 = talloc_zero(mem_ctx, struct SPropTagArray);
107 retval = GetIDsFromNames(obj, nameid->count, nameid->nameid, 0, &SPropTagArray2);
108 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
109 mapi_nameid_map_SPropTagArray(nameid, SPropTagArray, SPropTagArray2);
110 MAPIFreeBuffer(SPropTagArray2);
120 /* Fill the GetProps operation */
121 request.PropertySizeLimit = 0x0;
122 size += sizeof (uint16_t);
123 request.WantUnicode = (flags & MAPI_UNICODE) != 0 ? true : 0x0;
124 size += sizeof (uint16_t);
125 request.prop_count = (uint16_t) SPropTagArray->cValues;
126 size += sizeof (uint16_t);
127 properties.cValues = SPropTagArray->cValues;
128 properties.aulPropTag = talloc_memdup(mem_ctx, SPropTagArray->aulPropTag, SPropTagArray->cValues * sizeof(enum MAPITAGS));
129 request.properties = properties.aulPropTag;
130 size += request.prop_count * sizeof(uint32_t);
132 /* Fill the MAPI_REQ request */
133 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
134 mapi_req->opnum = op_MAPI_GetProps;
135 mapi_req->logon_id = logon_id;
136 mapi_req->handle_idx = 0;
137 mapi_req->u.mapi_GetProps = request;
140 /* Fill the mapi_request structure */
141 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
142 mapi_request->mapi_len = size + sizeof (uint32_t);
143 mapi_request->length = size;
144 mapi_request->mapi_req = mapi_req;
145 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
146 mapi_request->handles[0] = mapi_object_get_handle(obj);
148 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
149 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
150 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
151 retval = mapi_response->mapi_repl->error_code;
152 OPENCHANGE_RETVAL_IF((retval && retval != MAPI_W_ERRORS_RETURNED), retval, mem_ctx);
154 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
156 /* Read the SPropValue array from data blob.
157 fixme: replace the memory context by the object one.
160 mapi_nameid_unmap_SPropTagArray(nameid, SPropTagArray);
164 mapistatus = emsmdb_get_SPropValue((TALLOC_CTX *)session,
166 &mapi_response->mapi_repl->u.mapi_GetProps.prop_data,
167 &properties, lpProps, PropCount,
168 mapi_response->mapi_repl->u.mapi_GetProps.layout);
169 OPENCHANGE_RETVAL_IF(!mapistatus && (retval == MAPI_W_ERRORS_RETURNED), retval, mem_ctx);
171 talloc_free(mapi_response);
172 talloc_free(mem_ctx);
174 return MAPI_E_SUCCESS;
179 \details Set one or more properties on a given object
181 This function sets one or more properties on a specified object.
183 \param obj the object to set properties on
184 \param flags Flags for behaviour; can be MAPI_PROPS_SKIP_NAMEDID_CHECK
185 \param lpProps the list of properties to set
186 \param PropCount the number of properties
188 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
190 \note Developers may also call GetLastError() to retrieve the last
191 MAPI error code. Possible MAPI error codes are:
192 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
193 - MAPI_E_CALL_FAILED: A network problem was encountered during the
196 \sa GetProps, GetPropList, GetPropsAll, DeleteProps, GetLastError
198 _PUBLIC_ enum MAPISTATUS SetProps(mapi_object_t *obj,
200 struct SPropValue *lpProps,
201 unsigned long PropCount)
204 struct mapi_request *mapi_request;
205 struct mapi_response *mapi_response;
206 struct EcDoRpc_MAPI_REQ *mapi_req;
207 struct SetProps_req request;
208 struct mapi_session *session;
209 struct mapi_nameid *nameid;
210 struct SPropTagArray *SPropTagArray = NULL;
212 enum MAPISTATUS retval;
215 struct mapi_SPropValue *mapi_props;
220 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
222 session = mapi_object_get_session(obj);
223 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
225 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
228 mem_ctx = talloc_named(NULL, 0, "SetProps");
231 /* Named property mapping */
232 nameid = mapi_nameid_new(mem_ctx);
233 if (!(flags & MAPI_PROPS_SKIP_NAMEDID_CHECK)) {
234 retval = mapi_nameid_lookup_SPropValue(nameid, lpProps, PropCount);
235 if (retval == MAPI_E_SUCCESS) {
237 SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
238 retval = GetIDsFromNames(obj, nameid->count, nameid->nameid, 0, &SPropTagArray);
239 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
240 mapi_nameid_map_SPropValue(nameid, lpProps, PropCount, SPropTagArray);
241 MAPIFreeBuffer(SPropTagArray);
246 /* build the array */
247 request.values.lpProps = talloc_array(mem_ctx, struct mapi_SPropValue, PropCount);
248 mapi_props = request.values.lpProps;
249 for (i = 0; i < PropCount; i++) {
250 size += cast_mapi_SPropValue((TALLOC_CTX *)request.values.lpProps, &mapi_props[i], &lpProps[i]);
251 size += sizeof(uint32_t);
254 request.values.cValues = PropCount;
255 size += sizeof(uint16_t);
257 /* add the size of the subcontext that will be added on ndr layer */
258 size += sizeof(uint16_t);
260 /* Fill the MAPI_REQ request */
261 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
262 mapi_req->opnum = op_MAPI_SetProps;
263 mapi_req->logon_id = logon_id;
264 mapi_req->handle_idx = 0;
265 mapi_req->u.mapi_SetProps = request;
268 /* Fill the mapi_request structure */
269 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
270 mapi_request->mapi_len = size + sizeof (uint32_t);
271 mapi_request->length = size;
272 mapi_request->mapi_req = mapi_req;
273 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
274 mapi_request->handles[0] = mapi_object_get_handle(obj);
276 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
277 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
278 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
279 retval = mapi_response->mapi_repl->error_code;
280 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
282 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
285 mapi_nameid_unmap_SPropValue(nameid, lpProps, PropCount);
289 talloc_free(mapi_response);
290 talloc_free(mem_ctx);
292 return MAPI_E_SUCCESS;
297 \details Makes permanent any changes made to an attachment since the
300 \param obj_parent the parent of the object to save changes for
301 \param obj_child the object to save changes for
302 \param flags the access flags to set on the saved object
309 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
311 \note Developers may also call GetLastError() to retrieve the last
312 MAPI error code. Possible MAPI error codes are:
313 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
314 - MAPI_E_CALL_FAILED: A network problem was encountered during the
317 \sa SetProps, ModifyRecipients, GetLastError
319 _PUBLIC_ enum MAPISTATUS SaveChangesAttachment(mapi_object_t *obj_parent,
320 mapi_object_t *obj_child,
321 enum SaveFlags flags)
323 struct mapi_request *mapi_request;
324 struct mapi_response *mapi_response;
325 struct EcDoRpc_MAPI_REQ *mapi_req;
326 struct SaveChangesAttachment_req request;
327 struct mapi_session *session[2];
329 enum MAPISTATUS retval;
335 OPENCHANGE_RETVAL_IF(!obj_parent, MAPI_E_INVALID_PARAMETER, NULL);
336 OPENCHANGE_RETVAL_IF(!obj_child, MAPI_E_INVALID_PARAMETER, NULL);
337 OPENCHANGE_RETVAL_IF((flags != 0x9) && (flags != 0xA) && (flags != 0xC),
338 MAPI_E_INVALID_PARAMETER, NULL);
340 session[0] = mapi_object_get_session(obj_parent);
341 session[1] = mapi_object_get_session(obj_child);
342 OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
343 OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
344 OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
346 if ((retval = mapi_object_get_logon_id(obj_parent, &logon_id)) != MAPI_E_SUCCESS)
349 mem_ctx = talloc_named(NULL, 0, "SaveChangesAttachment");
352 /* Fill the SaveChangesAttachment operation */
353 request.handle_idx = 0x0;
354 request.SaveFlags = flags;
355 size += sizeof(uint8_t) + sizeof(uint8_t);
357 /* Fill the MAPI_REQ request */
358 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
359 mapi_req->opnum = op_MAPI_SaveChangesAttachment;
360 mapi_req->logon_id = logon_id;
361 mapi_req->handle_idx = 0;
362 mapi_req->u.mapi_SaveChangesAttachment = request;
365 /* Fill the mapi_request structure */
366 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
367 mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
368 mapi_request->length = size;
369 mapi_request->mapi_req = mapi_req;
370 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
371 mapi_request->handles[0] = mapi_object_get_handle(obj_child);
372 mapi_request->handles[1] = mapi_object_get_handle(obj_parent);
374 status = emsmdb_transaction_wrapper(session[0], mem_ctx, mapi_request, &mapi_response);
375 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
376 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
377 retval = mapi_response->mapi_repl->error_code;
378 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
380 OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
382 talloc_free(mapi_response);
383 talloc_free(mem_ctx);
385 return MAPI_E_SUCCESS;
390 \details Retrieve all the properties associated with a given object
392 \param obj the object to retrieve properties for
393 \param proptags the resulting list of properties associated with
396 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
398 \note Developers may also call GetLastError() to retrieve the last
399 MAPI error code. Possible MAPI error codes are:
400 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
401 - MAPI_E_CALL_FAILED: A network problem was encountered during the
404 The developer MUST provide an allocated SPropTagArray structure
407 \sa GetProps, GetPropsAll, GetLastError
409 _PUBLIC_ enum MAPISTATUS GetPropList(mapi_object_t *obj,
410 struct SPropTagArray *proptags)
412 struct mapi_request *mapi_request;
413 struct mapi_response *mapi_response;
414 struct EcDoRpc_MAPI_REQ *mapi_req;
415 struct mapi_session *session;
417 enum MAPISTATUS retval;
423 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
425 session = mapi_object_get_session(obj);
426 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
428 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
431 mem_ctx = talloc_named(NULL, 0, "GetPropList");
434 proptags->cValues = 0;
437 /* Fill the MAPI_REQ request */
438 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
439 mapi_req->opnum = op_MAPI_GetPropList;
440 mapi_req->logon_id = logon_id;
441 mapi_req->handle_idx = 0;
444 /* Fill the mapi_request structure */
445 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
446 mapi_request->mapi_len = size + sizeof (uint32_t) * 1;
447 mapi_request->length = size;
448 mapi_request->mapi_req = mapi_req;
449 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
450 mapi_request->handles[0] = mapi_object_get_handle(obj);
452 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
453 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
454 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
455 retval = mapi_response->mapi_repl->error_code;
456 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
458 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
460 /* Get the repsonse */
461 proptags->cValues = mapi_response->mapi_repl->u.mapi_GetPropList.count;
462 if (proptags->cValues) {
463 size = proptags->cValues * sizeof(enum MAPITAGS);
464 proptags->aulPropTag = talloc_array((TALLOC_CTX *) proptags, enum MAPITAGS, proptags->cValues);
465 memcpy((void*)proptags->aulPropTag,
466 (void*)mapi_response->mapi_repl->u.mapi_GetPropList.tags,
470 talloc_free(mapi_response);
471 talloc_free(mem_ctx);
473 return MAPI_E_SUCCESS;
478 \details Retrieve all properties and values associated with an
481 This function returns all the properties and and associated values
484 \param obj the object to get the properties for
485 \param flags Flags for behaviour; can be a MAPI_UNICODE constant
486 \param properties the properties / values for the object
488 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
490 \note Developers may also call GetLastError() to retrieve the last
491 MAPI error code. Possible MAPI error codes are:
492 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
493 - MAPI_E_CALL_FAILED: A network problem was encountered during the
496 \sa GetProps, GetPropList, GetLastError
498 _PUBLIC_ enum MAPISTATUS GetPropsAll(mapi_object_t *obj,
500 struct mapi_SPropValue_array *properties)
503 struct mapi_request *mapi_request;
504 struct mapi_response *mapi_response;
505 struct EcDoRpc_MAPI_REQ *mapi_req;
506 struct GetPropsAll_req request;
507 struct GetPropsAll_repl *reply;
508 struct mapi_session *session;
510 enum MAPISTATUS retval;
515 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
517 session = mapi_object_get_session(obj);
518 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
520 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
523 mem_ctx = talloc_named(NULL, 0, "GetPropsAll");
526 /* Fill the GetPropsAll operation */
527 request.PropertySizeLimit = 0;
528 size += sizeof (uint16_t);
529 request.WantUnicode = (flags & MAPI_UNICODE) != 0 ? true : 0x0;
530 size += sizeof (uint16_t);
532 /* Fill the MAPI_REQ request */
533 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
534 mapi_req->opnum = op_MAPI_GetPropsAll;
535 mapi_req->logon_id = logon_id;
536 mapi_req->handle_idx = 0;
537 mapi_req->u.mapi_GetPropsAll = request;
540 /* Fill the mapi_request structure */
541 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
542 mapi_request->mapi_len = size + sizeof (uint32_t);
543 mapi_request->length = size;
544 mapi_request->mapi_req = mapi_req;
545 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
546 mapi_request->handles[0] = mapi_object_get_handle(obj);
548 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
549 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
550 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
551 retval = mapi_response->mapi_repl->error_code;
552 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
554 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
556 reply = &mapi_response->mapi_repl->u.mapi_GetPropsAll;
557 properties->cValues = reply->properties.cValues;
558 properties->lpProps = talloc_steal((TALLOC_CTX *)session, reply->properties.lpProps);
560 talloc_free(mapi_response);
561 talloc_free(mem_ctx);
562 return MAPI_E_SUCCESS;
567 \details Delete one or more properties from an object
569 \param obj the object to remove properties from
570 \param proptags the properties to remove from the given object
572 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
574 \note Developers may also call GetLastError() to retrieve the last
575 MAPI error code. Possible MAPI error codes are:
576 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
577 - MAPI_E_CALL_FAILED: A network problem was encountered during the
580 \sa SetProps, GetLastError
582 _PUBLIC_ enum MAPISTATUS DeleteProps(mapi_object_t *obj,
583 struct SPropTagArray *proptags)
586 struct mapi_request *mapi_request;
587 struct mapi_response *mapi_response;
588 struct EcDoRpc_MAPI_REQ *mapi_req;
589 struct DeleteProps_req request;
590 struct mapi_session *session;
592 enum MAPISTATUS retval;
597 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
598 OPENCHANGE_RETVAL_IF(!proptags, MAPI_E_INVALID_PARAMETER, NULL);
600 session = mapi_object_get_session(obj);
601 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
603 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
606 mem_ctx = talloc_named(NULL, 0, "DeleteProps");
609 /* Fill the DeleteProps operation */
610 request.count = proptags->cValues;
611 size += sizeof(uint16_t);
612 request.tags = proptags->aulPropTag;
613 size += proptags->cValues * sizeof(enum MAPITAGS);
615 /* Fill the MAPI_REQ request */
616 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
617 mapi_req->opnum = op_MAPI_DeleteProps;
618 mapi_req->logon_id = logon_id;
619 mapi_req->handle_idx = 0;
620 mapi_req->u.mapi_DeleteProps = request;
623 /* Fill the mapi_request structure */
624 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
625 mapi_request->mapi_len = size + sizeof (uint32_t);
626 mapi_request->length = size;
627 mapi_request->mapi_req = mapi_req;
628 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
629 mapi_request->handles[0] = mapi_object_get_handle(obj);
631 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
632 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
633 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
634 retval = mapi_response->mapi_repl->error_code;
635 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
637 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
639 talloc_free(mapi_response);
640 talloc_free(mem_ctx);
642 return MAPI_E_SUCCESS;
646 \details Set one or more properties on a given object without
647 invoking replication.
649 This function sets one or more properties on a specified object. It
650 is the same as SetProps, except if the object is a folder, where
651 this function does not result in folder properties being replicated.
653 \param obj the object to set properties on
654 \param flags Flags for behaviour; can be MAPI_PROPS_SKIP_NAMEDID_CHECK
655 \param lpProps the list of properties to set
656 \param PropCount the number of properties
658 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
660 \note Developers may also call GetLastError() to retrieve the last
661 MAPI error code. Possible MAPI error codes are:
662 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
663 - MAPI_E_INVALID_PARAMETER: obj is not valid
664 - MAPI_E_CALL_FAILED: A network problem was encountered during the
667 \sa SetProps, DeletePropertiesNoReplicate
669 _PUBLIC_ enum MAPISTATUS SetPropertiesNoReplicate(mapi_object_t *obj,
671 struct SPropValue *lpProps,
672 unsigned long PropCount)
675 struct mapi_request *mapi_request;
676 struct mapi_response *mapi_response;
677 struct EcDoRpc_MAPI_REQ *mapi_req;
678 struct SetPropertiesNoReplicate_req request;
679 struct mapi_session *session;
680 struct mapi_nameid *nameid;
681 struct SPropTagArray *SPropTagArray = NULL;
683 enum MAPISTATUS retval;
686 struct mapi_SPropValue *mapi_props;
691 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
693 session = mapi_object_get_session(obj);
694 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
696 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
699 mem_ctx = talloc_named(NULL, 0, "SetPropertiesNoReplicate");
702 /* Named property mapping */
703 nameid = mapi_nameid_new(mem_ctx);
704 if (!(flags & MAPI_PROPS_SKIP_NAMEDID_CHECK)) {
705 retval = mapi_nameid_lookup_SPropValue(nameid, lpProps, PropCount);
706 if (retval == MAPI_E_SUCCESS) {
708 SPropTagArray = talloc_zero(mem_ctx, struct SPropTagArray);
709 retval = GetIDsFromNames(obj, nameid->count, nameid->nameid, 0, &SPropTagArray);
710 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
711 mapi_nameid_map_SPropValue(nameid, lpProps, PropCount, SPropTagArray);
712 MAPIFreeBuffer(SPropTagArray);
717 /* build the array */
718 request.values.lpProps = talloc_array(mem_ctx, struct mapi_SPropValue, PropCount);
719 mapi_props = request.values.lpProps;
720 for (i = 0; i < PropCount; i++) {
721 size += cast_mapi_SPropValue((TALLOC_CTX *)request.values.lpProps, &mapi_props[i], &lpProps[i]);
722 size += sizeof(uint32_t);
725 request.values.cValues = PropCount;
726 size += sizeof(uint16_t);
728 /* add the size of the subcontext that will be added on ndr layer */
729 size += sizeof(uint16_t);
731 /* Fill the MAPI_REQ request */
732 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
733 mapi_req->opnum = op_MAPI_SetPropertiesNoReplicate;
734 mapi_req->logon_id = logon_id;
735 mapi_req->handle_idx = 0;
736 mapi_req->u.mapi_SetPropertiesNoReplicate = request;
739 /* Fill the mapi_request structure */
740 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
741 mapi_request->mapi_len = size + sizeof (uint32_t);
742 mapi_request->length = size;
743 mapi_request->mapi_req = mapi_req;
744 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
745 mapi_request->handles[0] = mapi_object_get_handle(obj);
747 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
748 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
749 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
750 retval = mapi_response->mapi_repl->error_code;
751 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
754 mapi_nameid_unmap_SPropValue(nameid, lpProps, PropCount);
758 talloc_free(mapi_response);
759 talloc_free(mem_ctx);
761 return MAPI_E_SUCCESS;
766 \details Deletes property values from an object without invoking
769 \param obj the object to remove properties from
770 \param proptags the properties to remove from the given object
772 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
774 \note Developers may also call GetLastError() to retrieve the last
775 MAPI error code. Possible MAPI error codes are:
776 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
777 - MAPI_E_CALL_FAILED: A network problem was encountered during the
782 _PUBLIC_ enum MAPISTATUS DeletePropertiesNoReplicate(mapi_object_t *obj,
783 struct SPropTagArray *proptags)
786 struct mapi_request *mapi_request;
787 struct mapi_response *mapi_response;
788 struct EcDoRpc_MAPI_REQ *mapi_req;
789 struct DeletePropertiesNoReplicate_req request;
790 struct mapi_session *session;
792 enum MAPISTATUS retval;
797 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
798 OPENCHANGE_RETVAL_IF(!proptags, MAPI_E_INVALID_PARAMETER, NULL);
800 session = mapi_object_get_session(obj);
801 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
803 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
806 mem_ctx = talloc_named(NULL, 0, "DeletePropertiesNoReplicate");
809 /* Fill the DeletePropertiesNoReplicate operation */
810 request.PropertyTags.cValues = proptags->cValues;
811 size += sizeof (uint16_t);
812 request.PropertyTags.aulPropTag = proptags->aulPropTag;
813 size += proptags->cValues * sizeof (enum MAPITAGS);
815 /* Fill the MAPI_REQ request */
816 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
817 mapi_req->opnum = op_MAPI_DeletePropertiesNoReplicate;
818 mapi_req->logon_id = logon_id;
819 mapi_req->handle_idx = 0;
820 mapi_req->u.mapi_DeletePropertiesNoReplicate = request;
823 /* Fill the mapi_request structure */
824 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
825 mapi_request->mapi_len = size + sizeof (uint32_t);
826 mapi_request->length = size;
827 mapi_request->mapi_req = mapi_req;
828 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
829 mapi_request->handles[0] = mapi_object_get_handle(obj);
831 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
832 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
833 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
834 retval = mapi_response->mapi_repl->error_code;
835 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
837 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
839 talloc_free(mapi_response);
840 talloc_free(mem_ctx);
842 return MAPI_E_SUCCESS;
847 \details Provides the property names that correspond to one
848 or more property identifiers.
850 \param obj the object we are retrieving the names from
851 \param ulPropTag the mapped property tag
852 \param count count of property names pointed to by the nameid
853 parameter returned by the server
854 \param nameid pointer to a pointer to property names returned by
857 ulPropTag must be a property with type set to PT_NULL
859 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
861 \note Developers may also call GetLastError() to retrieve the last
862 MAPI error code. Possible MAPI error codes are:
863 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
864 - MAPI_E_CALL_FAILED: A network problem was encountered during the
867 \sa GetIDsFromNames, QueryNamesFromIDs
869 _PUBLIC_ enum MAPISTATUS GetNamesFromIDs(mapi_object_t *obj,
870 enum MAPITAGS ulPropTag,
872 struct MAPINAMEID **nameid)
874 struct mapi_request *mapi_request;
875 struct mapi_response *mapi_response;
876 struct EcDoRpc_MAPI_REQ *mapi_req;
877 struct GetNamesFromIDs_req request;
878 struct GetNamesFromIDs_repl *reply;
879 struct mapi_session *session;
881 enum MAPISTATUS retval;
887 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
889 session = mapi_object_get_session(obj);
890 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
892 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
896 mem_ctx = talloc_named(NULL, 0, "GetNamesFromIDs");
899 /* Fill the GetNamesFromIDs operation */
900 request.PropertyIdCount = 0x1;
901 size += sizeof (uint16_t);
902 request.PropertyIds = talloc_array(mem_ctx, uint16_t, request.PropertyIdCount);
903 request.PropertyIds[0] = ((ulPropTag & 0xFFFF0000) >> 16);
904 size += request.PropertyIdCount * sizeof (uint16_t);
906 /* Fill the MAPI_REQ request */
907 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
908 mapi_req->opnum = op_MAPI_GetNamesFromIDs;
909 mapi_req->logon_id = logon_id;
910 mapi_req->handle_idx = 0;
911 mapi_req->u.mapi_GetNamesFromIDs = request;
914 /* Fill the mapi_request structure */
915 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
916 mapi_request->mapi_len = size + sizeof (uint32_t);
917 mapi_request->length = size;
918 mapi_request->mapi_req = mapi_req;
919 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
920 mapi_request->handles[0] = mapi_object_get_handle(obj);
922 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
923 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
924 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
925 retval = mapi_response->mapi_repl->error_code;
926 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
928 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
931 reply = &mapi_response->mapi_repl->u.mapi_GetNamesFromIDs;
932 *count = reply->count;
934 /* Fill MAPINAMEID struct */
935 *nameid = talloc_steal((TALLOC_CTX *)session, reply->nameid);
937 talloc_free(mapi_response);
938 talloc_free(mem_ctx);
940 return MAPI_E_SUCCESS;
945 \details Provides the property identifiers that correspond to one
946 or more property names.
948 \param obj the object we are retrieving the identifiers from
949 \param count count of property names pointed to by the nameid
951 \param nameid pointer to an array of property names
952 \param ulFlags indicates how the property identifiers should be
954 \param proptags pointer to a pointer to an array of property tags
955 containing existing or newly assigned property
956 identifiers. Property types in this array are set to PT_NULL.
958 ulFlags can be set to:
959 - 0 retrieves named properties from the server
960 - MAPI_CREATE create the named properties if they don't exist on
963 \note count and nameid parameter can automatically be built
964 using the mapi_nameid API.
966 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
968 \note Developers may also call GetLastError() to retrieve the last
969 MAPI error code. Possible MAPI error codes are:
970 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
971 - MAPI_E_CALL_FAILED: A network problem was encountered during the
974 \sa GetNamesFromIds, QueryNamesFromIDs, mapi_nameid_new
976 _PUBLIC_ enum MAPISTATUS GetIDsFromNames(mapi_object_t *obj,
978 struct MAPINAMEID *nameid,
980 struct SPropTagArray **proptags)
982 struct mapi_request *mapi_request;
983 struct mapi_response *mapi_response;
984 struct EcDoRpc_MAPI_REQ *mapi_req;
985 struct GetIDsFromNames_req request;
986 struct mapi_session *session;
988 enum MAPISTATUS retval;
995 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
996 OPENCHANGE_RETVAL_IF(!count, MAPI_E_INVALID_PARAMETER, NULL);
997 OPENCHANGE_RETVAL_IF(!nameid, MAPI_E_INVALID_PARAMETER, NULL);
998 OPENCHANGE_RETVAL_IF(!proptags, MAPI_E_INVALID_PARAMETER, NULL);
999 OPENCHANGE_RETVAL_IF(!proptags[0], MAPI_E_INVALID_PARAMETER, NULL);
1001 session = mapi_object_get_session(obj);
1002 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
1004 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
1007 /* Initialization */
1008 mem_ctx = talloc_named(NULL, 0, "GetIDsFromNames");
1011 /* Fill the GetIDsFromNames operation */
1012 request.ulFlags = ulFlags;
1013 request.count = count;
1014 size += sizeof (uint8_t) + sizeof (uint16_t);
1016 request.nameid = nameid;
1017 for (i = 0; i < count; i++) {
1018 size += sizeof (uint8_t) + sizeof (request.nameid[i].lpguid);
1019 switch (request.nameid[i].ulKind) {
1021 size += sizeof (request.nameid[i].kind.lid);
1024 size += get_utf8_utf16_conv_length(request.nameid[i].kind.lpwstr.Name);
1025 size += sizeof (uint8_t);
1032 /* Fill the MAPI_REQ request */
1033 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
1034 mapi_req->opnum = op_MAPI_GetIDsFromNames;
1035 mapi_req->logon_id = logon_id;
1036 mapi_req->handle_idx = 0;
1037 mapi_req->u.mapi_GetIDsFromNames = request;
1040 /* Fill the mapi_request structure */
1041 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
1042 mapi_request->mapi_len = size + sizeof (uint32_t);
1043 mapi_request->length = size;
1044 mapi_request->mapi_req = mapi_req;
1045 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
1046 mapi_request->handles[0] = mapi_object_get_handle(obj);
1048 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
1049 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
1050 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
1051 retval = mapi_response->mapi_repl->error_code;
1052 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
1054 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
1056 /* Fill the SPropTagArray */
1057 proptags[0] = talloc_zero(NULL, struct SPropTagArray);
1058 proptags[0]->cValues = mapi_response->mapi_repl->u.mapi_GetIDsFromNames.count;
1059 proptags[0]->aulPropTag = (enum MAPITAGS *) talloc_array((TALLOC_CTX *)proptags[0], uint32_t, proptags[0]->cValues);
1060 for (i = 0; i < proptags[0]->cValues; i++) {
1061 proptags[0]->aulPropTag[i] = (mapi_response->mapi_repl->u.mapi_GetIDsFromNames.propID[i] << 16) | PT_UNSPECIFIED;
1064 talloc_free(mapi_response);
1065 talloc_free(mem_ctx);
1067 return MAPI_E_SUCCESS;
1072 \details Provides the property names that correspond to one or more
1073 property identifiers.
1075 \param obj the object to obtain the properties for
1076 \param queryFlags A set of flags that can restrict the type of properties
1077 \param guid a pointer to the GUID for the property set to fetch (null for all
1079 \param count count of property names pointed to by the nameid and propID
1080 parameters returned by the server
1081 \param propID pointer to an array of property IDs returned by the server
1082 \param nameid pointer to an array of property names returned by
1085 \note queryFlags can be NoStrings (0x1) or NoIds (0x2), neither or both.
1086 NoStrings will produce only ID properties, NoIds will produce only named
1087 properties, and both will result in no output.
1089 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
1093 _PUBLIC_ enum MAPISTATUS QueryNamedProperties(mapi_object_t *obj,
1098 struct MAPINAMEID **nameid)
1100 struct mapi_request *mapi_request;
1101 struct mapi_response *mapi_response;
1102 struct EcDoRpc_MAPI_REQ *mapi_req;
1103 struct QueryNamedProperties_req request;
1104 struct QueryNamedProperties_repl *reply;
1105 struct mapi_session *session;
1107 enum MAPISTATUS retval;
1109 TALLOC_CTX *mem_ctx;
1113 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
1115 session = mapi_object_get_session(obj);
1116 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
1118 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
1121 /* Initialization */
1122 mem_ctx = talloc_named(NULL, 0, "QueryNamesFromIDs");
1125 /* Fill the QueryNamedProperties operation */
1126 request.QueryFlags = queryFlags;
1127 size += sizeof (uint8_t);
1130 request.HasGuid = 0x1; /* true */
1131 size += sizeof (uint8_t);
1132 request.PropertyGuid.guid = *guid;
1133 size += sizeof (struct GUID);
1135 request.HasGuid = 0x0; /* false */
1136 size += sizeof (uint8_t);
1139 /* Fill the MAPI_REQ request */
1140 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
1141 mapi_req->opnum = op_MAPI_QueryNamedProperties;
1142 mapi_req->logon_id = logon_id;
1143 mapi_req->handle_idx = 0;
1144 mapi_req->u.mapi_QueryNamedProperties = request;
1147 /* Fill the mapi_request structure */
1148 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
1149 mapi_request->mapi_len = size + sizeof (uint32_t);
1150 mapi_request->length = size;
1151 mapi_request->mapi_req = mapi_req;
1152 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
1153 mapi_request->handles[0] = mapi_object_get_handle(obj);
1155 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
1156 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
1157 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
1158 retval = mapi_response->mapi_repl->error_code;
1159 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
1161 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
1163 /* Fill [out] parameters */
1164 reply = &mapi_response->mapi_repl->u.mapi_QueryNamedProperties;
1166 *count = reply->IdCount;
1167 *propID = talloc_steal((TALLOC_CTX *)session, reply->PropertyIds);
1168 *nameid = talloc_steal((TALLOC_CTX *)session, reply->PropertyNames);
1170 talloc_free(mapi_response);
1171 talloc_free(mem_ctx);
1173 return MAPI_E_SUCCESS;
1178 \details Copy properties from one object to another
1180 This function copies (or moves) specified properties from
1181 one object to another.
1183 \param obj_src the object to copy properties from
1184 \param obj_dst the object to set properties on
1185 \param copyFlags flags to determine whether to copy or
1186 move, and whether to overwrite existing properties.
1187 \param tags the list of properties to copy
1188 \param problemCount (return value) number of entries in the problems array
1189 \param problems (return value) array of problemCount entries.
1191 The caller is responsible for freeing the \b problems array
1192 using MAPIFreeBuffer(). If the \b problemCount pointer is NULL,
1193 then the problems array will not be returned.
1195 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
1197 \note Developers may also call GetLastError() to retrieve the last
1198 MAPI error code. Possible MAPI error codes are:
1199 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
1200 - MAPI_E_CALL_FAILED: A network problem was encountered during the
1203 \sa GetProps, SetProps, DeleteProps, CopyTo, GetLastError
1205 _PUBLIC_ enum MAPISTATUS CopyProps(mapi_object_t *obj_src,
1206 mapi_object_t *obj_dst,
1207 struct SPropTagArray *tags,
1209 uint16_t *problemCount,
1210 struct PropertyProblem **problems)
1213 TALLOC_CTX *mem_ctx;
1214 struct mapi_request *mapi_request;
1215 struct mapi_response *mapi_response;
1216 struct EcDoRpc_MAPI_REQ *mapi_req;
1217 struct CopyProperties_req request;
1218 struct mapi_session *session[2];
1220 enum MAPISTATUS retval;
1226 OPENCHANGE_RETVAL_IF(!obj_src, MAPI_E_INVALID_PARAMETER, NULL);
1227 OPENCHANGE_RETVAL_IF(!obj_dst, MAPI_E_INVALID_PARAMETER, NULL);
1228 OPENCHANGE_RETVAL_IF(!tags, MAPI_E_INVALID_PARAMETER, NULL);
1230 session[0] = mapi_object_get_session(obj_src);
1231 session[1] = mapi_object_get_session(obj_dst);
1232 OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
1233 OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
1234 OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
1236 if ((retval = mapi_object_get_logon_id(obj_src, &logon_id)) != MAPI_E_SUCCESS)
1239 mem_ctx = talloc_named(NULL, 0, "CopyProps");
1242 /* Fill the CopyProperties operation */
1243 request.handle_idx = 0x1;
1244 size += sizeof(uint8_t);
1245 request.WantAsynchronous = 0x0;
1246 size += sizeof(uint8_t);
1247 request.CopyFlags = copyFlags;
1248 size += sizeof(uint8_t);
1249 request.PropertyTags.cValues = tags->cValues;
1250 size += sizeof(uint16_t);
1251 request.PropertyTags.aulPropTag = tags->aulPropTag;
1252 size += tags->cValues * sizeof(enum MAPITAGS);
1254 /* Fill the MAPI_REQ request */
1255 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
1256 mapi_req->opnum = op_MAPI_CopyProperties;
1257 mapi_req->logon_id = logon_id;
1258 mapi_req->handle_idx = 0;
1259 mapi_req->u.mapi_CopyProperties = request;
1260 size += 5; // sizeof( EcDoRpc_MAPI_REQ )
1262 /* Fill the mapi_request structure */
1263 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
1264 mapi_request->mapi_len = size + sizeof (uint32_t) *2;
1265 mapi_request->length = size;
1266 mapi_request->mapi_req = mapi_req;
1267 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
1268 mapi_request->handles[0] = mapi_object_get_handle(obj_src);
1269 mapi_request->handles[1] = mapi_object_get_handle(obj_dst);
1271 status = emsmdb_transaction_wrapper(session[0], mem_ctx, mapi_request, &mapi_response);
1272 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
1273 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
1274 retval = mapi_response->mapi_repl->error_code;
1275 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
1277 OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
1280 *problemCount = mapi_response->mapi_repl->u.mapi_CopyProperties.PropertyProblemCount;
1281 *problems = talloc_array((TALLOC_CTX *)session[0], struct PropertyProblem, *problemCount);
1282 for(i = 0; i < *problemCount; i++) {
1283 (*(problems[i])).index = mapi_response->mapi_repl->u.mapi_CopyProperties.PropertyProblem[i].index;
1284 (*(problems[i])).property_tag = mapi_response->mapi_repl->u.mapi_CopyProperties.PropertyProblem[i].property_tag;
1285 (*(problems[i])).error_code = mapi_response->mapi_repl->u.mapi_CopyProperties.PropertyProblem[i].error_code;
1289 talloc_free(mapi_response);
1290 talloc_free(mem_ctx);
1292 return MAPI_E_SUCCESS;
1296 \details Copy multiple properties from one object to another
1298 This function copies (or moves) properties from one object to
1299 another. Unlike CopyProperties, this function copies all properties
1300 except those identified.
1302 \param obj_src the object to copy properties from
1303 \param obj_dst the object to set properties on
1304 \param excludeTags the list of properties to \em not copy
1305 \param copyFlags flags to determine whether to copy or
1306 move, and whether to overwrite existing properties.
1307 \param problemCount (return value) number of entries in the problems array
1308 \param problems (return value) array of problemCount entries.
1310 The caller is responsible for freeing the \b problems array
1311 using MAPIFreeBuffer(). If the \b problemCount pointer is NULL,
1312 then the problems array will not be returned.
1314 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
1316 \note Developers may also call GetLastError() to retrieve the last
1317 MAPI error code. Possible MAPI error codes are:
1318 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
1319 - MAPI_E_CALL_FAILED: A network problem was encountered during the
1322 \sa GetProps, SetProps, DeleteProps, CopyProps
1324 _PUBLIC_ enum MAPISTATUS CopyTo(mapi_object_t *obj_src,
1325 mapi_object_t *obj_dst,
1326 struct SPropTagArray *excludeTags,
1328 uint16_t *problemCount,
1329 struct PropertyProblem **problems)
1332 TALLOC_CTX *mem_ctx;
1333 struct mapi_request *mapi_request;
1334 struct mapi_response *mapi_response;
1335 struct EcDoRpc_MAPI_REQ *mapi_req;
1336 struct CopyTo_req request;
1337 struct mapi_session *session[2];
1339 enum MAPISTATUS retval;
1345 OPENCHANGE_RETVAL_IF(!obj_src, MAPI_E_INVALID_PARAMETER, NULL);
1346 OPENCHANGE_RETVAL_IF(!obj_dst, MAPI_E_INVALID_PARAMETER, NULL);
1347 OPENCHANGE_RETVAL_IF(!excludeTags, MAPI_E_INVALID_PARAMETER, NULL);
1349 session[0] = mapi_object_get_session(obj_src);
1350 session[1] = mapi_object_get_session(obj_dst);
1351 OPENCHANGE_RETVAL_IF(!session[0], MAPI_E_INVALID_PARAMETER, NULL);
1352 OPENCHANGE_RETVAL_IF(!session[1], MAPI_E_INVALID_PARAMETER, NULL);
1353 OPENCHANGE_RETVAL_IF(session[0] != session[1], MAPI_E_INVALID_PARAMETER, NULL);
1355 if ((retval = mapi_object_get_logon_id(obj_src, &logon_id)) != MAPI_E_SUCCESS)
1358 mem_ctx = talloc_named(NULL, 0, "CopyProps");
1361 /* Fill the CopyProperties operation */
1362 request.handle_idx = 0x1;
1363 size += sizeof(uint8_t);
1364 request.WantAsynchronous = 0x0;
1365 size += sizeof(uint8_t);
1366 request.WantSubObjects = 0x1;
1367 size += sizeof(uint8_t);
1368 request.CopyFlags = copyFlags;
1369 size += sizeof(uint8_t);
1370 request.ExcludedTags.cValues = (uint16_t)excludeTags->cValues;
1371 size += sizeof(uint16_t);
1372 request.ExcludedTags.aulPropTag = excludeTags->aulPropTag;
1373 size += excludeTags->cValues * sizeof(enum MAPITAGS);
1375 /* Fill the MAPI_REQ request */
1376 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
1377 mapi_req->opnum = op_MAPI_CopyTo;
1378 mapi_req->logon_id = logon_id;
1379 mapi_req->handle_idx = 0;
1380 mapi_req->u.mapi_CopyTo = request;
1381 size += 5; // sizeof( EcDoRpc_MAPI_REQ )
1383 /* Fill the mapi_request structure */
1384 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
1385 mapi_request->mapi_len = size + sizeof (uint32_t) *2;
1386 mapi_request->length = size;
1387 mapi_request->mapi_req = mapi_req;
1388 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
1389 mapi_request->handles[0] = mapi_object_get_handle(obj_src);
1390 mapi_request->handles[1] = mapi_object_get_handle(obj_dst);
1392 status = emsmdb_transaction_wrapper(session[0], mem_ctx, mapi_request, &mapi_response);
1393 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
1394 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
1395 retval = mapi_response->mapi_repl->error_code;
1396 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
1398 OPENCHANGE_CHECK_NOTIFICATION(session[0], mapi_response);
1401 *problemCount = mapi_response->mapi_repl->u.mapi_CopyTo.PropertyProblemCount;
1402 *problems = talloc_array((TALLOC_CTX *)session[0], struct PropertyProblem, *problemCount);
1403 for(i=0; i < *problemCount; ++i) {
1404 (*(problems[i])).index = mapi_response->mapi_repl->u.mapi_CopyTo.PropertyProblem[i].index;
1405 (*(problems[i])).property_tag = mapi_response->mapi_repl->u.mapi_CopyTo.PropertyProblem[i].property_tag;
1406 (*(problems[i])).error_code = mapi_response->mapi_repl->u.mapi_CopyTo.PropertyProblem[i].error_code;
1410 talloc_free(mapi_response);
1411 talloc_free(mem_ctx);
1413 return MAPI_E_SUCCESS;