Fix issue #376, patch from Milan Crha:
[jelmer/openchange-proposed.git/.git] / libmapi / IMAPIContainer.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/libmapi_private.h"
22
23
24 /**
25    \file IMAPIContainer.c
26
27    \brief Containers and tables related operations
28 */
29
30
31 /**
32    \details Returns a pointer to a container's table object
33
34    This function takes a pointer to a container object and returns a
35    pointer to its associated contents
36
37    \param obj_container the object to get the contents of
38    \param obj_table the resulting table containing the container's
39    contents.
40    \param TableFlags flags controlling the type of table
41    \param RowCount the number of rows in the hierarchy table
42
43    TableFlags possible values:
44
45    - TableFlags_Associated (0x2): Get the contents table for "Folder Associated
46    Information" messages, rather than normal messages.
47
48    - TableFlags_DeferredErrors (0x8): The call response can return immediately,
49    possibly before the call execution is complete and in this case the
50    ReturnValue as well the RowCount fields in the return buffer might
51    not be accurate.  Only retval reporting failure can be considered
52    valid in this case.
53
54    - TableFlags_NoNotifications (0x10): Disables all notifications on .this Table
55    object.
56
57    - TableFlags_SoftDeletes (0x20): Enables the client to get a list of the soft
58    deleted folders.
59
60    - TableFlags_UseUnicode (0x40): Requests that the columns that contain string
61    data be returned in Unicode format.
62
63    - TableFlags_SuppressNotifications (0x80): Suppresses notifications generated
64    by this client’s actions on this Table object.
65
66    Developers can either set RowCount to a valid pointer on uint32_t
67    or set it to NULL. In this last case, GetHierarchyTable won't
68    return any value to the calling function.
69
70    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
71
72    \note Developers may also call GetLastError() to retrieve the last
73    MAPI error code. Possible MAPI error codes are:
74    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
75    - MAPI_E_CALL_FAILED: A network problem was encountered during the
76      transaction
77
78    \sa OpenFolder, GetHierarchyTable, GetLastError
79 */
80 _PUBLIC_ enum MAPISTATUS GetContentsTable(mapi_object_t *obj_container, mapi_object_t *obj_table,
81                                           uint8_t TableFlags, uint32_t *RowCount)
82 {
83         struct mapi_request             *mapi_request;
84         struct mapi_response            *mapi_response;
85         struct EcDoRpc_MAPI_REQ         *mapi_req;
86         struct GetContentsTable_req     request;
87         struct mapi_session             *session;
88         NTSTATUS                        status;
89         enum MAPISTATUS                 retval;
90         uint32_t                        size = 0;
91         TALLOC_CTX                      *mem_ctx;
92         uint8_t                         logon_id;
93
94         /* Sanity checks */
95         OPENCHANGE_RETVAL_IF(!obj_container, MAPI_E_INVALID_PARAMETER, NULL);
96
97         session = mapi_object_get_session(obj_container);
98         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
99
100         if ((retval = mapi_object_get_logon_id(obj_container, &logon_id)) != MAPI_E_SUCCESS)
101                 return retval;
102
103         mem_ctx = talloc_named(session, 0, "GetContentsTable");
104         size = 0;
105
106         /* Fill the GetContentsTable operation */
107         request.handle_idx = 0x1;
108         request.TableFlags = TableFlags;
109         size += 2;
110
111         /* Fill the MAPI_REQ request */
112         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
113         mapi_req->opnum = op_MAPI_GetContentsTable;
114         mapi_req->logon_id = logon_id;
115         mapi_req->handle_idx = 0;
116         mapi_req->u.mapi_GetContentsTable = request;
117         size += 5;
118
119         /* Fill the mapi_request structure */
120         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
121         mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
122         mapi_request->length = size;
123         mapi_request->mapi_req = mapi_req;
124         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
125         mapi_request->handles[0] = mapi_object_get_handle(obj_container);
126         mapi_request->handles[1] = 0xffffffff;
127
128         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
129         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
130         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
131         retval = mapi_response->mapi_repl->error_code;
132         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
133
134         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
135
136         /* set object session, handle and logon_id */
137         mapi_object_set_session(obj_table, session);
138         mapi_object_set_handle(obj_table, mapi_response->handles[1]);
139         mapi_object_set_logon_id(obj_table, logon_id);
140
141         /* Retrieve RowCount if a valid pointer was set */
142         if (RowCount) {
143                 *RowCount = mapi_response->mapi_repl->u.mapi_GetContentsTable.RowCount;
144         }
145         
146         /* new table */
147         mapi_object_table_init((TALLOC_CTX *)session, obj_table);
148
149         talloc_free(mapi_response);
150         talloc_free(mem_ctx);
151
152         return MAPI_E_SUCCESS;
153 }
154
155
156 /**
157    \details Returns a pointer to a container's table object
158
159    This function takes a pointer to a container object and returns a
160    pointer to its associated hierarchy table
161
162    \param obj_container the object to get the contents of
163    \param obj_table the resulting table containing the container's
164    hierarchy
165    \param TableFlags flags controlling the type of table
166    \param RowCount the number of rows in the hierarchy table
167
168    TableFlags possible values:
169
170    - TableFlags_Depth (0x4): Fills the hierarchy table with containers
171    from all levels. If this flag is not set, the hierarchy table
172    contains only the container's immediate child containers.
173
174    - TableFlags_DeferredErrors (0x8): The call response can return immediately,
175    possibly before the call execution is complete and in this case the
176    ReturnValue as well the RowCount fields in the return buffer might
177    not be accurate.  Only retval reporting failure can be considered
178    valid in this case.
179
180    - TableFlags_NoNotifications (0x10): Disables all notifications on .this Table
181    object.
182
183    - TableFlags_SoftDeletes (0x20): Enables the client to get a list of the soft
184    deleted folders.
185
186    - TableFlags_UseUnicode (0x40): Requests that the columns that contain string
187    data be returned in Unicode format.
188
189    - TableFlags_SuppressNotifications (0x80): Suppresses notifications generated
190    by this client’s actions on this Table object.
191
192    Developers can either set RowCount to a valid pointer on uint32_t
193    or set it to NULL. In this last case, GetHierarchyTable won't
194    return any value to the calling function.
195
196    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
197
198    \note Developers may also call GetLastError() to retrieve the last
199    MAPI error code. Possible MAPI error codes are:
200    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
201    - MAPI_E_CALL_FAILED: A network problem was encountered during the
202      transaction
203
204    \sa OpenFolder, GetContentsTable, GetLastError
205 */
206 _PUBLIC_ enum MAPISTATUS GetHierarchyTable(mapi_object_t *obj_container, mapi_object_t *obj_table,
207                                            uint8_t TableFlags, uint32_t *RowCount)
208 {
209         struct mapi_request             *mapi_request;
210         struct mapi_response            *mapi_response;
211         struct EcDoRpc_MAPI_REQ         *mapi_req;
212         struct GetHierarchyTable_req    request;
213         struct mapi_session             *session;
214         NTSTATUS                        status;
215         enum MAPISTATUS                 retval;
216         uint32_t                        size = 0;
217         TALLOC_CTX                      *mem_ctx;
218         uint8_t                         logon_id;
219
220         /* Sanity checks */
221         OPENCHANGE_RETVAL_IF(!obj_container, MAPI_E_INVALID_PARAMETER, NULL);
222         
223         session = mapi_object_get_session(obj_container);
224         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
225
226         if ((retval = mapi_object_get_logon_id(obj_container, &logon_id)) != MAPI_E_SUCCESS)
227                 return retval;
228
229         mem_ctx = talloc_named(session, 0, "GetHierarchyTable");
230         size = 0;
231
232         /* Fill the GetHierarchyTable operation */
233         request.handle_idx = 0x1;
234         request.TableFlags = TableFlags;
235         size += 2;
236
237         /* Fill the MAPI_REQ request */
238         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
239         mapi_req->opnum = op_MAPI_GetHierarchyTable;
240         mapi_req->logon_id = logon_id;
241         mapi_req->handle_idx = 0;
242         mapi_req->u.mapi_GetHierarchyTable = request;
243         size += 5;
244
245         /* Fill the mapi_request structure */
246         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
247         mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
248         mapi_request->length = size;
249         mapi_request->mapi_req = mapi_req;
250         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
251         mapi_request->handles[0] = mapi_object_get_handle(obj_container);
252         mapi_request->handles[1] = 0xffffffff;
253
254         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
255         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
256         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
257         retval = mapi_response->mapi_repl->error_code;
258         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
259
260         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
261
262         /* set object session, handle and logon_id */
263         mapi_object_set_session(obj_table, session);
264         mapi_object_set_handle(obj_table, mapi_response->handles[1]);
265         mapi_object_set_logon_id(obj_table, logon_id);
266
267         /* Retrieve RowCount if a valid pointer was set */
268         if (RowCount) {
269                 *RowCount = mapi_response->mapi_repl->u.mapi_GetHierarchyTable.RowCount;
270         }
271
272         /* new table */
273         mapi_object_table_init((TALLOC_CTX *)session, obj_table);
274
275         talloc_free(mapi_response);
276         talloc_free(mem_ctx);
277
278         return MAPI_E_SUCCESS;
279 }
280
281
282 /**
283    \details Returns a pointer to the permission's table object.  
284
285    This function takes a pointer to a container object and returns a
286    pointer to its associated permission table
287
288    \param obj_container the object to get the contents of
289    \param flags any special flags to pass
290    \param obj_table the resulting table containing the container's
291    permissions
292    
293    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
294
295    The only meaningful value for flags is IncludeFreeBusy (0x02). This
296    should be set when getting permissions on the Calendar folder when
297    using Exchange 2007 and later. It should not be set in other situations.
298
299    \note Developers may also call GetLastError() to retrieve the last
300    MAPI error code. Possible MAPI error codes are:
301    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
302    - MAPI_E_CALL_FAILED: A network problem was encountered during the
303      transaction
304
305    \sa ModifyPermissions
306  */
307 _PUBLIC_ enum MAPISTATUS GetPermissionsTable(mapi_object_t *obj_container, uint8_t flags, mapi_object_t *obj_table)
308 {
309         struct mapi_request             *mapi_request;
310         struct mapi_response            *mapi_response;
311         struct EcDoRpc_MAPI_REQ         *mapi_req;
312         struct GetPermissionsTable_req  request;
313         struct mapi_session             *session;
314         NTSTATUS                        status;
315         enum MAPISTATUS                 retval;
316         uint32_t                        size = 0;
317         TALLOC_CTX                      *mem_ctx;
318         uint8_t                         logon_id;
319
320         /* Sanity checks */
321         OPENCHANGE_RETVAL_IF(!obj_container, MAPI_E_INVALID_PARAMETER, NULL);
322
323         session = mapi_object_get_session(obj_container);
324         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
325
326         if ((retval = mapi_object_get_logon_id(obj_container, &logon_id)) != MAPI_E_SUCCESS)
327                 return retval;
328
329         mem_ctx = talloc_named(session, 0, "GetPermissionsTable");
330         size = 0;
331
332         /* Fill the GetPermissionsTable operation */
333         request.handle_idx = 0x1;
334         request.TableFlags = flags;
335         size += 2;
336
337         /* Fill the MAPI_REQ request */
338         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
339         mapi_req->opnum = op_MAPI_GetPermissionsTable;
340         mapi_req->logon_id = logon_id;
341         mapi_req->handle_idx= 0;
342         mapi_req->u.mapi_GetPermissionsTable = request;
343         size += 5;
344
345         /* Fill the mapi_request structure */
346         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
347         mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
348         mapi_request->length = size;
349         mapi_request->mapi_req = mapi_req;
350         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
351         mapi_request->handles[0] = mapi_object_get_handle(obj_container);
352         mapi_request->handles[1] = 0xffffffff;
353
354         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
355         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
356         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
357         retval = mapi_response->mapi_repl->error_code;
358         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
359
360         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
361
362         /* set object session, handle and logon_id */
363         mapi_object_set_session(obj_table, session);
364         mapi_object_set_handle(obj_table, mapi_response->handles[1]);
365         mapi_object_set_logon_id(obj_table, logon_id);
366
367         /* new table */
368         mapi_object_table_init((TALLOC_CTX *)session, obj_table);
369
370         talloc_free(mapi_response);
371         talloc_free(mem_ctx);
372
373         return MAPI_E_SUCCESS;
374 }
375
376
377 /**
378    \details Gets the rules table of a folder
379
380    \param obj_folder the folder we want to retrieve the rules table
381    from
382    \param obj_table the rules table
383    \param TableFlags bitmask associated to the rules table
384
385    Possible values for TableFlags:
386
387    - RulesTableFlags_Unicode (0x40): Set if the client is requesting
388      that string values in the table to be returned as Unicode
389      strings.
390
391    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
392
393     \note Developers may also call GetLastError() to retrieve the last
394    MAPI error code. Possible MAPI error codes are:
395    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
396    - MAPI_E_CALL_FAILED: A network problem was encountered during the
397      transaction  
398  */
399 _PUBLIC_ enum MAPISTATUS GetRulesTable(mapi_object_t *obj_folder, 
400                                        mapi_object_t *obj_table,
401                                        uint8_t TableFlags)
402 {
403         struct mapi_request             *mapi_request;
404         struct mapi_response            *mapi_response;
405         struct EcDoRpc_MAPI_REQ         *mapi_req;
406         struct GetRulesTable_req        request;
407         struct mapi_session             *session;
408         NTSTATUS                        status;
409         enum MAPISTATUS                 retval;
410         uint32_t                        size;
411         TALLOC_CTX                      *mem_ctx;
412         uint8_t                         logon_id;
413
414         /* Sanity check */
415         OPENCHANGE_RETVAL_IF(!obj_folder, MAPI_E_INVALID_PARAMETER, NULL);
416         OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
417
418         session = mapi_object_get_session(obj_folder);
419         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
420
421         if ((retval = mapi_object_get_logon_id(obj_folder, &logon_id)) != MAPI_E_SUCCESS)
422                 return retval;
423
424         mem_ctx = talloc_named(session, 0, "GetRulesTable");
425         size = 0;
426
427         /* Fill the GetRulesTable operation */
428         request.handle_idx = 0x1;
429         size += sizeof (uint8_t);
430
431         request.TableFlags = TableFlags;
432         size += sizeof (uint8_t);
433
434         /* Fill the MAPI_REQ request */
435         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
436         mapi_req->opnum = op_MAPI_GetRulesTable;
437         mapi_req->logon_id = logon_id;
438         mapi_req->handle_idx = 0;
439         mapi_req->u.mapi_GetRulesTable = request;
440         size += 5;
441
442         /* Fill the mapi_request structure */
443         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
444         mapi_request->mapi_len = size + sizeof (uint32_t) * 2;
445         mapi_request->length = size;
446         mapi_request->mapi_req = mapi_req;
447         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2);
448         mapi_request->handles[0] = mapi_object_get_handle(obj_folder);
449         mapi_request->handles[1] = 0xffffffff;
450
451         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
452         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
453         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
454         retval = mapi_response->mapi_repl->error_code;
455         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
456
457         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
458
459         /* set object session, handle and logon_id */
460         mapi_object_set_session(obj_table, session);
461         mapi_object_set_handle(obj_table, mapi_response->handles[1]);
462         mapi_object_set_logon_id(obj_table, logon_id);
463
464         /* new table */
465         mapi_object_table_init((TALLOC_CTX *)session, obj_table);
466
467         talloc_free(mapi_response);
468         talloc_free(mem_ctx);
469
470         return MAPI_E_SUCCESS;
471 }
472
473
474
475 /**
476    \details Modify the entries of a permission table
477
478    This function takes a pointer to a table object, a list of entries
479    to modify and alter the permission table of its associated
480    container. This function can be used to add, modify or remove
481    permissions.
482
483    \param obj_table the table containing the container's permissions
484    \param flags any special flags to use
485    \param permsdata the list of permissions table entries to modify
486
487    Possible values for flags:
488
489    - 0x02 for IncludeFreeBusy.  This should be set when modifying permissions
490    on the Calendar folder when using Exchange 2007 and later. It should not
491    be set in other situations.
492    - 0x01 for ReplaceRows. This means "remove all current permissions and use
493    this set instead", so the permsdata must consist of ROW_ADD operations.
494
495    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
496
497    \note Developers may also call GetLastError() to retrieve the last
498    MAPI error code. Possible MAPI error codes are:
499    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
500    - MAPI_E_CALL_FAILED: A network problem was encountered during the
501      transaction
502
503    \sa GetPermissionsTable, AddUserPermission, ModifyUserPermission,
504    RemoveUserPermission
505  */
506 _PUBLIC_ enum MAPISTATUS ModifyPermissions(mapi_object_t *obj_table, uint8_t flags, struct mapi_PermissionsData *permsdata)
507 {
508         struct mapi_request             *mapi_request;
509         struct mapi_response            *mapi_response;
510         struct EcDoRpc_MAPI_REQ         *mapi_req;
511         struct ModifyPermissions_req    request;
512         struct mapi_session             *session;
513         NTSTATUS                        status;
514         enum MAPISTATUS                 retval;
515         uint32_t                        size = 0;
516         TALLOC_CTX                      *mem_ctx;
517         uint32_t                        i, j;
518         uint8_t                         logon_id;
519
520         /* Sanity checks */
521         OPENCHANGE_RETVAL_IF(!obj_table, MAPI_E_INVALID_PARAMETER, NULL);
522         OPENCHANGE_RETVAL_IF(!permsdata, MAPI_E_INVALID_PARAMETER, NULL);
523
524         session = mapi_object_get_session(obj_table);
525         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
526
527         if ((retval = mapi_object_get_logon_id(obj_table, &logon_id)) != MAPI_E_SUCCESS)
528                 return retval;
529
530         mem_ctx = talloc_named(session, 0, "ModifyPermissions");
531
532         /* Fill the ModifyPermissions operation */
533         request.rowList = *permsdata;
534         request.rowList.ModifyFlags = flags;
535         size += sizeof (uint8_t) + sizeof (uint16_t);
536
537         for (i = 0; i < permsdata->ModifyCount; i++) {
538                 size += sizeof (uint8_t);
539                         for (j = 0; j < permsdata->PermissionsData[i].lpProps.cValues; j++) {
540                                 size += get_mapi_property_size(&(permsdata->PermissionsData[i].lpProps.lpProps[j]));
541                                 size += sizeof (uint32_t);
542                         }
543         size += sizeof (uint16_t);
544         }
545
546         /* Fill the MAPI_REQ request */
547         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
548         mapi_req->opnum = op_MAPI_ModifyPermissions;
549         mapi_req->logon_id = logon_id;
550         mapi_req->handle_idx= 0;
551         mapi_req->u.mapi_ModifyPermissions = request;
552         size += 5;
553
554         /* Fill the mapi_request structure */
555         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
556         mapi_request->mapi_len = size + sizeof (uint32_t);
557         mapi_request->length = size;
558         mapi_request->mapi_req = mapi_req;
559         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
560         mapi_request->handles[0] = mapi_object_get_handle(obj_table);
561
562         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
563         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
564         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
565         retval = mapi_response->mapi_repl->error_code;
566         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
567
568         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
569
570         talloc_free(mapi_response);
571         talloc_free(mem_ctx);
572         
573         return MAPI_E_SUCCESS;
574 }
575
576 /**
577    \details Establishes search criteria for the container
578
579    \param obj_container the object we apply search criteria to
580    \param res pointer to a mapi_SRestriction structure defining the
581    search criteria
582    \param SearchFlags bitmask of flags that controls how the search
583    is performed
584    \param lpContainerList pointer to a list of identifiers
585    representing containers to be included in the search
586
587    SearchFlags can take the following values:
588
589    - BACKGROUND_SEARCH: Search run at normal priority relative to
590      other searches. This flag is mutually exclusive with the
591      FOREGROUND_SEARCH one.
592    - FOREGROUND_SEARCH: Search run at high priority relative to other
593      searches. This flag is mutually exclusive with the
594      BACKGROUND_SEARCH one.
595    - RECURSIVE_SEARCH: The search should include the containers
596      specified in the lpContainerList parameter and all of their child
597      container. This flag is mutually exclusive with the
598      SHALLOW_SEARCH one.
599    - RESTART_SEARCH: The search should be initiated, if this is the
600      first call to SetSearchCriteria, or restarted, if the search is
601      inactive. This flag is mutually exclusive with the STOP_SEARCH
602      flag.
603    - SHALLOW_SEARCH: The search should only look in the containers
604      specified in the lpContainerList parameter for matching
605      entries. This flag is mutually exclusive with the
606      RECURSIVE_SEARCH one.
607    - STOP_SEARCH: The search should be aborted. This flag is mutually
608      exclusive with the RESTART_SEARCH one.
609
610    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
611
612    \note Developers may also call GetLastError() to retrieve the last
613    MAPI error code. Possible MAPI error codes are:
614    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
615    - MAPI_E_INVALID_PARAMETER: One or more parameters were invalid (usually null pointer)
616    - MAPI_E_CALL_FAILED: A network problem was encountered during the
617      transaction
618      
619    \sa GetSearchCriteria
620  */
621 _PUBLIC_ enum MAPISTATUS SetSearchCriteria(mapi_object_t *obj_container, 
622                                            struct mapi_SRestriction *res, 
623                                            uint32_t SearchFlags,
624                                            mapi_id_array_t *lpContainerList)
625 {
626         struct mapi_request             *mapi_request;
627         struct mapi_response            *mapi_response;
628         struct EcDoRpc_MAPI_REQ         *mapi_req;
629         struct SetSearchCriteria_req    request;
630         struct mapi_session             *session;
631         NTSTATUS                        status;
632         enum MAPISTATUS                 retval;
633         uint32_t                        size;
634         TALLOC_CTX                      *mem_ctx;
635         uint8_t                         logon_id;
636
637         /* Sanity checks */
638         OPENCHANGE_RETVAL_IF(!obj_container, MAPI_E_INVALID_PARAMETER, NULL);
639         OPENCHANGE_RETVAL_IF(!res, MAPI_E_INVALID_PARAMETER, NULL);
640
641         session = mapi_object_get_session(obj_container);
642         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
643
644         if ((retval = mapi_object_get_logon_id(obj_container, &logon_id)) != MAPI_E_SUCCESS)
645                 return retval;
646
647         mem_ctx = talloc_named(session, 0, "SetSearchCriteria");
648         size = 0;
649
650         /* Fill the SetSearchCriteria operation */
651         request.res = *res;
652         size += get_mapi_SRestriction_size(res);
653         if (lpContainerList != NULL) {
654                 request.FolderIdCount = lpContainerList->count;
655                 size += sizeof (uint16_t);
656
657                 mapi_id_array_get(mem_ctx, lpContainerList, &request.FolderIds);
658                 size += lpContainerList->count * sizeof (uint64_t);
659         } else {
660                 request.FolderIdCount = 0;
661                 size += sizeof (uint16_t);
662                 request.FolderIds = NULL;
663         }
664         request.SearchFlags = SearchFlags;
665         size += sizeof (uint32_t);
666
667         /* add subcontext size */
668         size += sizeof (uint16_t);
669
670         /* Fill the MAPI_REQ request */
671         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
672         mapi_req->opnum = op_MAPI_SetSearchCriteria;
673         mapi_req->logon_id = logon_id;
674         mapi_req->handle_idx = 0;
675         mapi_req->u.mapi_SetSearchCriteria = request;
676         size += 5;
677
678         /* Fill the mapi_request structure */
679         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
680         mapi_request->mapi_len = size + sizeof (uint32_t);
681         mapi_request->length = size;
682         mapi_request->mapi_req = mapi_req;
683         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
684         mapi_request->handles[0] = mapi_object_get_handle(obj_container);
685
686         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
687         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
688         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
689         retval = mapi_response->mapi_repl->error_code;
690         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
691
692         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
693
694         talloc_free(mapi_response);
695         talloc_free(mem_ctx);
696
697         return MAPI_E_SUCCESS;
698 }
699
700
701 /**
702    \details Obtains the search criteria for a container
703
704    \param obj_container the object we retrieve search criteria from
705    \param res pointer to a mapi_SRestriction structure defining the
706    search criteria 
707    \param SearchFlags bitmask of flags that controls how the search
708    is performed
709    \param FolderIdCount number of FolderIds entries
710    \param FolderIds pointer to a list of identifiers
711    representing containers included in the search
712
713    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
714
715    \note Developers may also call GetLastError() to retrieve the last
716    MAPI error code. Possible MAPI error codes are:
717    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
718    - MAPI_E_CALL_FAILED: A network problem was encountered during the
719      transaction
720      
721    \sa SetSearchCriteria
722  */
723 _PUBLIC_ enum MAPISTATUS GetSearchCriteria(mapi_object_t *obj_container,
724                                            struct mapi_SRestriction *res,
725                                            uint32_t *SearchFlags,
726                                            uint16_t *FolderIdCount,
727                                            uint64_t **FolderIds)
728 {
729         struct mapi_request             *mapi_request;
730         struct mapi_response            *mapi_response;
731         struct EcDoRpc_MAPI_REQ         *mapi_req;
732         struct GetSearchCriteria_req    request;
733         struct GetSearchCriteria_repl   *reply;
734         struct mapi_session             *session;
735         NTSTATUS                        status;
736         enum MAPISTATUS                 retval;
737         uint32_t                        size;
738         TALLOC_CTX                      *mem_ctx;
739         uint8_t                         logon_id;
740
741         /* Sanity checks */
742         OPENCHANGE_RETVAL_IF(!obj_container, MAPI_E_INVALID_PARAMETER, NULL);
743         OPENCHANGE_RETVAL_IF(!SearchFlags, MAPI_E_INVALID_PARAMETER, NULL);
744         OPENCHANGE_RETVAL_IF(!FolderIdCount, MAPI_E_INVALID_PARAMETER, NULL);
745         OPENCHANGE_RETVAL_IF(!FolderIds, MAPI_E_INVALID_PARAMETER, NULL);
746
747         session = mapi_object_get_session(obj_container);
748         OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL);
749
750         if ((retval = mapi_object_get_logon_id(obj_container, &logon_id)) != MAPI_E_SUCCESS)
751                 return retval;
752
753         mem_ctx = talloc_named(session, 0, "GetSearchCriteria");
754         size = 0;
755
756         /* Fill the GetSearchCriteria operation */
757         request.UseUnicode = 0x1;
758         request.IncludeRestriction = 0x1;
759         request.IncludeFolders = 0x1;
760         size += 3 * sizeof (uint8_t);
761
762         /* Fill the MAPI_REQ request */
763         mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ);
764         mapi_req->opnum = op_MAPI_GetSearchCriteria;
765         mapi_req->logon_id = logon_id;
766         mapi_req->handle_idx = 0;
767         mapi_req->u.mapi_GetSearchCriteria = request;
768         size += 5;
769
770         /* Fill the mapi_request structure */
771         mapi_request = talloc_zero(mem_ctx, struct mapi_request);
772         mapi_request->mapi_len = size + sizeof (uint32_t);
773         mapi_request->length = size;
774         mapi_request->mapi_req = mapi_req;
775         mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1);
776         mapi_request->handles[0] = mapi_object_get_handle(obj_container);
777
778         status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response);
779         OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx);
780         OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx);
781         retval = mapi_response->mapi_repl->error_code;
782         OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
783
784         OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response);
785
786         reply = &mapi_response->mapi_repl->u.mapi_GetSearchCriteria;
787
788         res = &reply->RestrictionData;
789         *FolderIdCount = reply->FolderIdCount;
790         *FolderIds = talloc_steal((TALLOC_CTX *)session, reply->FolderIds);
791         *SearchFlags = reply->SearchFlags;
792
793         talloc_free(mapi_response);
794         talloc_free(mem_ctx);
795
796         return MAPI_E_SUCCESS;
797 }