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/proto_private.h>
22 #include <gen_ndr/ndr_exchange.h>
33 \details Opens a specific message and retrieves a MAPI object that
34 can be used to get or set message properties.
36 This function opens a specific message defined by a combination of
37 object store, folder ID, and message ID and which read/write access
38 is defined by ulFlags.
40 \param obj_store the store to read from
41 \param id_folder the folder ID
42 \param id_message the message ID
43 \param obj_message the resulting message object
46 Possible ulFlags values:
47 - 0x0: read only access
51 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
53 \note Developers may also call GetLastError() to retrieve the last
54 MAPI error code. Possible MAPI error codes are:
55 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
56 - MAPI_E_INVALID_PARAMETER: obj_store is undefined
57 - MAPI_E_CALL_FAILED: A network problem was encountered during the
60 \sa MAPIInitialize, GetLastError
62 _PUBLIC_ enum MAPISTATUS OpenMessage(mapi_object_t *obj_store,
65 mapi_object_t *obj_message,
68 struct mapi_request *mapi_request;
69 struct mapi_response *mapi_response;
70 struct EcDoRpc_MAPI_REQ *mapi_req;
71 struct OpenMessage_req request;
72 struct OpenMessage_repl *reply;
73 struct mapi_session *session;
74 mapi_object_message_t *message;
75 struct SPropValue lpProp;
77 enum MAPISTATUS retval;
83 OPENCHANGE_RETVAL_IF(!global_mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL);
84 OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL);
85 session = mapi_object_get_session(obj_store);
86 OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
88 mem_ctx = talloc_named(NULL, 0, "OpenMessage");
90 /* Fill the OpenMessage operation */
91 request.handle_idx = 0x1;
92 request.CodePageId = 0xfff;
93 request.FolderId = id_folder;
94 request.OpenModeFlags = ulFlags;
95 request.MessageId = id_message;
96 size = sizeof (uint8_t) + sizeof(uint16_t) + sizeof(mapi_id_t) + sizeof(uint8_t) + sizeof(mapi_id_t);
98 /* Fill the MAPI_REQ request */
99 mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
100 mapi_req->opnum = op_MAPI_OpenMessage;
101 mapi_req->logon_id = 0;
102 mapi_req->handle_idx = 0;
103 mapi_req->u.mapi_OpenMessage = request;
106 /* Fill the mapi_request structure */
107 mapi_request = talloc_zero(mem_ctx, struct mapi_request);
108 mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
109 mapi_request->length = size;
110 mapi_request->mapi_req = mapi_req;
111 mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
112 mapi_request->handles[0] = mapi_object_get_handle(obj_store);
113 mapi_request->handles[1] = 0xffffffff;
115 status = emsmdb_transaction(session->emsmdb->ctx, mapi_request, &mapi_response);
116 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
117 OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
118 retval = mapi_response->mapi_repl->error_code;
119 OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
121 /* Set object session and handle */
122 mapi_object_set_session(obj_message, session);
123 mapi_object_set_handle(obj_message, mapi_response->handles[1]);
125 /* Store OpenMessage reply data */
126 reply = &mapi_response->mapi_repl->u.mapi_OpenMessage;
128 message = talloc_zero((TALLOC_CTX *)session, mapi_object_message_t);
129 message->cValues = reply->RecipientColumns.cValues;
130 message->SRowSet.cRows = reply->RowCount;
131 message->SRowSet.aRow = talloc_array((TALLOC_CTX *)message, struct SRow, reply->RowCount + 1);
133 message->SPropTagArray.cValues = reply->RecipientColumns.cValues;
134 message->SPropTagArray.aulPropTag = reply->RecipientColumns.aulPropTag;
136 for (i = 0; i < reply->RowCount; i++) {
137 emsmdb_get_SRow((TALLOC_CTX *)message, global_mapi_ctx->lp_ctx,
138 &(message->SRowSet.aRow[i]), &message->SPropTagArray,
139 reply->recipients[i].RecipientRow.prop_count,
140 &reply->recipients[i].RecipientRow.prop_values,
141 reply->recipients[i].RecipientRow.layout, 1);
143 lpProp.ulPropTag = PR_RECIPIENT_TYPE;
144 lpProp.value.l = reply->recipients[i].RecipClass;
145 SRow_addprop(&(message->SRowSet.aRow[i]), lpProp);
147 lpProp.ulPropTag = PR_INTERNET_CPID;
148 lpProp.value.l = reply->recipients[i].codepage;
149 SRow_addprop(&(message->SRowSet.aRow[i]), lpProp);
152 /* add SPropTagArray elements we automatically append to SRow */
153 SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_RECIPIENT_TYPE);
154 SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_INTERNET_CPID);
156 obj_message->private_data = (void *) message;
158 talloc_free(mapi_response);
159 talloc_free(mem_ctx);
161 return MAPI_E_SUCCESS;