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 Incremental Change Synchronization operations
32 \details Reserves a range of IDs to be used by a local replica
34 \param obj_store pointer on the store MAPI object
35 \param IdCount ID range length to reserve
36 \param ReplGuid pointer to the GUID structure returned by the
38 \param GlobalCount byte array that specifies the first allocated
41 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
43 \note Developers may also call GetLastError() to retrieve the last
44 MAPI error code. Possible MAPI error codes are:
45 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
46 - MAPI_E_INVALID_PARAMETER: one of the function parameters is
48 - MAPI_E_CALL_FAILED: A network problem was encountered during the
51 _PUBLIC_ enum MAPISTATUS GetLocalReplicaIds(mapi_object_t *obj_store,
53 struct GUID *ReplGuid,
54 uint8_t GlobalCount[6])
56 struct mapi_request *mapi_request;
57 struct mapi_response *mapi_response;
58 struct EcDoRpc_MAPI_REQ *mapi_req;
59 struct GetLocalReplicaIds_req request;
60 struct GetLocalReplicaIds_repl *reply;
61 struct mapi_session *session;
63 enum MAPISTATUS retval;
69 OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
70 OPENCHANGE_RETVAL_IF(!ReplGuid, MAPI_E_INVALID_PARAMETER, NULL);
72 session = mapi_object_get_session(obj_store);
73 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
75 if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS)
78 mem_ctx = talloc_named(NULL, 0, "GetLocalReplicaIds");
81 /* Fill the GetLocalReplicaIds operation */
82 request.IdCount = IdCount;
83 size += sizeof (uint32_t);
85 /* Fill the MAPI_REQ structure */
86 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
87 mapi_req->opnum = op_MAPI_GetLocalReplicaIds;
88 mapi_req->logon_id = logon_id;
89 mapi_req->handle_idx = 0;
90 mapi_req->u.mapi_GetLocalReplicaIds = request;
93 /* Fill the mapi_request structure */
94 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
95 mapi_request->mapi_len = size + sizeof (uint32_t);
96 mapi_request->length = (uint16_t)size;
97 mapi_request->mapi_req = mapi_req;
98 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
99 mapi_request->handles[0] = mapi_object_get_handle(obj_store);
101 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
102 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
103 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
104 retval = mapi_response->mapi_repl->error_code;
105 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
107 OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
109 /* Retrieve output parameters */
110 reply = &mapi_response->mapi_repl->u.mapi_GetLocalReplicaIds;
111 *ReplGuid = reply->ReplGuid;
112 memcpy(GlobalCount, reply->GlobalCount, 6);
114 talloc_free(mapi_response);
115 talloc_free(mem_ctx);
117 return MAPI_E_SUCCESS;
121 \details Prepare a server for Fast Transfer receive
123 This function is used to configure a server for fast-transfer receive operation.
124 This could be the target server in a server->client->server copy, or for a
125 client->server upload.
127 \param obj the target object for the upload (folder, message or attachment)
128 \param sourceOperation the type of transfer (one of FastTransferDest_CopyTo,
129 FastTransferDest_CopyProperties,FastTransferDest_CopyMessages or
130 FastTransferDest_CopyFolder)
131 \param obj_destination_context the fast transfer context for future ROPs.
133 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
135 \note Developers may also call GetLastError() to retrieve the last
136 MAPI error code. Possible MAPI error codes are:
137 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
138 - MAPI_E_INVALID_PARAMETER: one of the function parameters is
140 - MAPI_E_CALL_FAILED: A network problem was encountered during the
143 _PUBLIC_ enum MAPISTATUS FXDestConfigure(mapi_object_t *obj,
144 enum FastTransferDestConfig_SourceOperation sourceOperation,
145 mapi_object_t *obj_destination_context)
147 struct mapi_request *mapi_request;
148 struct mapi_response *mapi_response;
149 struct EcDoRpc_MAPI_REQ *mapi_req;
150 struct FastTransferDestinationConfigure_req request;
151 struct mapi_session *session;
153 enum MAPISTATUS retval;
156 uint8_t logon_id = 0;
159 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
161 session = mapi_object_get_session(obj);
162 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
163 OPENCHANGE_RETVAL_IF(!obj_destination_context, MAPI_E_INVALID_PARAMETER, NULL);
165 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
168 mem_ctx = talloc_named(NULL, 0, "FXDestConfigure");
171 /* Fill the ConfigureDestination operation */
172 request.handle_idx = 0x01;
173 size += sizeof(uint8_t);
174 request.SourceOperation = sourceOperation;
175 size += sizeof(uint8_t);
176 request.CopyFlags = 0x00; /* we don't support move yet */
177 size += sizeof(uint8_t);
179 /* Fill the MAPI_REQ structure */
180 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
181 mapi_req->opnum = op_MAPI_FastTransferDestConfigure;
182 mapi_req->logon_id = logon_id;
183 mapi_req->handle_idx = 0;
184 mapi_req->u.mapi_FastTransferDestinationConfigure = request;
187 /* Fill the mapi_request structure */
188 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
189 mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
190 mapi_request->length = (uint16_t)size;
191 mapi_request->mapi_req = mapi_req;
192 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
193 mapi_request->handles[0] = mapi_object_get_handle(obj);
194 mapi_request->handles[1] = 0xFFFFFFFF;
196 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
197 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
198 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
199 retval = mapi_response->mapi_repl->error_code;
200 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
202 /* Set object session and handle */
203 mapi_object_set_session(obj_destination_context, session);
204 mapi_object_set_handle(obj_destination_context, mapi_response->handles[1]);
205 mapi_object_set_logon_id(obj_destination_context, logon_id);
207 talloc_free(mapi_response);
208 talloc_free(mem_ctx);
210 return MAPI_E_SUCCESS;
214 \details Advise a server of the "other server" version
216 This function is used to set up a fast server-client-server transfer.
218 \param obj_store pointer to the store MAPI object
219 \param version the server version
221 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
223 \note Developers may also call GetLastError() to retrieve the last
224 MAPI error code. Possible MAPI error codes are:
225 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
226 - MAPI_E_INVALID_PARAMETER: one of the function parameter is
228 - MAPI_E_CALL_FAILED: A network problem was encountered during the
231 _PUBLIC_ enum MAPISTATUS TellVersion(mapi_object_t *obj_store, uint16_t version[3])
233 struct mapi_request *mapi_request;
234 struct mapi_response *mapi_response;
235 struct EcDoRpc_MAPI_REQ *mapi_req;
236 struct TellVersion_req request;
237 struct mapi_session *session;
239 enum MAPISTATUS retval;
242 uint8_t logon_id = 0;
245 OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
246 OPENCHANGE_RETVAL_IF(!version, MAPI_E_INVALID_PARAMETER, NULL);
248 session = mapi_object_get_session(obj_store);
249 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
251 if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS)
254 mem_ctx = talloc_named(NULL, 0, "TellVersion");
257 /* Fill the operation */
258 request.version[0] = version[0];
259 request.version[1] = version[1];
260 request.version[2] = version[2];
261 size += 3 * sizeof (uint16_t);
265 /* Fill the MAPI_REQ structure */
266 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
267 mapi_req->opnum = op_MAPI_TellVersion;
268 mapi_req->logon_id = logon_id;
269 mapi_req->handle_idx = 0;
270 mapi_req->u.mapi_TellVersion = request;
273 /* Fill the mapi_request structure */
274 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
275 mapi_request->mapi_len = size + sizeof (uint32_t);
276 mapi_request->length = (uint16_t)size;
277 mapi_request->mapi_req = mapi_req;
278 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
279 mapi_request->handles[0] = mapi_object_get_handle(obj_store);
281 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
282 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
283 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
284 retval = mapi_response->mapi_repl->error_code;
285 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
287 talloc_free(mapi_response);
288 talloc_free(mem_ctx);
290 return MAPI_E_SUCCESS;
294 \details Prepare a server for Fast Transfer transmission of a folder hierachy
296 This function is used to configure a server for a fast-transfer folder hierachy
297 send operation. This could be the origin server in a server->client->server copy, or for a
298 server to client download.
300 This operation copies the folder object, and any sub-objects (including folder properties
301 and messages). It can optionally copy sub-folders, depending on copyFlags.
303 \param obj the source object for the operation (folder)
304 \param copyFlags flags that change the copy behaviour (see below)
305 \param sendOptions flags that change the format of the transfer (see FXCopyMessages)
306 \param obj_source_context the fast transfer source context for future ROPs
308 \a copyflags can be zero or more of the following:
309 - FastTransferCopyFolder_CopySubfolders to recursively copy any sub-folders and contained messages
310 - FastTransferCopyFolder_NoGhostedContent to omit any ghosted content when copying public folders
312 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
314 \note Developers may also call GetLastError() to retrieve the last
315 MAPI error code. Possible MAPI error codes are:
316 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
317 - MAPI_E_INVALID_PARAMETER: one of the function parameters is
319 - MAPI_E_CALL_FAILED: A network problem was encountered during the
322 _PUBLIC_ enum MAPISTATUS FXCopyFolder(mapi_object_t *obj, uint8_t copyFlags, uint8_t sendOptions,
323 mapi_object_t *obj_source_context)
325 struct mapi_request *mapi_request;
326 struct mapi_response *mapi_response;
327 struct EcDoRpc_MAPI_REQ *mapi_req;
328 struct FastTransferSourceCopyFolder_req request;
329 struct mapi_session *session;
331 enum MAPISTATUS retval;
334 uint8_t logon_id = 0;
337 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
339 session = mapi_object_get_session(obj);
340 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
341 OPENCHANGE_RETVAL_IF(!obj_source_context, MAPI_E_INVALID_PARAMETER, NULL);
343 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
346 mem_ctx = talloc_named(NULL, 0, "FXCopyFolder");
349 /* Fill the CopyFolder operation */
350 request.handle_idx = 0x01;
351 size += sizeof(uint8_t);
352 request.CopyFlags = copyFlags;
353 size += sizeof(uint8_t);
354 request.SendOptions = sendOptions;
355 size += sizeof(uint8_t);
357 /* Fill the MAPI_REQ structure */
358 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
359 mapi_req->opnum = op_MAPI_FastTransferSourceCopyFolder;
360 mapi_req->logon_id = logon_id;
361 mapi_req->handle_idx = 0;
362 mapi_req->u.mapi_FastTransferSourceCopyFolder = 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 = (uint16_t)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);
372 mapi_request->handles[1] = 0xffffffff;
374 status = emsmdb_transaction_wrapper(session, 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 /* Set object session and handle */
381 mapi_object_set_session(obj_source_context, session);
382 mapi_object_set_handle(obj_source_context, mapi_response->handles[1]);
383 mapi_object_set_logon_id(obj_source_context, logon_id);
385 talloc_free(mapi_response);
386 talloc_free(mem_ctx);
388 return MAPI_E_SUCCESS;
392 \details Prepare a server for Fast Transfer transmission of a list of messages
394 This function is used to configure a server for a fast-transfer message
395 send operation. This could be the origin server in a server->client->server copy, or for a
396 server to client download.
398 This operation copies the message objects, and any sub-objects (including attachments and embedded
401 \param obj the source object for the operation (folder)
402 \param message_ids the message IDs for the messages to copy.
403 \param copyFlags flags that change the copy behaviour (see below)
404 \param sendOptions flags that change the format of the transfer (see below)
405 \param obj_source_context the fast transfer source context for future ROPs
407 \a copyflags can be zero or more of the following:
408 - FastTransferCopyMessage_Move - configure output for move
409 - FastTransferCopyMessage_BestBody - output message bodies in original format (if not set, output in RTF)
410 - FastTransferCopyMessage_SendEntryId - include message and change identification in the output stream
412 \a sendOptions can be zero or more of the following:
413 - FastTransfer_Unicode - enable Unicode output
414 - FastTransfer_UseCpid (not normally used directly - implied by ForUpload)
415 - FastTransfer_ForUpload - (enable Unicode, and advise the server that transfer is server->client->server)
416 - FastTransfer_RecoverMode - advise the server that the client supports recovery mode
417 - FastTransfer_ForceUnicode - force Unicode output
418 - FastTransfer_PartialItem - used for synchronisation download
420 If the \a FastTransfer_ForUpload is set, the next call must be TellVersion()
422 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
424 \note Developers may also call GetLastError() to retrieve the last
425 MAPI error code. Possible MAPI error codes are:
426 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
427 - MAPI_E_INVALID_PARAMETER: one of the function parameters is
429 - MAPI_E_CALL_FAILED: A network problem was encountered during the
432 _PUBLIC_ enum MAPISTATUS FXCopyMessages(mapi_object_t *obj, mapi_id_array_t *message_ids,
433 uint8_t copyFlags, uint8_t sendOptions,
434 mapi_object_t *obj_source_context)
436 struct mapi_request *mapi_request;
437 struct mapi_response *mapi_response;
438 struct EcDoRpc_MAPI_REQ *mapi_req;
439 struct FastTransferSourceCopyMessages_req request;
440 struct mapi_session *session;
442 enum MAPISTATUS retval;
445 uint8_t logon_id = 0;
448 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
450 session = mapi_object_get_session(obj);
451 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
452 OPENCHANGE_RETVAL_IF(!obj_source_context, MAPI_E_INVALID_PARAMETER, NULL);
453 OPENCHANGE_RETVAL_IF(!message_ids, MAPI_E_INVALID_PARAMETER, NULL);
454 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
457 mem_ctx = talloc_named(NULL, 0, "FXCopyMessages");
460 /* Fill the CopyMessages operation */
461 request.handle_idx = 0x01;
462 size += sizeof(uint8_t);
463 request.MessageIdCount = message_ids->count;
464 size += sizeof (uint16_t);
465 retval = mapi_id_array_get(mem_ctx, message_ids, &(request.MessageIds));
466 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
467 size += request.MessageIdCount * sizeof (mapi_id_t);
468 request.CopyFlags = copyFlags;
469 size += sizeof(uint8_t);
470 request.SendOptions = sendOptions;
471 size += sizeof(uint8_t);
473 /* Fill the MAPI_REQ structure */
474 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
475 mapi_req->opnum = op_MAPI_FastTransferSourceCopyMessages;
476 mapi_req->logon_id = logon_id;
477 mapi_req->handle_idx = 0;
478 mapi_req->u.mapi_FastTransferSourceCopyMessages = request;
481 /* Fill the mapi_request structure */
482 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
483 mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
484 mapi_request->length = (uint16_t)size;
485 mapi_request->mapi_req = mapi_req;
486 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
487 mapi_request->handles[0] = mapi_object_get_handle(obj);
488 mapi_request->handles[1] = 0xffffffff;
490 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
491 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
492 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
493 retval = mapi_response->mapi_repl->error_code;
494 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
496 /* Set object session and handle */
497 mapi_object_set_session(obj_source_context, session);
498 mapi_object_set_handle(obj_source_context, mapi_response->handles[1]);
499 mapi_object_set_logon_id(obj_source_context, logon_id);
501 talloc_free(mapi_response);
502 talloc_free(mem_ctx);
504 return MAPI_E_SUCCESS;
508 \details Prepare a server for Fast Transfer transmission of a folder, message or attachment
510 This function is used to configure a server for a fast-transfer download of a folder, message
511 or attachment. This could be the origin server in a server->client->server copy, or for a
512 server to client download.
514 This operation copies the source object, potentially omitting some properties. It can optionally
515 copy sub-objects, depending on \a Level.
517 \param obj the source object for the operation (folder, message or attachment)
518 \param level whether to copy sub-objects of folders or messages (set to 0) or not (set to any other value)
519 \param copyFlags flags that change the copy behaviour (see below)
520 \param sendOptions flags that change the format of the transfer (see FXCopyMessages)
521 \param excludes the list of properties to exclude from the transfer
522 \param obj_source_context the fast transfer source context for future ROPs
524 \a copyflags can be zero or more of the following:
525 - FastTransferCopyTo_Move to configure as part of a move operation
526 - FastTransferCopyTo_BestBody to use original format for message bodies (if not set, use RTF instead)
528 Be careful in setting \a level to something other than zero. In particular, if \a level is
529 non-zero for a message, then the list of recipients, and any attachments or embedded messages, will
532 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
534 \note Developers may also call GetLastError() to retrieve the last
535 MAPI error code. Possible MAPI error codes are:
536 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
537 - MAPI_E_INVALID_PARAMETER: one of the function parameters is
539 - MAPI_E_CALL_FAILED: A network problem was encountered during the
542 _PUBLIC_ enum MAPISTATUS FXCopyTo(mapi_object_t *obj, uint8_t level, uint32_t copyFlags,
543 uint8_t sendOptions, struct SPropTagArray *excludes,
544 mapi_object_t *obj_source_context)
546 struct mapi_request *mapi_request;
547 struct mapi_response *mapi_response;
548 struct EcDoRpc_MAPI_REQ *mapi_req;
549 struct FastTransferSourceCopyTo_req request;
550 struct mapi_session *session;
552 enum MAPISTATUS retval;
555 uint8_t logon_id = 0;
558 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
560 session = mapi_object_get_session(obj);
561 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
562 OPENCHANGE_RETVAL_IF(!obj_source_context, MAPI_E_INVALID_PARAMETER, NULL);
563 OPENCHANGE_RETVAL_IF(!excludes, MAPI_E_INVALID_PARAMETER, NULL);
565 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
568 mem_ctx = talloc_named(NULL, 0, "FXCopyTo");
571 /* Fill the CopyTo operation */
572 request.handle_idx = 0x01;
573 size += sizeof(uint8_t);
574 request.Level = level;
575 size += sizeof(uint8_t);
576 request.CopyFlags = copyFlags;
577 size += sizeof(uint32_t);
578 request.SendOptions = sendOptions;
579 size += sizeof(uint8_t);
580 request.PropertyTags.cValues = excludes->cValues;
581 size += sizeof(uint16_t);
582 request.PropertyTags.aulPropTag = excludes->aulPropTag;
583 size += excludes->cValues * sizeof(enum MAPITAGS);
585 /* Fill the MAPI_REQ structure */
586 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
587 mapi_req->opnum = op_MAPI_FastTransferSourceCopyTo;
588 mapi_req->logon_id = logon_id;
589 mapi_req->handle_idx = 0;
590 mapi_req->u.mapi_FastTransferSourceCopyTo = request;
593 /* Fill the mapi_request structure */
594 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
595 mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
596 mapi_request->length = (uint16_t)size;
597 mapi_request->mapi_req = mapi_req;
598 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
599 mapi_request->handles[0] = mapi_object_get_handle(obj);
600 mapi_request->handles[1] = 0xffffffff;
602 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
603 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
604 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
605 retval = mapi_response->mapi_repl->error_code;
606 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
608 /* Set object session and handle */
609 mapi_object_set_session(obj_source_context, session);
610 mapi_object_set_handle(obj_source_context, mapi_response->handles[1]);
611 mapi_object_set_logon_id(obj_source_context, logon_id);
613 talloc_free(mapi_response);
614 talloc_free(mem_ctx);
616 return MAPI_E_SUCCESS;
620 \details Prepare a server for Fast Transfer transmission of the properties of a folder, message or attachment
622 This function is used to configure a server for a fast-transfer download of properties. This could be the
623 origin server in a server->client->server copy, or for a server to client download.
625 This operation copies the specified properties of the source object. It can optionally copy properties of
626 sub-objects, depending on \a Level.
628 \param obj the source object for the operation (folder, message or attachment)
629 \param level whether to copy properties of sub-objects of folders or messages (set to 0) or not (set to any other value)
630 \param copyFlags flags that change the copy behaviour (see below)
631 \param sendOptions flags that change the format of the transfer (see FXCopyMessages)
632 \param properties the list of properties to transfer
633 \param obj_source_context the fast transfer source context for future ROPs
635 \a copyflags may be the following:
636 - FastTransferCopyProperties_Move to configure as part of a move operation
638 Be careful in setting \a level to something other than zero. In particular, if \a level is
639 non-zero for a message, then the list of recipients, and any attachments or embedded messages, will
642 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
644 \note Developers may also call GetLastError() to retrieve the last
645 MAPI error code. Possible MAPI error codes are:
646 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
647 - MAPI_E_INVALID_PARAMETER: one of the function parameters is
649 - MAPI_E_CALL_FAILED: A network problem was encountered during the
652 _PUBLIC_ enum MAPISTATUS FXCopyProperties(mapi_object_t *obj, uint8_t level, uint32_t copyFlags,
653 uint8_t sendOptions, struct SPropTagArray *properties,
654 mapi_object_t *obj_source_context)
656 struct mapi_request *mapi_request;
657 struct mapi_response *mapi_response;
658 struct EcDoRpc_MAPI_REQ *mapi_req;
659 struct FastTransferSourceCopyProperties_req request;
660 struct mapi_session *session;
662 enum MAPISTATUS retval;
665 uint8_t logon_id = 0;
668 OPENCHANGE_RETVAL_IF(!obj, MAPI_E_INVALID_PARAMETER, NULL);
670 session = mapi_object_get_session(obj);
671 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
672 OPENCHANGE_RETVAL_IF(!obj_source_context, MAPI_E_INVALID_PARAMETER, NULL);
673 OPENCHANGE_RETVAL_IF(!properties, MAPI_E_INVALID_PARAMETER, NULL);
675 if ((retval = mapi_object_get_logon_id(obj, &logon_id)) != MAPI_E_SUCCESS)
678 mem_ctx = talloc_named(NULL, 0, "FXCopyProperties");
681 /* Fill the CopyProperties operation */
682 request.handle_idx = 0x01;
683 size += sizeof(uint8_t);
684 request.Level = level;
685 size += sizeof(uint8_t);
686 request.CopyFlags = copyFlags;
687 size += sizeof(uint8_t);
688 request.SendOptions = sendOptions;
689 size += sizeof(uint8_t);
690 request.PropertyTags.cValues = properties->cValues;
691 size += sizeof(uint16_t);
692 request.PropertyTags.aulPropTag = properties->aulPropTag;
693 size += properties->cValues * sizeof(enum MAPITAGS);
695 /* Fill the MAPI_REQ structure */
696 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
697 mapi_req->opnum = op_MAPI_FastTransferSourceCopyProps;
698 mapi_req->logon_id = logon_id;
699 mapi_req->handle_idx = 0;
700 mapi_req->u.mapi_FastTransferSourceCopyProperties = request;
703 /* Fill the mapi_request structure */
704 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
705 mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
706 mapi_request->length = (uint16_t)size;
707 mapi_request->mapi_req = mapi_req;
708 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
709 mapi_request->handles[0] = mapi_object_get_handle(obj);
710 mapi_request->handles[1] = 0xffffffff;
712 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
713 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
714 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
715 retval = mapi_response->mapi_repl->error_code;
716 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
718 /* Set object session and handle */
719 mapi_object_set_session(obj_source_context, session);
720 mapi_object_set_handle(obj_source_context, mapi_response->handles[1]);
721 mapi_object_set_logon_id(obj_source_context, logon_id);
723 talloc_free(mapi_response);
724 talloc_free(mem_ctx);
726 return MAPI_E_SUCCESS;
730 Get data from source fast transfer object
732 Fast transfers are done in blocks, each block transfered over a call to FXGetBuffer. If the block
733 is small, it will fit into a single call, and the transferStatus will indicate completion. However
734 larger transfers will require multiple calls.
736 \param obj_source_context the source object (from FXCopyTo, FXCopyProperties, FXCopyFolder or FXCopyMessages)
737 \param maxSize the maximum size (pass 0 to indicate maximum available size)
738 \param transferStatus result of the transfer
739 \param progressStepCount the approximate number of steps (of totalStepCount) completed
740 \param totalStepCount the approximate number of steps (total)
741 \param blob this part of the transfer
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_INVALID_PARAMETER: one of the function parameters is
750 - MAPI_E_CALL_FAILED: A network problem was encountered during the
753 _PUBLIC_ enum MAPISTATUS FXGetBuffer(mapi_object_t *obj_source_context, uint16_t maxSize, enum TransferStatus *transferStatus,
754 uint16_t *progressStepCount, uint16_t *totalStepCount, DATA_BLOB *blob)
756 struct mapi_request *mapi_request;
757 struct mapi_response *mapi_response;
758 struct EcDoRpc_MAPI_REQ *mapi_req;
759 struct FastTransferSourceGetBuffer_req request;
760 struct FastTransferSourceGetBuffer_repl *reply;
761 struct mapi_session *session;
763 enum MAPISTATUS retval;
766 uint8_t logon_id = 0;
769 OPENCHANGE_RETVAL_IF(!obj_source_context, MAPI_E_INVALID_PARAMETER, NULL);
771 session = mapi_object_get_session(obj_source_context);
772 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
774 if ((retval = mapi_object_get_logon_id(obj_source_context, &logon_id)) != MAPI_E_SUCCESS)
777 mem_ctx = talloc_named(NULL, 0, "FXGetBuffer");
780 /* Fill the GetBuffer operation */
781 if ((maxSize == 0) || (maxSize < 15480)) {
782 request.BufferSize = 0xBABE;
783 size += sizeof(uint16_t);
784 request.MaximumBufferSize.MaximumBufferSize = 0x8000;
785 size += sizeof(uint16_t);
787 request.BufferSize = maxSize;
788 size += sizeof(uint16_t);
791 /* Fill the MAPI_REQ structure */
792 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
793 mapi_req->opnum = op_MAPI_FastTransferSourceGetBuffer;
794 mapi_req->logon_id = logon_id;
795 mapi_req->handle_idx = 0;
796 mapi_req->u.mapi_FastTransferSourceGetBuffer = request;
799 /* Fill the mapi_request structure */
800 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
801 mapi_request->mapi_len = size + sizeof (uint32_t);
802 mapi_request->length = (uint16_t)size;
803 mapi_request->mapi_req = mapi_req;
804 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
805 mapi_request->handles[0] = mapi_object_get_handle(obj_source_context);
807 // TODO: handle backoff (0x00000480)
808 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
809 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
810 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
811 retval = mapi_response->mapi_repl->error_code;
812 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
814 /* Retrieve the result */
815 reply = &(mapi_response->mapi_repl->u.mapi_FastTransferSourceGetBuffer);
816 *transferStatus = reply->TransferStatus;
817 *progressStepCount = reply->InProgressCount;
818 *totalStepCount = reply->TotalStepCount;
819 blob->length = reply->TransferBufferSize;
820 blob->data = talloc_size((TALLOC_CTX *)session, blob->length);
821 memcpy(blob->data, reply->TransferBuffer.data, blob->length);
823 talloc_free(mapi_response);
824 talloc_free(mem_ctx);
826 return MAPI_E_SUCCESS;
830 Send data to a destination fast transfer object
832 Fast transfers are done in blocks, each block transfered over a call to FXGetBuffer. If the block
833 is small, it will fit into a single call, and the transferStatus will indicate completion. However
834 larger transfers will require multiple calls.
836 \param obj_dest_context the destination object (from FXDestConfigure)
837 \param blob this part of the transfer
838 \param usedSize how many bytes of this part of the transfer that were used (only less than the total if an error occurred)
840 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
842 \note Developers may also call GetLastError() to retrieve the last
843 MAPI error code. Possible MAPI error codes are:
844 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
845 - MAPI_E_INVALID_PARAMETER: one of the function parameters is
847 - MAPI_E_CALL_FAILED: A network problem was encountered during the
850 _PUBLIC_ enum MAPISTATUS FXPutBuffer(mapi_object_t *obj_dest_context, DATA_BLOB *blob, uint16_t *usedSize)
852 struct mapi_request *mapi_request;
853 struct mapi_response *mapi_response;
854 struct EcDoRpc_MAPI_REQ *mapi_req;
855 struct FastTransferDestinationPutBuffer_req request;
856 struct FastTransferDestinationPutBuffer_repl *reply;
857 struct mapi_session *session;
859 enum MAPISTATUS retval;
862 uint8_t logon_id = 0;
865 OPENCHANGE_RETVAL_IF(!obj_dest_context, MAPI_E_INVALID_PARAMETER, NULL);
866 OPENCHANGE_RETVAL_IF(!blob, MAPI_E_INVALID_PARAMETER, NULL);
867 OPENCHANGE_RETVAL_IF(!usedSize, MAPI_E_INVALID_PARAMETER, NULL);
869 session = mapi_object_get_session(obj_dest_context);
870 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
872 if ((retval = mapi_object_get_logon_id(obj_dest_context, &logon_id)) != MAPI_E_SUCCESS)
875 mem_ctx = talloc_named(NULL, 0, "FXPutBuffer");
878 /* Fill the PutBuffer operation */
879 request.TransferBufferSize = blob->length;
880 size += sizeof(uint16_t);
881 request.TransferBuffer = *blob;
882 size += blob->length;
884 /* Fill the MAPI_REQ structure */
885 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
886 mapi_req->opnum = op_MAPI_FastTransferDestPutBuffer;
887 mapi_req->logon_id = logon_id;
888 mapi_req->handle_idx = 0;
889 mapi_req->u.mapi_FastTransferDestinationPutBuffer = request;
892 /* Fill the mapi_request structure */
893 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
894 mapi_request->mapi_len = size + sizeof (uint32_t);
895 mapi_request->length = (uint16_t)size;
896 mapi_request->mapi_req = mapi_req;
897 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
898 mapi_request->handles[0] = mapi_object_get_handle(obj_dest_context);
900 // TODO: handle backoff (0x00000480)
901 status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
902 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
903 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
904 retval = mapi_response->mapi_repl->error_code;
905 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
907 /* Retrieve the result */
908 reply = &(mapi_response->mapi_repl->u.mapi_FastTransferDestinationPutBuffer);
909 *usedSize = reply->BufferUsedCount;
910 /* we could pull more stuff here, but it doesn't seem useful */
912 talloc_free(mapi_response);
913 talloc_free(mem_ctx);
915 return MAPI_E_SUCCESS;