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>
32 \details Opens a specific message and retrieves a MAPI object that
33 can be used to get or set message properties.
35 This function opens a specific message defined by a combination of
36 object store, folder ID, and message ID and which read/write access
37 is defined by ulFlags.
39 \param obj_store the store to read from
40 \param id_folder the folder ID
41 \param id_message the message ID
42 \param obj_message the resulting message object
45 Possible ulFlags values:
46 - 0x0: read only access
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_store is undefined
56 - MAPI_E_CALL_FAILED: A network problem was encountered during the
59 \sa MAPIInitialize, GetLastError
61 _PUBLIC_
enum MAPISTATUS
OpenMessage(mapi_object_t
*obj_store
,
64 mapi_object_t
*obj_message
,
67 struct mapi_request
*mapi_request
;
68 struct mapi_response
*mapi_response
;
69 struct EcDoRpc_MAPI_REQ
*mapi_req
;
70 struct OpenMessage_req request
;
71 struct OpenMessage_repl
*reply
;
72 struct mapi_session
*session
;
73 mapi_object_message_t
*message
;
74 struct SPropValue lpProp
;
76 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 if ((retval
= mapi_object_get_logon_id(obj_store
, &logon_id
)) != MAPI_E_SUCCESS
)
91 mem_ctx
= talloc_named(NULL
, 0, "OpenMessage");
93 /* Fill the OpenMessage operation */
94 request
.handle_idx
= 0x1;
95 request
.CodePageId
= 0xfff;
96 request
.FolderId
= id_folder
;
97 request
.OpenModeFlags
= ulFlags
;
98 request
.MessageId
= id_message
;
99 size
= sizeof (uint8_t) + sizeof(uint16_t) + sizeof(mapi_id_t
) + sizeof(uint8_t) + sizeof(mapi_id_t
);
101 /* Fill the MAPI_REQ request */
102 mapi_req
= talloc_zero(mem_ctx
, struct EcDoRpc_MAPI_REQ
);
103 mapi_req
->opnum
= op_MAPI_OpenMessage
;
104 mapi_req
->logon_id
= logon_id
;
105 mapi_req
->handle_idx
= 0;
106 mapi_req
->u
.mapi_OpenMessage
= request
;
109 /* Fill the mapi_request structure */
110 mapi_request
= talloc_zero(mem_ctx
, struct mapi_request
);
111 mapi_request
->mapi_len
= size
+ sizeof (uint32_t) * 2;
112 mapi_request
->length
= size
;
113 mapi_request
->mapi_req
= mapi_req
;
114 mapi_request
->handles
= talloc_array(mem_ctx
, uint32_t, 2);
115 mapi_request
->handles
[0] = mapi_object_get_handle(obj_store
);
116 mapi_request
->handles
[1] = 0xffffffff;
118 status
= emsmdb_transaction(session
->emsmdb
->ctx
, mapi_request
, &mapi_response
);
119 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status
), MAPI_E_CALL_FAILED
, mem_ctx
);
120 OPENCHANGE_RETVAL_IF(!mapi_response
->mapi_repl
, MAPI_E_CALL_FAILED
, mem_ctx
);
121 retval
= mapi_response
->mapi_repl
->error_code
;
122 OPENCHANGE_RETVAL_IF(retval
, retval
, mem_ctx
);
124 OPENCHANGE_CHECK_NOTIFICATION(session
, mapi_response
);
126 /* Set object session and handle */
127 mapi_object_set_session(obj_message
, session
);
128 mapi_object_set_handle(obj_message
, mapi_response
->handles
[1]);
129 mapi_object_set_logon_id(obj_message
, logon_id
);
131 /* Store OpenMessage reply data */
132 reply
= &mapi_response
->mapi_repl
->u
.mapi_OpenMessage
;
134 message
= talloc_zero((TALLOC_CTX
*)session
, mapi_object_message_t
);
135 message
->cValues
= reply
->RecipientColumns
.cValues
;
136 message
->SRowSet
.cRows
= reply
->RowCount
;
137 message
->SRowSet
.aRow
= talloc_array((TALLOC_CTX
*)message
, struct SRow
, reply
->RowCount
+ 1);
139 message
->SPropTagArray
.cValues
= reply
->RecipientColumns
.cValues
;
140 message
->SPropTagArray
.aulPropTag
= talloc_steal(message
, reply
->RecipientColumns
.aulPropTag
);
142 for (i
= 0; i
< reply
->RowCount
; i
++) {
143 emsmdb_get_SRow((TALLOC_CTX
*)message
, global_mapi_ctx
->lp_ctx
,
144 &(message
->SRowSet
.aRow
[i
]), &message
->SPropTagArray
,
145 reply
->recipients
[i
].RecipientRow
.prop_count
,
146 &reply
->recipients
[i
].RecipientRow
.prop_values
,
147 reply
->recipients
[i
].RecipientRow
.layout
, 1);
149 lpProp
.ulPropTag
= PR_RECIPIENT_TYPE
;
150 lpProp
.value
.l
= reply
->recipients
[i
].RecipClass
;
151 SRow_addprop(&(message
->SRowSet
.aRow
[i
]), lpProp
);
153 lpProp
.ulPropTag
= PR_INTERNET_CPID
;
154 lpProp
.value
.l
= reply
->recipients
[i
].codepage
;
155 SRow_addprop(&(message
->SRowSet
.aRow
[i
]), lpProp
);
158 /* add SPropTagArray elements we automatically append to SRow */
159 SPropTagArray_add((TALLOC_CTX
*)message
, &message
->SPropTagArray
, PR_RECIPIENT_TYPE
);
160 SPropTagArray_add((TALLOC_CTX
*)message
, &message
->SPropTagArray
, PR_INTERNET_CPID
);
162 obj_message
->private_data
= (void *) message
;
164 talloc_free(mapi_response
);
165 talloc_free(mem_ctx
);
167 return MAPI_E_SUCCESS
;
171 \details Retrieve the message properties for an already open message.
173 This function is very similar to OpenMessage, but works on an already
176 \param obj_store the store to read from
177 \param id_folder the folder ID
178 \param id_message the message ID
179 \param obj_message the resulting message object
182 Possible ulFlags values:
183 - 0x0: read only access
187 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
189 \note Developers may also call GetLastError() to retrieve the last
190 MAPI error code. Possible MAPI error codes are:
191 - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
192 - MAPI_E_INVALID_PARAMETER: obj_store is undefined
193 - MAPI_E_CALL_FAILED: A network problem was encountered during the
198 _PUBLIC_
enum MAPISTATUS
ReloadCachedInformation(mapi_object_t
*obj_message
)
200 struct mapi_request
*mapi_request
;
201 struct mapi_response
*mapi_response
;
202 struct EcDoRpc_MAPI_REQ
*mapi_req
;
203 struct ReloadCachedInformation_req request
;
204 struct ReloadCachedInformation_repl
*reply
;
205 struct mapi_session
*session
;
206 mapi_object_message_t
*message
;
207 struct SPropValue lpProp
;
209 enum MAPISTATUS retval
;
216 OPENCHANGE_RETVAL_IF(!global_mapi_ctx
, MAPI_E_NOT_INITIALIZED
, NULL
);
217 OPENCHANGE_RETVAL_IF(!obj_message
, MAPI_E_INVALID_PARAMETER
, NULL
);
218 session
= mapi_object_get_session(obj_message
);
219 OPENCHANGE_RETVAL_IF(!session
, MAPI_E_INVALID_PARAMETER
, NULL
);
221 if ((retval
= mapi_object_get_logon_id(obj_message
, &logon_id
)) != MAPI_E_SUCCESS
)
224 mem_ctx
= talloc_named(NULL
, 0, "ReloadCachedInformation");
226 /* Fill the ReloadCachedInformation operation */
227 request
.Reserved
= 0x0000;
228 size
+= sizeof (uint16_t);
230 /* Fill the MAPI_REQ request */
231 mapi_req
= talloc_zero(mem_ctx
, struct EcDoRpc_MAPI_REQ
);
232 mapi_req
->opnum
= op_MAPI_ReloadCachedInformation
;
233 mapi_req
->logon_id
= logon_id
;
234 mapi_req
->handle_idx
= 0;
235 mapi_req
->u
.mapi_ReloadCachedInformation
= request
;
238 /* Fill the mapi_request structure */
239 mapi_request
= talloc_zero(mem_ctx
, struct mapi_request
);
240 mapi_request
->mapi_len
= size
+ sizeof (uint32_t);
241 mapi_request
->length
= size
;
242 mapi_request
->mapi_req
= mapi_req
;
243 mapi_request
->handles
= talloc_array(mem_ctx
, uint32_t, 1);
244 mapi_request
->handles
[0] = mapi_object_get_handle(obj_message
);
246 status
= emsmdb_transaction(session
->emsmdb
->ctx
, mapi_request
, &mapi_response
);
247 OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status
), MAPI_E_CALL_FAILED
, mem_ctx
);
248 OPENCHANGE_RETVAL_IF(!mapi_response
->mapi_repl
, MAPI_E_CALL_FAILED
, mem_ctx
);
249 retval
= mapi_response
->mapi_repl
->error_code
;
251 OPENCHANGE_RETVAL_IF(retval
, retval
, mem_ctx
);
253 OPENCHANGE_CHECK_NOTIFICATION(session
, mapi_response
);
255 /* Store ReloadCachedInformation reply data */
256 reply
= &mapi_response
->mapi_repl
->u
.mapi_ReloadCachedInformation
;
258 message
= talloc_zero((TALLOC_CTX
*)session
, mapi_object_message_t
);
259 message
->cValues
= reply
->RecipientColumns
.cValues
;
260 message
->SRowSet
.cRows
= reply
->RowCount
;
261 message
->SRowSet
.aRow
= talloc_array((TALLOC_CTX
*)message
, struct SRow
, reply
->RowCount
+ 1);
263 message
->SPropTagArray
.cValues
= reply
->RecipientColumns
.cValues
;
264 message
->SPropTagArray
.aulPropTag
= talloc_steal(message
, reply
->RecipientColumns
.aulPropTag
);
266 for (i
= 0; i
< reply
->RowCount
; i
++) {
267 emsmdb_get_SRow((TALLOC_CTX
*)message
, global_mapi_ctx
->lp_ctx
,
268 &(message
->SRowSet
.aRow
[i
]), &message
->SPropTagArray
,
269 reply
->RecipientRows
[i
].RecipientRow
.prop_count
,
270 &reply
->RecipientRows
[i
].RecipientRow
.prop_values
,
271 reply
->RecipientRows
[i
].RecipientRow
.layout
, 1);
273 lpProp
.ulPropTag
= PR_RECIPIENT_TYPE
;
274 lpProp
.value
.l
= reply
->RecipientRows
[i
].RecipientType
;
275 SRow_addprop(&(message
->SRowSet
.aRow
[i
]), lpProp
);
277 lpProp
.ulPropTag
= PR_INTERNET_CPID
;
278 lpProp
.value
.l
= reply
->RecipientRows
[i
].CodePageId
;
279 SRow_addprop(&(message
->SRowSet
.aRow
[i
]), lpProp
);
282 /* add SPropTagArray elements we automatically append to SRow */
283 SPropTagArray_add((TALLOC_CTX
*)message
, &message
->SPropTagArray
, PR_RECIPIENT_TYPE
);
284 SPropTagArray_add((TALLOC_CTX
*)message
, &message
->SPropTagArray
, PR_INTERNET_CPID
);
286 talloc_free(obj_message
->private_data
);
287 obj_message
->private_data
= (void *) message
;
289 talloc_free(mapi_response
);
290 talloc_free(mem_ctx
);
293 return MAPI_E_SUCCESS
;