Replace deprecated talloc_init calls with talloc_named
[jelmer/openchange.git] / libmapi / IStoreFolder.c
1 /*
2    OpenChange MAPI implementation.
3
4    Copyright (C) Julien Kerihuel 2007-2008.
5
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.
10    
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.
15    
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/>.
18  */
19
20 #include <libmapi/libmapi.h>
21 #include <libmapi/proto_private.h>
22 #include <gen_ndr/ndr_exchange.h>
23
24
25 /**
26    \file IStoreFolder.c
27  
28    \brief Open messages
29 */
30
31
32 /**
33    \details Opens a specific message and retrieves a MAPI object that
34    can be used to get or set message properties.
35
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.
39
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
44    \param ulFlags
45
46    Possible ulFlags values:
47    - 0x0: read only access
48    - 0x1: ReadWrite
49    - 0x3: Create
50
51    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
52
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
58      transaction
59
60    \sa MAPIInitialize, GetLastError
61 */
62 _PUBLIC_ enum MAPISTATUS OpenMessage(mapi_object_t *obj_store, 
63                                      mapi_id_t id_folder, 
64                                      mapi_id_t id_message, 
65                                      mapi_object_t *obj_message,
66                                      uint8_t ulFlags)
67 {
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;
76         NTSTATUS                        status;
77         enum MAPISTATUS                 retval;
78         uint32_t                        size = 0;
79         TALLOC_CTX                      *mem_ctx;
80         uint32_t                        i = 0;
81
82         /* Sanity checks */
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);
87
88         mem_ctx = talloc_named(NULL, 0, "OpenMessage");
89
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);
97
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;
104         size += 5;
105
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;
114
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);
120
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]);
124
125         /* Store OpenMessage reply data */
126         reply = &mapi_response->mapi_repl->u.mapi_OpenMessage;
127
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);
132
133         message->SPropTagArray.cValues = reply->RecipientColumns.cValues;
134         message->SPropTagArray.aulPropTag = reply->RecipientColumns.aulPropTag;
135
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);
142
143                 lpProp.ulPropTag = PR_RECIPIENT_TYPE;
144                 lpProp.value.l = reply->recipients[i].RecipClass;
145                 SRow_addprop(&(message->SRowSet.aRow[i]), lpProp);
146
147                 lpProp.ulPropTag = PR_INTERNET_CPID;
148                 lpProp.value.l = reply->recipients[i].codepage;
149                 SRow_addprop(&(message->SRowSet.aRow[i]), lpProp);
150         }
151
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);
155
156         obj_message->private_data = (void *) message;
157
158         talloc_free(mapi_response);
159         talloc_free(mem_ctx);
160
161         return MAPI_E_SUCCESS;
162 }