Merge r3881,3893,3894,3895,3907,3908,3910,3911,3912,3913,3915,3916,3917,3919,3920...
[jelmer/openchange.git] / libmapi / property.c
1 /*
2    OpenChange MAPI implementation.
3
4    Copyright (C) Julien Kerihuel 2005 - 2011.
5    Copyright (C) Gregory Schiro 2006
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "libmapi/libmapi.h"
22 #include "libmapi/libmapi_private.h"
23 #include <gen_ndr/ndr_property.h>
24 #include <param.h>
25
26 /**
27    \file property.c
28
29    \brief Functions for manipulating MAPI properties
30  */
31
32
33 /**
34   \details Create a property tag array
35   
36   \param mem_ctx talloc memory context to use for allocation
37   \param PropCount the number of properties in the array
38   
39   The varargs (the third and subsequent arguments) are the property
40   tags to make up the array. So the normal way to use this to create
41   an array of two tags is like:
42   \code
43   struct SPropTagArray *array
44   array = set_SPropTagArray(mem_ctx, 2, PR_ENTRYID, PR_DISPLAY_NAME);
45   \endcode
46 */
47 _PUBLIC_ struct SPropTagArray *set_SPropTagArray(TALLOC_CTX *mem_ctx, 
48                                                  uint32_t PropCount, ...)
49 {
50         struct SPropTagArray    *SPropTagArray;
51         va_list                 ap;
52         uint32_t                i;
53         uint32_t                *aulPropTag;
54
55         aulPropTag = talloc_array(mem_ctx, uint32_t, PropCount);
56
57         va_start(ap, PropCount);
58         for (i = 0; i < PropCount; i++) {
59                 aulPropTag[i] = va_arg(ap, int);
60         }
61         va_end(ap);
62
63         SPropTagArray = talloc(mem_ctx, struct SPropTagArray);
64         SPropTagArray->aulPropTag = (enum MAPITAGS *) aulPropTag;
65         SPropTagArray->cValues = PropCount;
66         return SPropTagArray;
67 }
68
69 /**
70    \details Add a property tag to an existing properties array
71
72    \param mem_ctx talloc memory context to use for allocation
73    \param SPropTagArray existing properties array to add to
74    \param aulPropTag the property tag to add
75
76    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
77
78    \note Possible MAPI error codes are:
79    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
80    - MAPI_E_INVALID_PARAMETER: SPropTagArray parameter is not correctly set
81 */
82 _PUBLIC_ enum MAPISTATUS SPropTagArray_add(TALLOC_CTX *mem_ctx, 
83                                            struct SPropTagArray *SPropTagArray, 
84                                            enum MAPITAGS aulPropTag)
85 {
86         /* Sanity checks */
87         OPENCHANGE_RETVAL_IF(!mem_ctx, MAPI_E_NOT_INITIALIZED, NULL);
88         OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
89         OPENCHANGE_RETVAL_IF(!SPropTagArray->aulPropTag, MAPI_E_INVALID_PARAMETER, NULL);
90
91         SPropTagArray->cValues += 1;
92         SPropTagArray->aulPropTag = (enum MAPITAGS *) talloc_realloc(mem_ctx, SPropTagArray->aulPropTag,
93                                                                      uint32_t, SPropTagArray->cValues + 1);
94         SPropTagArray->aulPropTag[SPropTagArray->cValues - 1] = aulPropTag;
95         SPropTagArray->aulPropTag[SPropTagArray->cValues] = (enum MAPITAGS) 0;
96
97         return MAPI_E_SUCCESS;
98 }
99
100 /**
101    \details Delete a property tag from an existing properties array
102
103    \param mem_ctx talloc memory context to use for allocation
104    \param SPropTagArray existing properties array to remove from
105    \param aulPropTag the property tag to remove
106
107    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
108
109    \note Possible MAPI error codes are:
110    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
111    - MAPI_E_INVALID_PARAMETER: SPropTagArray parameter is not correctly set
112 */
113 _PUBLIC_ enum MAPISTATUS SPropTagArray_delete(TALLOC_CTX *mem_ctx,
114                                               struct SPropTagArray *SPropTagArray,
115                                               uint32_t aulPropTag)
116 {
117         uint32_t i, removed = 0;
118
119         /* Sanity checks */
120         OPENCHANGE_RETVAL_IF(!mem_ctx, MAPI_E_NOT_INITIALIZED, NULL);
121         OPENCHANGE_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
122         OPENCHANGE_RETVAL_IF(!SPropTagArray->cValues, MAPI_E_INVALID_PARAMETER, NULL);
123
124         for (i = 0; i < SPropTagArray->cValues; i++) {
125                 if (SPropTagArray->aulPropTag[i] == aulPropTag) {
126                         removed++;
127                 }
128                 else if (removed > 0) {
129                         SPropTagArray->aulPropTag[i-removed] = SPropTagArray->aulPropTag[i];
130                 }
131         }
132
133         SPropTagArray->cValues -= removed;
134         SPropTagArray->aulPropTag = (enum MAPITAGS *) talloc_realloc(mem_ctx, SPropTagArray->aulPropTag,
135                                                                      uint32_t, SPropTagArray->cValues + 1);
136         SPropTagArray->aulPropTag[SPropTagArray->cValues] = (enum MAPITAGS) 0;
137
138         return MAPI_E_SUCCESS;
139 }
140
141 /**
142    \details Return the index of a property tag in an existing properties array
143
144    \param SPropTagArray existing properties array to remove from
145    \param aulPropTag the property tag to find
146    \param propIdx the index of the found property (undefined when MAPI_E_NOT_FOUND is returned)
147
148    \return MAPI_E_SUCCESS on success, otherwise MAPI error.
149
150    \note Possible MAPI error codes are:
151    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
152    - MAPI_E_INVALID_PARAMETER: SPropTagArray parameter is not correctly set
153 */
154 _PUBLIC_ enum MAPISTATUS SPropTagArray_find(struct SPropTagArray SPropTagArray,
155                                             enum MAPITAGS aulPropTag, 
156                                             uint32_t *propIdx)
157 {
158         uint32_t i;
159
160         /* Sanity checks */
161         OPENCHANGE_RETVAL_IF(!propIdx, MAPI_E_INVALID_PARAMETER, NULL);
162
163         for (i = 0; i < SPropTagArray.cValues; i++) {
164                 if (SPropTagArray.aulPropTag[i] == aulPropTag) {
165                         *propIdx = i;
166                         return MAPI_E_SUCCESS;
167                 }
168         }
169
170         return MAPI_E_NOT_FOUND;
171 }
172
173 _PUBLIC_ const void *get_SPropValue(struct SPropValue *lpProps, 
174                                     enum MAPITAGS ulPropTag)
175 {
176         uint32_t        i;
177
178         /* Sanity checks */
179         if (!lpProps) return NULL;
180
181         for (i = 0; lpProps[i].ulPropTag; i++) {
182                 if (ulPropTag == lpProps[i].ulPropTag) {
183                         return get_SPropValue_data(&lpProps[i]);
184                 }
185         }
186         return NULL;
187 }
188
189 _PUBLIC_ struct SPropValue *get_SPropValue_SRowSet(struct SRowSet *RowSet, 
190                                                    uint32_t ulPropTag)
191 {
192         uint32_t        i;
193         uint32_t        j;
194
195         /* Sanity Checks */
196         if (!RowSet) return NULL;
197
198         for (i = 0; i != RowSet->cRows; i++) {
199                 for (j = 0; j < RowSet->aRow[i].cValues; j++) {
200                         if (ulPropTag == RowSet->aRow[i].lpProps[j].ulPropTag) {
201                                 return (&RowSet->aRow[i].lpProps[j]);
202                         }
203                 }
204         }
205
206         return NULL;
207 }
208
209 _PUBLIC_ const void *get_SPropValue_SRowSet_data(struct SRowSet *RowSet,
210                                                  uint32_t ulPropTag)
211 {
212         struct SPropValue *lpProp;
213
214         lpProp = get_SPropValue_SRowSet(RowSet, ulPropTag);
215         return get_SPropValue(lpProp, ulPropTag);
216 }
217
218 _PUBLIC_ enum MAPISTATUS set_default_error_SPropValue_SRow(struct SRow *aRow, enum MAPITAGS ulPropTag, void *data)
219 {
220         uint32_t        i;
221
222         for (i = 0; i < aRow->cValues; i++) {
223                 if ((ulPropTag & 0xFFFF0000) == (aRow->lpProps[i].ulPropTag & 0xFFFF0000) &&
224                     (aRow->lpProps[i].ulPropTag & 0xFFFF) == 0xA) {
225                         set_SPropValue_proptag(&(aRow->lpProps[i]), ulPropTag, data);
226                         return MAPI_E_SUCCESS;
227                 }
228         }
229         return MAPI_E_NOT_FOUND;
230 }
231
232 _PUBLIC_ struct SPropValue *get_SPropValue_SRow(struct SRow *aRow,
233                                                 uint32_t ulPropTag)
234 {
235         uint32_t        i;
236
237         if ( ! aRow) {
238                 return NULL;
239         }
240
241         for (i = 0; i < aRow->cValues; i++) {
242                 if (ulPropTag == aRow->lpProps[i].ulPropTag) {
243                         return (&aRow->lpProps[i]);
244                 }
245         }
246
247         return NULL;
248 }
249
250 _PUBLIC_ const void *get_SPropValue_SRow_data(struct SRow *aRow,
251                                               uint32_t ulPropTag)
252 {
253         struct SPropValue *lpProp;
254
255         lpProp = get_SPropValue_SRow(aRow, ulPropTag);
256         return get_SPropValue(lpProp, ulPropTag);
257 }
258
259 /*
260   Create a MAPITAGS array from a SRow entry
261  */
262
263 enum MAPITAGS *get_MAPITAGS_SRow(TALLOC_CTX *mem_ctx, 
264                                  struct SRow *aRow, 
265                                  uint32_t *actual_count)
266 {
267         enum MAPITAGS   *mapitags;
268         uint32_t        count, idx;
269
270         mapitags = talloc_array(mem_ctx, enum MAPITAGS, aRow->cValues + 1);
271
272         for (count = 0, idx=0; count < aRow->cValues; count++) {
273                 if ((aRow->lpProps[count].ulPropTag & 0xFFFF) != PT_ERROR) {
274                         mapitags[idx] = aRow->lpProps[count].ulPropTag;
275                         idx++;
276                 }
277         }
278         mapitags[idx] = (enum MAPITAGS) 0;
279         *actual_count = idx;
280
281         return mapitags;
282 }
283
284 /*
285   Remove MAPITAGS entries from a MAPITAGS array
286 */
287
288 uint32_t MAPITAGS_delete_entries(enum MAPITAGS *mapitags, uint32_t final_count, uint32_t PropCount, ...)
289 {
290         va_list                 ap;
291         uint32_t                i,j;
292         uint32_t                aulPropTag;
293         uint32_t                count = 0;
294         
295         va_start(ap, PropCount);
296         for (i = 0; i != PropCount; i++) {
297                 aulPropTag = va_arg(ap, uint32_t);
298                 for (count = 0; mapitags[count]; count++) {
299                         if (aulPropTag == (uint32_t)mapitags[count]) {
300                                 final_count -= 1;
301                                 for (j = count; mapitags[j]; j++) {
302                                   mapitags[j] = (mapitags[j+1]) ? mapitags[j+1] : (enum MAPITAGS) 0;
303                                 }
304                         }
305                 }
306         }
307         va_end(ap);
308
309         return final_count;
310 }
311
312 _PUBLIC_ const void *find_SPropValue_data(struct SRow *aRow, uint32_t mapitag)
313 {
314         uint32_t i;
315
316         if (!aRow) {
317                 return NULL;
318         }
319
320         for (i = 0; i < aRow->cValues; i++) {
321                 if (aRow->lpProps[i].ulPropTag == mapitag) {
322                         return get_SPropValue_data(&(aRow->lpProps[i]));
323                 }
324         }
325         return NULL;
326 }
327
328 _PUBLIC_ const void *find_mapi_SPropValue_data(
329                                         struct mapi_SPropValue_array *properties, uint32_t mapitag)
330 {
331         uint32_t i;
332
333         if ( ! properties) {
334                 return NULL;
335         }
336
337         for (i = 0; i < properties->cValues; i++) {
338                 if (properties->lpProps[i].ulPropTag == mapitag) {
339                         return get_mapi_SPropValue_data(&properties->lpProps[i]);
340                 }
341         }
342         return NULL;
343 }
344
345 _PUBLIC_ const void *get_mapi_SPropValue_data(struct mapi_SPropValue *lpProp)
346 {
347         if ( ! lpProp) {
348                 return NULL;
349         }
350         if (lpProp->ulPropTag == 0) {
351                 return NULL;
352         }
353         switch(lpProp->ulPropTag & 0xFFFF) {
354         case PT_BOOLEAN:
355                 return (const void *)(uint8_t *)&lpProp->value.b;
356         case PT_I2: /* Equivalent to PT_SHORT */
357                 return (const void *)(uint16_t *)&lpProp->value.i;
358         case PT_LONG: /* Equivalent to PT_I4 */
359                 return (const void *)&lpProp->value.l;
360         case PT_DOUBLE:
361                 return (const void *)&lpProp->value.dbl;
362         case PT_I8:
363                 return (const void *)&lpProp->value.d;
364         case PT_SYSTIME:
365                 return (const void *)(struct FILETIME *)&lpProp->value.ft;
366         case PT_ERROR:
367                 return (const void *)&lpProp->value.err;
368         case PT_STRING8:
369                 return (const void *)lpProp->value.lpszA;
370         case PT_UNICODE:
371                 return (const void *)lpProp->value.lpszW;
372         case PT_BINARY:
373                 return (const void *)(struct SBinary_short *)&lpProp->value.bin;
374         case PT_MV_LONG:
375                 return (const void *)(struct mapi_MV_LONG_STRUCT *)&lpProp->value.MVl;
376         case PT_MV_STRING8:
377                 return (const void *)(struct mapi_SLPSTRArray *)&lpProp->value.MVszA;
378         case PT_MV_UNICODE:
379                 return (const void *)(struct mapi_SLPSTRArrayW *)&lpProp->value.MVszW;
380         case PT_MV_BINARY:
381                 return (const void *)(struct mapi_SBinaryArray *)&lpProp->value.MVbin;
382         default:
383                 return NULL;
384         }
385 }
386
387 _PUBLIC_ const void *get_SPropValue_data(struct SPropValue *lpProps)
388 {
389         if (lpProps->ulPropTag == 0) {
390                 return NULL;
391         }
392
393         switch(lpProps->ulPropTag & 0xFFFF) {
394         case PT_SHORT:
395                 return (const void *)&lpProps->value.i;
396         case PT_BOOLEAN:
397                 return (const void *)&lpProps->value.b;
398         case PT_I8:
399                 return (const void *)&lpProps->value.d;
400         case PT_STRING8:
401                 return (const void *)lpProps->value.lpszA;
402         case PT_UNICODE:
403                 return (const void *)lpProps->value.lpszW;
404         case PT_SYSTIME:
405                 return (const void *)(struct FILETIME *)&lpProps->value.ft;
406         case PT_ERROR:
407                 return (const void *)&lpProps->value.err;
408         case PT_LONG:
409                 return (const void *)&lpProps->value.l;
410         case PT_DOUBLE:
411                 return (const void *)&lpProps->value.dbl;
412         case PT_CLSID:
413                 return (const void *)lpProps->value.lpguid;
414         case PT_BINARY:
415         case PT_SVREID:
416                 return (const void *)&lpProps->value.bin;
417         case PT_OBJECT:
418                 return (const void *)&lpProps->value.object;
419         case PT_MV_SHORT:
420                 return (const void *)(struct ShortArray_r *)&lpProps->value.MVi;
421         case PT_MV_LONG:
422                 return (const void *)(struct LongArray_r *)&lpProps->value.MVl;
423         case PT_MV_STRING8:
424                 return (const void *)(struct StringArray_r *)&lpProps->value.MVszA;
425         case PT_MV_UNICODE:
426                 return (const void *)(struct StringArrayW_r *)&lpProps->value.MVszW;
427         case PT_MV_BINARY:
428                 return (const void *)(struct BinaryArray_r *)&lpProps->value.MVbin;
429         case PT_MV_SYSTIME:
430                 return (const void *)(struct DateTimeArray_r *)&lpProps->value.MVft;
431         case PT_NULL:
432                 return (const void *)&lpProps->value.null;
433         default:
434                 return NULL;
435         }
436 }
437
438 _PUBLIC_ bool set_SPropValue_proptag(struct SPropValue *lpProps, enum MAPITAGS aulPropTag, const void *data)
439 {
440         lpProps->ulPropTag = aulPropTag;
441         lpProps->dwAlignPad = 0x0;
442
443         return (set_SPropValue(lpProps, data));
444 }
445
446 _PUBLIC_ struct SPropValue *add_SPropValue(TALLOC_CTX *mem_ctx, 
447                                            struct SPropValue *lpProps, 
448                                            uint32_t *cValues, 
449                                            enum MAPITAGS aulPropTag, 
450                                            const void * data)
451 {
452         lpProps = talloc_realloc(mem_ctx, lpProps, struct SPropValue, *cValues + 2);
453
454         set_SPropValue_proptag(&lpProps[*cValues], aulPropTag, data);
455         *cValues = *cValues + 1;
456
457         return lpProps;
458 }
459
460 _PUBLIC_ bool set_mapi_SPropValue(TALLOC_CTX *mem_ctx, struct mapi_SPropValue *lpProps, const void *data)
461 {
462         if (data == NULL) {
463                 lpProps->ulPropTag = (lpProps->ulPropTag & 0xffff0000) | PT_ERROR;
464                 lpProps->value.err = MAPI_E_NOT_FOUND;
465                 return false;
466         }
467         switch (lpProps->ulPropTag & 0xFFFF) {
468         case PT_SHORT:
469                 lpProps->value.i = *((const uint16_t *)data);
470                 break;
471         case PT_LONG:
472                 lpProps->value.l = *((const uint32_t *)data);
473                 break;
474         case PT_DOUBLE:
475                 lpProps->value.dbl = *((const double *)data);
476                 break;
477         case PT_I8:
478                 lpProps->value.d = *((const uint64_t *)data);
479                 break;
480         case PT_BOOLEAN:
481                 lpProps->value.b = *((const uint8_t *)data);
482                 break;
483         case PT_STRING8:
484                 lpProps->value.lpszA = (const char *) data;
485                 break;
486         case PT_BINARY:
487         {
488                 struct Binary_r *bin;
489
490                 bin = (struct Binary_r *)data;
491                 lpProps->value.bin.cb = (uint16_t)bin->cb;
492                 lpProps->value.bin.lpb = (void *)bin->lpb;
493         }
494                 break;
495         case PT_UNICODE: 
496                 lpProps->value.lpszW = (const char *) data;
497                 break;
498         case PT_CLSID:
499                 lpProps->value.lpguid = *((struct GUID *) data);
500                 break;
501         case PT_SYSTIME:
502                 lpProps->value.ft = *((const struct FILETIME *) data);
503                 break;
504         case PT_ERROR:
505                 lpProps->value.err = *((const uint32_t *)data);
506                 break;
507         case PT_MV_LONG:
508                 lpProps->value.MVl = *((const struct mapi_MV_LONG_STRUCT *)data);
509                 break;
510         case PT_MV_STRING8:
511                 lpProps->value.MVszA = *((const struct mapi_SLPSTRArray *)data);
512                 break;
513         case PT_MV_BINARY:
514                 lpProps->value.MVbin = *((const struct mapi_SBinaryArray *)data);
515                 break;
516         case PT_MV_CLSID:
517                 lpProps->value.MVguid = *((const struct mapi_SGuidArray *)data);
518                 break;
519         case PT_MV_UNICODE:
520                 lpProps->value.MVszW = *((const struct mapi_SLPSTRArrayW *)data);
521                 break;
522         default:
523                 lpProps->ulPropTag = (lpProps->ulPropTag & 0xffff0000) | PT_ERROR;
524                 lpProps->value.err = MAPI_E_NOT_FOUND;
525
526                 return false;
527         }
528
529         return true;
530 }
531
532 _PUBLIC_ bool set_mapi_SPropValue_proptag(TALLOC_CTX *mem_ctx, struct mapi_SPropValue *lpProps, uint32_t aulPropTag, const void *data)
533 {
534         lpProps->ulPropTag = aulPropTag;
535
536         return (set_mapi_SPropValue(mem_ctx, lpProps, data));
537 }
538
539 _PUBLIC_ struct mapi_SPropValue *add_mapi_SPropValue(TALLOC_CTX *mem_ctx, struct mapi_SPropValue *lpProps, uint16_t *cValues, uint32_t aulPropTag, const void *data)
540 {
541         lpProps = talloc_realloc(mem_ctx, lpProps, struct mapi_SPropValue, *cValues + 2);
542         DEBUG(0, ("%d: setting value for 0x%.8x\n", *cValues, aulPropTag));
543         set_mapi_SPropValue_proptag(mem_ctx, &lpProps[*cValues], aulPropTag, data);
544         *cValues = *cValues + 1;
545
546         return lpProps;
547 }
548
549 _PUBLIC_ bool set_SPropValue(struct SPropValue *lpProps, const void *data)
550 {
551         if (data == NULL) {
552                 lpProps->ulPropTag = (lpProps->ulPropTag & 0xffff0000) | PT_ERROR;
553                 lpProps->value.err = MAPI_E_NOT_FOUND;
554                 return false;
555         }
556         switch (lpProps->ulPropTag & 0xFFFF) {
557         case PT_SHORT:
558                 lpProps->value.i = *((const uint16_t *)data);
559                 break;
560         case PT_LONG:
561                 lpProps->value.l = *((const uint32_t *)data);
562                 break;
563         case PT_DOUBLE:
564                 lpProps->value.dbl = *((const double *)data);
565                 break;
566         case PT_I8:
567                 lpProps->value.d = *((const uint64_t *)data);
568                 break;
569         case PT_BOOLEAN:
570                 lpProps->value.b = *((const uint8_t *)data);
571                 break;
572         case PT_STRING8:
573                 lpProps->value.lpszA = (const char *) data;
574                 break;
575         case PT_BINARY:
576         case PT_SVREID:
577                 lpProps->value.bin = *((const struct Binary_r *)data);
578                 break;
579         case PT_UNICODE:
580                 lpProps->value.lpszW = (const char *) data;
581                 break;
582         case PT_CLSID:
583                 lpProps->value.lpguid = (struct FlatUID_r *) data;
584                 break;
585         case PT_SYSTIME:
586                 lpProps->value.ft = *((const struct FILETIME *) data);
587                 break;
588         case PT_ERROR:
589                 lpProps->value.err = *((enum MAPISTATUS *)data);
590                 break;
591         case PT_MV_SHORT:
592                 lpProps->value.MVi = *((const struct ShortArray_r *)data);
593                 break;
594         case PT_MV_LONG:
595                 lpProps->value.MVl = *((const struct LongArray_r *)data);
596                 break;
597         case PT_MV_STRING8:
598                 lpProps->value.MVszA = *((const struct StringArray_r *)data);
599                 break;
600         case PT_MV_BINARY:
601                 lpProps->value.MVbin = *((const struct BinaryArray_r *)data);
602                 break;
603         case PT_MV_CLSID:
604                 lpProps->value.MVguid = *((const struct FlatUIDArray_r *)data);
605                 break;
606         case PT_MV_UNICODE:
607                 lpProps->value.MVszW = *((const struct StringArrayW_r *)data);
608                 break;
609         case PT_MV_SYSTIME:
610                 lpProps->value.MVft = *((const struct DateTimeArray_r *)data);
611                 break;
612         case PT_NULL:
613                 lpProps->value.null = *((const uint32_t *)data);
614                 break;
615         case PT_OBJECT:
616                 lpProps->value.object = *((const uint32_t *)data);
617                 break;
618         default:
619                 lpProps->ulPropTag = (lpProps->ulPropTag & 0xffff0000) | PT_ERROR;
620                 lpProps->value.err = MAPI_E_NOT_FOUND;
621
622                 return false;
623         }
624
625         return true;
626 }
627
628 _PUBLIC_ uint32_t get_mapi_property_size(struct mapi_SPropValue *lpProp)
629 {
630         switch(lpProp->ulPropTag & 0xFFFF) {
631         case PT_BOOLEAN:
632                 return sizeof (uint8_t);
633         case PT_I2:
634                 return sizeof (uint16_t);
635         case PT_LONG:
636         case PT_ERROR:
637                 return sizeof (uint32_t);
638         case PT_DOUBLE:
639                 return sizeof (double);
640         case PT_I8:
641                 return sizeof (uint64_t);
642         case PT_STRING8:
643                 return strlen(lpProp->value.lpszA) + 1;
644         case PT_UNICODE:
645                 return get_utf8_utf16_conv_length(lpProp->value.lpszW);
646         case PT_SYSTIME:
647                 return sizeof (struct FILETIME);
648         case PT_BINARY:
649                 return (lpProp->value.bin.cb + sizeof(uint16_t));
650         }
651         return 0;
652 }
653
654
655 /**
656    \details Convenience function to copy an array of struct SPropValue or a
657    part thereof into another array, by duplicating and properly parenting
658    pointer data. The destination array is considered to be preallocated.
659 */
660 _PUBLIC_ void mapi_copy_spropvalues(TALLOC_CTX *mem_ctx, struct SPropValue *source_values, struct SPropValue *dest_values, uint32_t count)
661 {
662         uint32_t                i;
663         struct SPropValue       *source_value, *dest_value;
664         uint16_t                prop_type;
665
666         for (i = 0; i < count; i++) {
667                 source_value = source_values + i;
668                 dest_value = dest_values + i;
669                 *dest_value = *source_value;
670
671                 prop_type = (source_value->ulPropTag & 0xFFFF);
672                 if ((prop_type & MV_FLAG)) {
673                         DEBUG(5, ("multivalues not handled\n"));
674                         abort();
675                 }
676                 else {
677                         switch(prop_type) {
678                         case PT_STRING8:
679                                 dest_value->value.lpszA = talloc_strdup(mem_ctx, source_value->value.lpszA);
680                                 break;
681                         case PT_UNICODE:
682                                 dest_value->value.lpszW = talloc_strdup(mem_ctx, source_value->value.lpszW);
683                                 break;
684                         case PT_BINARY:
685                                 dest_value->value.bin.cb = source_value->value.bin.cb;
686                                 dest_value->value.bin.lpb = talloc_memdup(mem_ctx, source_value->value.bin.lpb, sizeof(uint8_t) * source_value->value.bin.cb);
687                                 break;
688                         default:
689                                 *dest_value = *source_value;
690                         }
691                 }
692         }
693 }
694
695 /**
696    \details Convenience function to convert a SPropValue structure
697    into a mapi_SPropValue structure and return the associated size.
698
699    \param mem_ctx pointer to the memory context to use for allocation
700    \param mapi_sprop pointer to the MAPI SPropValue structure to copy data to
701    \param sprop pointer to the SPropValue structure to copy data from
702
703    \return size of the converted data on success, otherwise 0
704  */
705 _PUBLIC_ uint32_t cast_mapi_SPropValue(TALLOC_CTX *mem_ctx,
706                                        struct mapi_SPropValue *mapi_sprop, 
707                                        struct SPropValue *sprop)
708 {
709         mapi_sprop->ulPropTag = sprop->ulPropTag;
710
711         switch(sprop->ulPropTag & 0xFFFF) {
712         case PT_BOOLEAN:
713                 mapi_sprop->value.b = sprop->value.b;
714                 return sizeof(uint8_t);
715         case PT_I2:
716                 mapi_sprop->value.i = sprop->value.i;
717                 return sizeof(uint16_t);
718         case PT_LONG:
719                 mapi_sprop->value.l = sprop->value.l;
720                 return sizeof(uint32_t);
721         case PT_DOUBLE:
722                 mapi_sprop->value.dbl = sprop->value.dbl;
723                 return sizeof(double);
724         case PT_I8:
725                 mapi_sprop->value.d = sprop->value.d;
726                 return sizeof(uint64_t);
727         case PT_STRING8:
728                 mapi_sprop->value.lpszA = sprop->value.lpszA;
729                 if (!mapi_sprop->value.lpszA) return 0;
730                 return (strlen(sprop->value.lpszA) + 1);
731         case PT_UNICODE:
732                 mapi_sprop->value.lpszW = sprop->value.lpszW;
733                 if (!mapi_sprop->value.lpszW) return 0;
734                 return (get_utf8_utf16_conv_length(mapi_sprop->value.lpszW));
735         case PT_SYSTIME:
736                 mapi_sprop->value.ft.dwLowDateTime = sprop->value.ft.dwLowDateTime;
737                 mapi_sprop->value.ft.dwHighDateTime = sprop->value.ft.dwHighDateTime;
738                 return (sizeof (struct FILETIME));
739         case PT_BINARY:
740                 mapi_sprop->value.bin.cb = sprop->value.bin.cb;
741                 mapi_sprop->value.bin.lpb = sprop->value.bin.lpb;
742                 return (mapi_sprop->value.bin.cb + sizeof(uint16_t));
743         case PT_ERROR:
744                 mapi_sprop->value.err = sprop->value.err;
745                 return sizeof(uint32_t);
746         case PT_CLSID:
747         {
748                 DATA_BLOB       b;
749
750                 b.data = sprop->value.lpguid->ab;
751                 b.length = 16;
752                 GUID_from_ndr_blob(&b, &mapi_sprop->value.lpguid);
753                 return sizeof(struct GUID);
754         }
755         case PT_SVREID:
756                 mapi_sprop->value.bin.cb = sprop->value.bin.cb;
757                 mapi_sprop->value.bin.lpb = sprop->value.bin.lpb;
758                 return (mapi_sprop->value.bin.cb + sizeof(uint16_t));
759         case PT_MV_STRING8:
760         {
761                 uint32_t        i;
762                 uint32_t        size = 0;
763                 
764                 mapi_sprop->value.MVszA.cValues = sprop->value.MVszA.cValues;
765                 size += 4;
766                 
767                 mapi_sprop->value.MVszA.strings = talloc_array(mem_ctx, struct mapi_LPSTR, 
768                                                                mapi_sprop->value.MVszA.cValues);
769                 for (i = 0; i < mapi_sprop->value.MVszA.cValues; i++) {
770                         mapi_sprop->value.MVszA.strings[i].lppszA = sprop->value.MVszA.lppszA[i];
771                         size += strlen(mapi_sprop->value.MVszA.strings[i].lppszA) + 1;
772                 }
773                 return size;
774         }
775         case PT_MV_UNICODE:
776         {
777                 uint32_t        i;
778                 uint32_t        size = 0;
779
780                 mapi_sprop->value.MVszW.cValues = sprop->value.MVszW.cValues;
781                 size += 4;
782                 
783                 mapi_sprop->value.MVszW.strings = talloc_array(mem_ctx, struct mapi_LPWSTR, 
784                                                                mapi_sprop->value.MVszW.cValues);
785                 for (i = 0; i < mapi_sprop->value.MVszW.cValues; i++) {
786                         mapi_sprop->value.MVszW.strings[i].lppszW = sprop->value.MVszW.lppszW[i];
787                         size += get_utf8_utf16_conv_length(mapi_sprop->value.MVszW.strings[i].lppszW);
788                 }
789                 return size;
790         }
791         case PT_MV_BINARY:
792         {
793                 uint32_t        i;
794                 uint32_t        size = 0;
795                 
796                 mapi_sprop->value.MVbin.cValues = sprop->value.MVbin.cValues;
797                 size += 4;
798
799                 mapi_sprop->value.MVbin.bin = talloc_array(mem_ctx, struct SBinary_short, 
800                                                            mapi_sprop->value.MVbin.cValues);
801                 for (i = 0; i < mapi_sprop->value.MVbin.cValues; i++) {
802                         mapi_sprop->value.MVbin.bin[i].cb = sprop->value.MVbin.lpbin[i].cb;
803                         mapi_sprop->value.MVbin.bin[i].lpb = sprop->value.MVbin.lpbin[i].lpb;
804                         size += sprop->value.MVbin.lpbin[i].cb + sizeof (uint16_t);
805                 }
806                 return size;
807         }
808         case PT_MV_LONG:
809         {
810                 uint32_t i;
811                 
812                 mapi_sprop->value.MVl.cValues = sprop->value.MVl.cValues;
813                 mapi_sprop->value.MVl.lpl = talloc_array (mem_ctx, uint32_t, mapi_sprop->value.MVl.cValues);
814                 for (i = 0; i < mapi_sprop->value.MVl.cValues; i++) {
815                         mapi_sprop->value.MVl.lpl[i] = sprop->value.MVl.lpl[i];
816                 }
817                 return sizeof(mapi_sprop->value.MVl.cValues) + (mapi_sprop->value.MVl.cValues * sizeof (uint32_t));
818         }
819         case PT_MV_CLSID:
820         {
821                 uint32_t i;
822                 DATA_BLOB b;
823
824                 mapi_sprop->value.MVguid.cValues = sprop->value.MVguid.cValues;
825                 mapi_sprop->value.MVguid.lpguid = talloc_array (mem_ctx, struct GUID, mapi_sprop->value.MVguid.cValues);
826                 for (i = 0; i < mapi_sprop->value.MVguid.cValues; i++) {
827                         b.data = sprop->value.MVguid.lpguid[i]->ab;
828                         b.length = 16;
829
830                         GUID_from_ndr_blob(&b, &(mapi_sprop->value.MVguid.lpguid[i]));
831                 }
832                 return sizeof(mapi_sprop->value.MVguid.cValues) + (mapi_sprop->value.MVguid.cValues * sizeof (struct GUID));
833         }
834         default:
835                 printf("unhandled conversion case in cast_mapi_SPropValue(): 0x%x\n", (sprop->ulPropTag & 0xFFFF));
836                 OPENCHANGE_ASSERT();
837         }
838         return 0;
839
840 }
841
842
843 /**
844    \details Convenience function to convert a mapi_SPropValue
845    structure into a SPropValue structure and return the associated
846    size
847
848    \param mem_ctx pointer to the memory context to use for allocation
849    \param mapi_sprop pointer to the MAPI SPropValue structure to copy data from
850    \param sprop pointer to the SPropValue structure to copy data to
851
852    \return size of the converted data on success, otherwise 0
853  */
854 _PUBLIC_ uint32_t cast_SPropValue(TALLOC_CTX *mem_ctx, 
855                                   struct mapi_SPropValue *mapi_sprop, 
856                                   struct SPropValue *sprop)
857 {
858         sprop->ulPropTag = mapi_sprop->ulPropTag;
859
860         switch(sprop->ulPropTag & 0xFFFF) {
861         case PT_BOOLEAN:
862                 sprop->value.b = mapi_sprop->value.b;
863                 return sizeof(uint8_t);
864         case PT_I2:
865                 sprop->value.i = mapi_sprop->value.i;
866                 return sizeof(uint16_t);
867         case PT_LONG:
868                 sprop->value.l = mapi_sprop->value.l;
869                 return sizeof(uint32_t);
870         case PT_DOUBLE:
871                 sprop->value.dbl = mapi_sprop->value.dbl;
872                 return sizeof(double);
873         case PT_I8:
874                 sprop->value.d = mapi_sprop->value.d;
875                 return sizeof(uint64_t);
876         case PT_STRING8:
877                 sprop->value.lpszA = mapi_sprop->value.lpszA;
878                 if (!mapi_sprop->value.lpszA) return 0;
879                 return (strlen(sprop->value.lpszA) + 1);
880         case PT_UNICODE:
881                 sprop->value.lpszW = mapi_sprop->value.lpszW;
882                 if (!sprop->value.lpszW) return 0;
883                 return (get_utf8_utf16_conv_length(mapi_sprop->value.lpszW));
884         case PT_SYSTIME:
885                 sprop->value.ft.dwLowDateTime = mapi_sprop->value.ft.dwLowDateTime;
886                 sprop->value.ft.dwHighDateTime = mapi_sprop->value.ft.dwHighDateTime;
887                 return (sizeof (struct FILETIME));
888         case PT_CLSID:
889         {
890                 DATA_BLOB       b;
891                 
892                 GUID_to_ndr_blob(&(mapi_sprop->value.lpguid), mem_ctx, &b);
893                 sprop->value.lpguid = talloc_zero(mem_ctx, struct FlatUID_r);
894                 sprop->value.lpguid = (struct FlatUID_r *)memcpy(sprop->value.lpguid->ab, b.data, 16);
895                 return (sizeof (struct FlatUID_r));
896         }
897         case PT_SVREID:
898                 sprop->value.bin.cb = mapi_sprop->value.bin.cb;
899                 sprop->value.bin.lpb = mapi_sprop->value.bin.lpb;
900                 return (sprop->value.bin.cb + sizeof (uint16_t));
901         case PT_BINARY:
902                 sprop->value.bin.cb = mapi_sprop->value.bin.cb;
903                 sprop->value.bin.lpb = mapi_sprop->value.bin.lpb;
904                 return (sprop->value.bin.cb + sizeof(uint16_t));
905         case PT_ERROR:
906                 sprop->value.err = (enum MAPISTATUS)mapi_sprop->value.err;
907                 return sizeof(uint32_t);
908         case PT_MV_LONG:
909         {
910                 uint32_t        i;
911                 uint32_t        size = 0;
912
913                 sprop->value.MVl.cValues = mapi_sprop->value.MVl.cValues;
914                 size += 4;
915
916                 sprop->value.MVl.lpl = talloc_array(mem_ctx, uint32_t, sprop->value.MVl.cValues);
917                 for (i = 0; i < sprop->value.MVl.cValues; i++) {
918                         sprop->value.MVl.lpl[i] = mapi_sprop->value.MVl.lpl[i];
919                         size += sizeof (uint32_t);
920                 }
921                 return size;
922         }
923         case PT_MV_STRING8:
924         {
925                 uint32_t        i;
926                 uint32_t        size = 0;
927
928                 sprop->value.MVszA.cValues = mapi_sprop->value.MVszA.cValues;
929                 size += 4;
930
931                 sprop->value.MVszA.lppszA = talloc_array(mem_ctx, const char *, sprop->value.MVszA.cValues);
932                 for (i = 0; i < sprop->value.MVszA.cValues; i++) {
933                         sprop->value.MVszA.lppszA[i] = mapi_sprop->value.MVszA.strings[i].lppszA;
934                         size += strlen(sprop->value.MVszA.lppszA[i]) + 1;
935                 }
936                 return size;
937         }
938         case PT_MV_UNICODE:
939         {
940                 uint32_t        i;
941                 uint32_t        size = 0;
942
943                 sprop->value.MVszW.cValues = mapi_sprop->value.MVszW.cValues;
944                 size += 4;
945
946                 sprop->value.MVszW.lppszW = talloc_array(mem_ctx, const char*, sprop->value.MVszW.cValues);
947                 for (i = 0; i < sprop->value.MVszW.cValues; i++) {
948                         sprop->value.MVszW.lppszW[i] = mapi_sprop->value.MVszW.strings[i].lppszW;
949                         size += get_utf8_utf16_conv_length(sprop->value.MVszW.lppszW[i]);
950                 }
951                 return size;
952         }
953         case PT_MV_CLSID:
954         {
955                 uint32_t        i;
956                 uint32_t        size = 0;
957                 // conceptually we're copying  mapi_SGuidArray over to FlatUIDArray_r
958                 //      typedef struct {
959                 //              uint32          cValues;
960                 //              GUID            lpguid[cValues];
961                 //      } mapi_SGuidArray;
962                 //      typedef [flag(NDR_NOALIGN)] struct {
963                 //              [range(0,100000)]uint32         cValues;
964                 //              [size_is(cValues)] FlatUID_r    **lpguid; 
965                 //      } FlatUIDArray_r;
966                 sprop->value.MVguid.cValues = mapi_sprop->value.MVguid.cValues;
967                 size += sizeof(uint32_t);
968                 
969                 sprop->value.MVguid.lpguid = talloc_array(mem_ctx, struct FlatUID_r*, sprop->value.MVguid.cValues);
970                 for (i = 0; i < sprop->value.MVguid.cValues; ++i) {
971                         DATA_BLOB       b;
972                         
973                         sprop->value.MVguid.lpguid[i] = talloc_zero(mem_ctx, struct FlatUID_r);
974                         GUID_to_ndr_blob(&(mapi_sprop->value.MVguid.lpguid[i]), mem_ctx, &b);
975                         sprop->value.MVguid.lpguid[i] = (struct FlatUID_r *)memcpy(sprop->value.MVguid.lpguid[i]->ab, b.data, sizeof(struct FlatUID_r));
976                         size += (sizeof (struct FlatUID_r));
977                 }
978                 return size;
979         }
980         case PT_MV_BINARY:
981         {
982                 uint32_t        i;
983                 uint32_t        size = 0;
984
985                 sprop->value.MVbin.cValues = mapi_sprop->value.MVbin.cValues;
986                 size += 4;
987
988                 sprop->value.MVbin.lpbin = talloc_array(mem_ctx, struct Binary_r, sprop->value.MVbin.cValues);
989                 for (i = 0; i < sprop->value.MVbin.cValues; i++) {
990                         sprop->value.MVbin.lpbin[i].cb = mapi_sprop->value.MVbin.bin[i].cb;
991                         if (sprop->value.MVbin.lpbin[i].cb) {
992                           sprop->value.MVbin.lpbin[i].lpb = (uint8_t *)talloc_memdup(sprop->value.MVbin.lpbin, 
993                                                                                 mapi_sprop->value.MVbin.bin[i].lpb,
994                                                                                 mapi_sprop->value.MVbin.bin[i].cb);
995                         } else {
996                                 sprop->value.MVbin.lpbin[i].lpb = NULL;
997                         }
998                         size += sizeof (uint32_t);
999                         size += sprop->value.MVbin.lpbin[i].cb;
1000                 }
1001                 return size;
1002         }
1003         default:
1004                 printf("unhandled conversion case in cast_SPropValue(): 0x%x\n", (sprop->ulPropTag & 0xFFFF));
1005                 OPENCHANGE_ASSERT();
1006         }
1007         return 0;
1008 }
1009
1010
1011 /**
1012    \details add a SPropValue structure to a SRow array
1013
1014    \param aRow pointer to the SRow array where spropvalue should be
1015    appended
1016    \param spropvalue reference to the SPropValue structure to add to
1017    aRow
1018
1019    \return MAPI_E_SUCCESS on success, otherwise
1020    MAPI_E_INVALID_PARAMETER.
1021  */
1022 _PUBLIC_ enum MAPISTATUS SRow_addprop(struct SRow *aRow, struct SPropValue spropvalue)
1023 {
1024         TALLOC_CTX              *mem_ctx;
1025         uint32_t                cValues;
1026         struct SPropValue       lpProp;
1027         uint32_t                i;
1028         
1029         /* Sanity checks */
1030         OPENCHANGE_RETVAL_IF(!aRow, MAPI_E_INVALID_PARAMETER, NULL);
1031
1032         mem_ctx = (TALLOC_CTX *) aRow;
1033
1034         /* If the property tag already exist, overwrite its value */
1035         for (i = 0; i < aRow->cValues; i++) {
1036                 if (aRow->lpProps[i].ulPropTag == spropvalue.ulPropTag) {
1037                         aRow->lpProps[i] = spropvalue;
1038                         return MAPI_E_SUCCESS;
1039                 }
1040         }
1041
1042         cValues = aRow->cValues + 1;
1043         aRow->lpProps = talloc_realloc(mem_ctx, aRow->lpProps, struct SPropValue, cValues);
1044         lpProp = aRow->lpProps[cValues-1];
1045         lpProp.ulPropTag = spropvalue.ulPropTag;
1046         lpProp.dwAlignPad = 0;
1047         set_SPropValue(&(lpProp), get_SPropValue_data(&spropvalue));
1048         aRow->cValues = cValues;
1049         aRow->lpProps[cValues - 1] = lpProp;
1050
1051         return MAPI_E_SUCCESS;
1052 }
1053
1054
1055 /**
1056    \details Append a SPropValue structure to given SRowSet
1057
1058    \param mem_ctx pointer to the memory context
1059    \param SRowSet pointer to the SRowSet array to update
1060    \param spropvalue the SPropValue to append within SRowSet
1061
1062    \return 0 on success, otherwise 1
1063  */
1064 _PUBLIC_ uint32_t SRowSet_propcpy(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, struct SPropValue spropvalue)
1065 {
1066         uint32_t                rows;
1067         uint32_t                cValues;
1068         struct SPropValue       lpProp;
1069
1070         /* Sanity checks */
1071         if (!SRowSet) return 1;
1072
1073         for (rows = 0; rows < SRowSet->cRows; rows++) {
1074                 cValues = SRowSet->aRow[rows].cValues + 1;
1075                 SRowSet->aRow[rows].lpProps = talloc_realloc(mem_ctx, SRowSet->aRow[rows].lpProps, struct SPropValue, cValues);
1076                 lpProp = SRowSet->aRow[rows].lpProps[cValues-1];
1077                 lpProp.ulPropTag = spropvalue.ulPropTag;
1078                 lpProp.dwAlignPad = 0;
1079                 set_SPropValue(&(lpProp), (void *)&spropvalue.value);
1080                 SRowSet->aRow[rows].cValues = cValues;
1081                 SRowSet->aRow[rows].lpProps[cValues - 1] = lpProp;
1082         }
1083         return 0;
1084 }
1085
1086 _PUBLIC_ void mapi_SPropValue_array_named(mapi_object_t *obj, 
1087                                           struct mapi_SPropValue_array *props)
1088 {
1089         TALLOC_CTX              *mem_ctx;
1090         enum MAPISTATUS         retval;
1091         struct MAPINAMEID       *nameid;
1092         uint32_t                propID;
1093         uint16_t                count;
1094         uint32_t                i;
1095
1096         mem_ctx = talloc_named(mapi_object_get_session(obj), 0, "mapi_SPropValue_array_named");
1097
1098         for (i = 0; i < props->cValues; i++) {
1099                 if ((props->lpProps[i].ulPropTag & 0xFFFF0000) > 0x80000000) {
1100                         propID = props->lpProps[i].ulPropTag;
1101                         propID = (propID & 0xFFFF0000) | PT_NULL;
1102                         nameid = talloc_zero(mem_ctx, struct MAPINAMEID);
1103                         retval = GetNamesFromIDs(obj, (enum MAPITAGS)propID, &count, &nameid);
1104                         if (retval != MAPI_E_SUCCESS) goto end;
1105
1106                         if (count) {
1107                                 /* Display property given its propID */
1108                                 switch (nameid->ulKind) {
1109                                 case MNID_ID:
1110                                   props->lpProps[i].ulPropTag = (enum MAPITAGS)((nameid->kind.lid << 16) | 
1111                                                                                 ((int)props->lpProps[i].ulPropTag & 0x0000FFFF));
1112                                         break;
1113                                 case MNID_STRING:
1114                                         /* MNID_STRING named properties don't have propIDs */
1115                                         break;
1116                                 }
1117                         }
1118                         talloc_free(nameid);
1119                 }
1120         }
1121 end:
1122         talloc_free(mem_ctx);
1123 }
1124
1125 _PUBLIC_ enum MAPISTATUS get_mapi_SPropValue_array_date_timeval(struct timeval *t,
1126                                                                 struct mapi_SPropValue_array *properties,
1127                                                                 uint32_t mapitag)
1128 {
1129         const struct FILETIME   *filetime;
1130         NTTIME                  time;
1131         
1132         filetime = (const struct FILETIME *) find_mapi_SPropValue_data(properties, mapitag);
1133         if (!filetime) {
1134                 t = NULL;
1135                 return MAPI_E_NOT_FOUND;
1136         }
1137
1138         time = filetime->dwHighDateTime;
1139         time = time << 32;
1140         time |= filetime->dwLowDateTime;
1141         nttime_to_timeval(t, time);
1142         
1143         return MAPI_E_SUCCESS;  
1144 }
1145
1146 _PUBLIC_ enum MAPISTATUS get_mapi_SPropValue_date_timeval(struct timeval *t, 
1147                                                           struct SPropValue lpProp)
1148 {
1149         const struct FILETIME   *filetime;
1150         NTTIME                  time;
1151         
1152         filetime = (const struct FILETIME *) get_SPropValue_data(&lpProp);
1153         if (!filetime) {
1154                 t = NULL;
1155                 return MAPI_E_NOT_FOUND;
1156         }
1157
1158         time = filetime->dwHighDateTime;
1159         time = time << 32;
1160         time |= filetime->dwLowDateTime;
1161         nttime_to_timeval(t, time);
1162         
1163         return MAPI_E_SUCCESS;
1164 }
1165
1166 _PUBLIC_ bool set_SPropValue_proptag_date_timeval(struct SPropValue *lpProps, enum MAPITAGS aulPropTag, const struct timeval *t) 
1167 {
1168         struct FILETIME filetime;
1169         NTTIME          time;
1170         
1171         time = timeval_to_nttime(t);
1172
1173         filetime.dwLowDateTime = (time << 32) >> 32;
1174         filetime.dwHighDateTime = time >> 32;
1175
1176         return set_SPropValue_proptag(lpProps, aulPropTag, &filetime);
1177 }
1178
1179
1180 /**
1181    \details Retrieve a RecurrencePattern structure from a binary blob
1182
1183    \param mem_ctx pointer to the memory context
1184    \param bin pointer to the Binary_r structure with non-mapped
1185    reccurrence data
1186
1187    \return Allocated RecurrencePattern structure on success,
1188    otherwise NULL
1189
1190    \note Developers must free the allocated RecurrencePattern when
1191    finished.
1192  */
1193 _PUBLIC_ struct RecurrencePattern *get_RecurrencePattern(TALLOC_CTX *mem_ctx, 
1194                                                          struct Binary_r *bin)
1195 {
1196         struct RecurrencePattern        *RecurrencePattern = NULL;
1197         struct ndr_pull                 *ndr;
1198         enum ndr_err_code               ndr_err_code;
1199         
1200         /* Sanity checks */
1201         if (!bin) return NULL;
1202         if (!bin->cb) return NULL;
1203         if (!bin->lpb) return NULL;
1204
1205         ndr = talloc_zero(mem_ctx, struct ndr_pull);
1206         ndr->offset = 0;
1207         ndr->data = bin->lpb;
1208         ndr->data_size = bin->cb;
1209
1210         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
1211         RecurrencePattern = talloc_zero(mem_ctx, struct RecurrencePattern);
1212         ndr_err_code = ndr_pull_RecurrencePattern(ndr, NDR_SCALARS, RecurrencePattern);
1213
1214         talloc_free(ndr);
1215
1216         if (ndr_err_code != NDR_ERR_SUCCESS) {
1217                 talloc_free(RecurrencePattern);
1218                 return NULL;
1219         }
1220         
1221         /*Copy DeletedInstanceDates and ModifiedInstanceDates into memory*/ 
1222         RecurrencePattern->DeletedInstanceDates = (uint32_t *) talloc_memdup(mem_ctx, RecurrencePattern->DeletedInstanceDates, 
1223                                                                              sizeof(uint32_t) * RecurrencePattern->DeletedInstanceCount);
1224                                                               
1225         RecurrencePattern->ModifiedInstanceDates = (uint32_t *) talloc_memdup(mem_ctx, RecurrencePattern->ModifiedInstanceDates, 
1226                                                                               sizeof(uint32_t) * RecurrencePattern->ModifiedInstanceCount);
1227         
1228         /*Set reference to parent so arrays get free with RecurrencePattern struct*/
1229         RecurrencePattern->DeletedInstanceDates=talloc_reference(RecurrencePattern, RecurrencePattern->DeletedInstanceDates);
1230         RecurrencePattern->ModifiedInstanceDates=talloc_reference(RecurrencePattern, RecurrencePattern->ModifiedInstanceDates);
1231
1232         return RecurrencePattern;
1233 }
1234
1235 _PUBLIC_ size_t set_RecurrencePattern_size(const struct RecurrencePattern *rp)
1236 {
1237         size_t size = SIZE_DFLT_RECURRENCEPATTERN;
1238
1239         switch (rp->PatternType) {
1240         case PatternType_MonthNth:
1241         case PatternType_HjMonthNth:
1242                 size += sizeof(uint32_t);
1243         case PatternType_Week:
1244         case PatternType_Month:
1245         case PatternType_MonthEnd:
1246         case PatternType_HjMonth:
1247         case PatternType_HjMonthEnd:
1248                 size += sizeof(uint32_t);
1249         case PatternType_Day:
1250                 break;
1251         default:
1252                 DEBUG(0, ("%s: unrecognized pattern type: %d", __PRETTY_FUNCTION__, rp->PatternType));
1253         }
1254
1255         size += rp->DeletedInstanceCount * sizeof(uint32_t);
1256         size += rp->ModifiedInstanceCount * sizeof(uint32_t);
1257
1258         return size;
1259 }
1260
1261 _PUBLIC_ struct Binary_r *set_RecurrencePattern(TALLOC_CTX *mem_ctx, const struct RecurrencePattern *rp)
1262 {
1263         struct Binary_r                 *bin = NULL;
1264         struct ndr_push                 *ndr;
1265         enum ndr_err_code               ndr_err_code;
1266         size_t                          bin_size;
1267         
1268         /* SANITY CHECKS */
1269         if (!rp) return NULL;
1270
1271         bin_size = set_RecurrencePattern_size(rp);
1272         bin = talloc_zero(mem_ctx, struct Binary_r);
1273         bin->cb = bin_size;
1274         bin->lpb = talloc_array(bin, uint8_t, bin_size);
1275
1276         ndr = talloc_zero(mem_ctx, struct ndr_push);
1277         ndr->offset = 0;
1278         ndr->data = bin->lpb;
1279
1280         ndr_err_code = ndr_push_RecurrencePattern(ndr, NDR_SCALARS, rp);
1281
1282         talloc_free(ndr);
1283
1284         if (ndr_err_code != NDR_ERR_SUCCESS) {
1285                 talloc_free(bin);
1286                 return NULL;
1287         }
1288
1289         return bin;
1290 }
1291
1292 _PUBLIC_ struct AppointmentRecurrencePattern *get_AppointmentRecurrencePattern(TALLOC_CTX *mem_ctx, 
1293                                                                                struct Binary_r *bin)
1294 {
1295         struct AppointmentRecurrencePattern             *arp = NULL;
1296         struct ndr_pull                                 *ndr;
1297         enum ndr_err_code                               ndr_err_code;
1298
1299         /* Sanity checks */
1300         if (!bin) return NULL;
1301         if (!bin->cb) return NULL;
1302         if (!bin->lpb) return NULL;
1303
1304         ndr = talloc_zero(mem_ctx, struct ndr_pull);
1305         ndr->offset = 0;
1306         ndr->data = bin->lpb;
1307         ndr->data_size = bin->cb;
1308
1309         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
1310         arp = talloc_zero(mem_ctx, struct AppointmentRecurrencePattern);
1311         ndr_err_code = ndr_pull_AppointmentRecurrencePattern(ndr, NDR_SCALARS, arp);
1312
1313         talloc_free(ndr);
1314
1315         if (ndr_err_code != NDR_ERR_SUCCESS) {
1316                 talloc_free(arp);
1317                 return NULL;
1318         }
1319
1320         /* Copy ExceptionInfo array into memory */ 
1321         arp->ExceptionInfo = (struct ExceptionInfo *) talloc_memdup(mem_ctx,arp->ExceptionInfo, sizeof(struct ExceptionInfo) * arp->ExceptionCount);
1322         
1323         /* Copy DeletedInstanceDates and ModifiedInstanceDates into memory */ 
1324         arp->RecurrencePattern.DeletedInstanceDates = (uint32_t *) talloc_memdup(mem_ctx, arp->RecurrencePattern.DeletedInstanceDates, 
1325                                                                                  sizeof(uint32_t) * arp->RecurrencePattern.DeletedInstanceCount);
1326                                                               
1327         arp->RecurrencePattern.ModifiedInstanceDates = (uint32_t *) talloc_memdup(mem_ctx, arp->RecurrencePattern.ModifiedInstanceDates, 
1328                                                                                   sizeof(uint32_t) * arp->RecurrencePattern.ModifiedInstanceCount);
1329         
1330         /* Set reference to parent so arrays get free with rest */
1331         arp->ExceptionInfo = talloc_reference(arp, arp->ExceptionInfo);
1332         arp->RecurrencePattern.DeletedInstanceDates = talloc_reference(arp,arp->RecurrencePattern.DeletedInstanceDates);
1333         arp->RecurrencePattern.ModifiedInstanceDates = talloc_reference(arp, arp->RecurrencePattern.ModifiedInstanceDates);
1334         
1335         return arp;
1336 }
1337
1338 _PUBLIC_ size_t set_AppointmentRecurrencePattern_size(const struct AppointmentRecurrencePattern *arp)
1339 {
1340         size_t size = SIZE_DFLT_APPOINTMENTRECURRENCEPATTERN;
1341         uint16_t i;
1342
1343         size += set_RecurrencePattern_size(&arp->RecurrencePattern);
1344         for (i = 0; i < arp->ExceptionCount; i++) {
1345                 size += set_ExceptionInfo_size(arp->ExceptionInfo + i);
1346                 /* size += set_ExtendedException_size(arp->ExtendedException +
1347                    i); */
1348         }
1349         size += arp->ReservedBlock1Size * sizeof(uint32_t);
1350         /* size += arp->ReservedBlock2Size * sizeof(uint32_t); */
1351
1352         return size;
1353 }
1354
1355 _PUBLIC_ struct Binary_r *set_AppointmentRecurrencePattern(TALLOC_CTX *mem_ctx, const struct AppointmentRecurrencePattern *arp)
1356 {
1357         struct Binary_r                 *bin = NULL;
1358         struct ndr_push                 *ndr;
1359         enum ndr_err_code               ndr_err_code;
1360         size_t                          bin_size;
1361         
1362         /* SANITY CHECKS */
1363         if (!arp) return NULL;
1364
1365         ndr = ndr_push_init_ctx(mem_ctx);
1366         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
1367         ndr->offset = 0;
1368         bin_size = set_AppointmentRecurrencePattern_size(arp);
1369         talloc_free(ndr->data);
1370         ndr->data = talloc_array(ndr, uint8_t, bin_size);
1371
1372         ndr_err_code = ndr_push_AppointmentRecurrencePattern(ndr, NDR_SCALARS, arp);
1373         if (ndr_err_code != NDR_ERR_SUCCESS) {
1374                 return NULL;
1375         }
1376
1377         bin = talloc_zero(mem_ctx, struct Binary_r);
1378         bin->cb = bin_size;
1379         bin->lpb = ndr->data;
1380         talloc_steal(bin, bin->lpb);
1381
1382         talloc_free(ndr);
1383
1384         return bin;
1385 }
1386
1387 _PUBLIC_ size_t set_ExceptionInfo_size(const struct ExceptionInfo *exc_info)
1388 {
1389         size_t size = SIZE_DFLT_EXCEPTIONINFO;
1390
1391         if ((exc_info->OverrideFlags & ARO_SUBJECT)) {
1392                 size += 3 * sizeof(uint16_t); /* SubjectLength + SubjectLength2 + Subject */
1393         }
1394         if ((exc_info->OverrideFlags & ARO_MEETINGTYPE)) {
1395                 size += sizeof(uint32_t);
1396         }
1397         if ((exc_info->OverrideFlags & ARO_REMINDERDELTA)) {
1398                 size += sizeof(uint32_t);
1399         }
1400         if ((exc_info->OverrideFlags & ARO_REMINDER)) {
1401                 size += sizeof(uint32_t);
1402         }
1403         if ((exc_info->OverrideFlags & ARO_LOCATION)) {
1404                 size += 2 * sizeof(uint16_t); /* LocationLength + LocationLength2 */
1405                 size += sizeof(uint32_t); /* Location */
1406         }
1407         if ((exc_info->OverrideFlags & ARO_BUSYSTATUS)) {
1408                 size += sizeof(uint32_t);
1409         }
1410         if ((exc_info->OverrideFlags & ARO_ATTACHMENT)) {
1411                 size += sizeof(uint32_t);
1412         }
1413         if ((exc_info->OverrideFlags & ARO_SUBTYPE)) {
1414                 size += sizeof(uint32_t);
1415         }
1416         if ((exc_info->OverrideFlags & ARO_APPTCOLOR)) {
1417                 size += sizeof(uint32_t);
1418         }
1419
1420         return size;
1421 }
1422
1423 /**
1424    \details Retrieve a TimeZoneStruct structure from a binary blob
1425
1426    \param mem_ctx pointer to the memory context
1427    \param bin pointer to the Binary_r structure with raw
1428    TimeZoneStruct data
1429
1430    \return Allocated TimeZoneStruct structure on success, otherwise
1431    NULL
1432
1433    \note Developers must free the allocated TimeZoneStruct when
1434    finished.
1435  */
1436 _PUBLIC_ struct TimeZoneStruct *get_TimeZoneStruct(TALLOC_CTX *mem_ctx, 
1437                                                    struct Binary_r *bin)
1438 {
1439         struct TimeZoneStruct   *TimeZoneStruct = NULL;
1440         struct ndr_pull         *ndr;
1441         enum ndr_err_code       ndr_err_code;
1442
1443         /* Sanity checks */
1444         if (!bin) return NULL;
1445         if (!bin->cb) return NULL;
1446         if (!bin->lpb) return NULL;
1447
1448         ndr = talloc_zero(mem_ctx, struct ndr_pull);
1449         ndr->offset = 0;
1450         ndr->data = bin->lpb;
1451         ndr->data_size = bin->cb;
1452
1453         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
1454         TimeZoneStruct = talloc_zero(mem_ctx, struct TimeZoneStruct);
1455         ndr_err_code = ndr_pull_TimeZoneStruct(ndr, NDR_SCALARS, TimeZoneStruct);
1456
1457         talloc_free(ndr);
1458         
1459         if (ndr_err_code != NDR_ERR_SUCCESS) {
1460                 talloc_free(TimeZoneStruct);
1461                 return NULL;
1462         }
1463
1464         return TimeZoneStruct;
1465 }
1466
1467
1468 /**
1469    \details Retrieve a PtypServerId structure from a binary blob
1470
1471    \param mem_ctx pointer to the memory context
1472    \param bin pointer to the Binary_r structure with raw PtypServerId data
1473
1474    \return Allocated PtypServerId structure on success, otherwise
1475    NULL
1476
1477    \note Developers must free the allocated PtypServerId when
1478    finished.
1479  */
1480 _PUBLIC_ struct PtypServerId *get_PtypServerId(TALLOC_CTX *mem_ctx, struct Binary_r *bin)
1481 {
1482         struct PtypServerId     *PtypServerId = NULL;
1483         struct ndr_pull         *ndr;
1484         enum ndr_err_code       ndr_err_code;
1485
1486         /* Sanity checks */
1487         if (!bin) return NULL;
1488         if (!bin->cb) return NULL;
1489         if (!bin->lpb) return NULL;
1490
1491         ndr = talloc_zero(mem_ctx, struct ndr_pull);
1492         ndr->offset = 0;
1493         ndr->data = bin->lpb;
1494         ndr->data_size = bin->cb;
1495
1496         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
1497         PtypServerId = talloc_zero(mem_ctx, struct PtypServerId);
1498         ndr_err_code = ndr_pull_PtypServerId(ndr, NDR_SCALARS, PtypServerId);
1499
1500         talloc_free(ndr);
1501
1502         if (ndr_err_code != NDR_ERR_SUCCESS) {
1503                 talloc_free(PtypServerId);
1504                 return NULL;
1505         }
1506
1507         return PtypServerId;
1508 }
1509
1510 /**
1511    \details Retrieve a GlobalObjectId structure from a binary blob
1512
1513    \param mem_ctx pointer to the memory context
1514    \param bin pointer to the Binary_r structure with raw
1515    GlobalObjectId data
1516
1517    \return Allocated GlobalObjectId structure on success, otherwise
1518    NULL
1519
1520    \note Developers must free the allocated GlobalObjectId when
1521    finished.
1522  */
1523 _PUBLIC_ struct GlobalObjectId *get_GlobalObjectId(TALLOC_CTX *mem_ctx,
1524                                                    struct Binary_r *bin)
1525 {
1526         struct GlobalObjectId   *GlobalObjectId = NULL;
1527         struct ndr_pull         *ndr;
1528         enum ndr_err_code       ndr_err_code;
1529
1530         /* Sanity checks */
1531         if (!bin) return NULL;
1532         if (!bin->cb) return NULL;
1533         if (!bin->lpb) return NULL;
1534
1535         ndr = talloc_zero(mem_ctx, struct ndr_pull);
1536         ndr->offset = 0;
1537         ndr->data = bin->lpb;
1538         ndr->data_size = bin->cb;
1539
1540         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
1541         GlobalObjectId = talloc_zero(mem_ctx, struct GlobalObjectId);
1542         ndr_err_code = ndr_pull_GlobalObjectId(ndr, NDR_SCALARS, GlobalObjectId);
1543
1544         talloc_free(ndr);
1545
1546         if (ndr_err_code != NDR_ERR_SUCCESS) {
1547                 talloc_free(GlobalObjectId);
1548                 return NULL;
1549         }
1550
1551         return GlobalObjectId;
1552 }
1553
1554 /**
1555    \details Retrieve a MessageEntryId structure from a binary blob
1556
1557    \param mem_ctx pointer to the memory context
1558    \param bin pointer to the Binary_r structure with raw
1559    MessageEntryId data
1560
1561    \return Allocated MessageEntryId structure on success, otherwise
1562    NULL
1563
1564    \note Developers must free the allocated MessageEntryId when
1565    finished.
1566  */
1567 _PUBLIC_ struct MessageEntryId *get_MessageEntryId(TALLOC_CTX *mem_ctx, struct Binary_r *bin)
1568 {
1569         struct MessageEntryId   *MessageEntryId = NULL;
1570         struct ndr_pull         *ndr;
1571         enum ndr_err_code       ndr_err_code;
1572
1573         /* Sanity checks */
1574         if (!bin) return NULL;
1575         if (!bin->cb) return NULL;
1576         if (!bin->lpb) return NULL;
1577
1578         ndr = talloc_zero(mem_ctx, struct ndr_pull);
1579         ndr->offset = 0;
1580         ndr->data = bin->lpb;
1581         ndr->data_size = bin->cb;
1582
1583         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
1584         MessageEntryId = talloc_zero(mem_ctx, struct MessageEntryId);
1585         ndr_err_code = ndr_pull_MessageEntryId(ndr, NDR_SCALARS, MessageEntryId);
1586
1587         talloc_free(ndr);
1588
1589         if (ndr_err_code != NDR_ERR_SUCCESS) {
1590                 talloc_free(MessageEntryId);
1591                 return NULL;
1592         }
1593
1594         return MessageEntryId;
1595 }
1596
1597 /**
1598    \details Retrieve a FolderEntryId structure from a binary blob
1599
1600    \param mem_ctx pointer to the memory context
1601    \param bin pointer to the Binary_r structure with raw FolderEntryId data
1602
1603    \return Allocated FolderEntryId structure on success, otherwise
1604    NULL
1605
1606    \note Developers must free the allocated FolderEntryId when
1607    finished.
1608  */
1609 _PUBLIC_ struct FolderEntryId *get_FolderEntryId(TALLOC_CTX *mem_ctx, struct Binary_r *bin)
1610 {
1611         struct FolderEntryId    *FolderEntryId = NULL;
1612         struct ndr_pull         *ndr;
1613         enum ndr_err_code       ndr_err_code;
1614
1615         /* Sanity checks */
1616         if (!bin) return NULL;
1617         if (!bin->cb) return NULL;
1618         if (!bin->lpb) return NULL;
1619
1620         ndr = talloc_zero(mem_ctx, struct ndr_pull);
1621         ndr->offset = 0;
1622         ndr->data = bin->lpb;
1623         ndr->data_size = bin->cb;
1624
1625         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
1626         FolderEntryId = talloc_zero(mem_ctx, struct FolderEntryId);
1627         ndr_err_code = ndr_pull_FolderEntryId(ndr, NDR_SCALARS, FolderEntryId);
1628
1629         talloc_free(ndr);
1630
1631         if (ndr_err_code != NDR_ERR_SUCCESS) {
1632                 talloc_free(FolderEntryId);
1633                 return NULL;
1634         }
1635
1636         return FolderEntryId;
1637 }
1638
1639 /**
1640    \details Retrieve a AddressBookEntryId structure from a binary blob
1641
1642    \param mem_ctx pointer to the memory context
1643    \param bin pointer to the Binary_r structure with raw AddressBookEntryId data
1644
1645    \return Allocated AddressBookEntryId structure on success, otherwise NULL
1646
1647    \note Developers must free the allocated AddressBookEntryId when finished.
1648  */
1649 _PUBLIC_ struct AddressBookEntryId *get_AddressBookEntryId(TALLOC_CTX *mem_ctx, struct Binary_r *bin)
1650 {
1651         struct AddressBookEntryId       *AddressBookEntryId = NULL;
1652         struct ndr_pull                 *ndr;
1653         enum ndr_err_code               ndr_err_code;
1654
1655         /* Sanity checks */
1656         if (!bin) return NULL;
1657         if (!bin->cb) return NULL;
1658         if (!bin->lpb) return NULL;
1659
1660         ndr = talloc_zero(mem_ctx, struct ndr_pull);
1661         ndr->offset = 0;
1662         ndr->data = bin->lpb;
1663         ndr->data_size = bin->cb;
1664
1665         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
1666         AddressBookEntryId = talloc_zero(mem_ctx, struct AddressBookEntryId);
1667         ndr_err_code = ndr_pull_AddressBookEntryId(ndr, NDR_SCALARS, AddressBookEntryId);
1668
1669         talloc_free(ndr);
1670
1671         if (ndr_err_code != NDR_ERR_SUCCESS) {
1672                 talloc_free(AddressBookEntryId);
1673                 return NULL;
1674         }
1675
1676         return AddressBookEntryId;
1677 }
1678
1679 /**
1680    \details Return the effective value used in a TypedString
1681    structure.
1682
1683    \param tstring pointer to TypedString structure
1684
1685    \return pointer to a valid string on success, otherwise NULL
1686  */
1687 _PUBLIC_ const char *get_TypedString(struct TypedString *tstring)
1688 {
1689         if (!tstring) return NULL;
1690
1691         switch (tstring->StringType) {
1692         case StringType_STRING8:
1693                 return tstring->String.lpszA;
1694         case StringType_UNICODE_REDUCED:
1695                 return tstring->String.lpszW_reduced;
1696         case StringType_UNICODE:
1697                 return tstring->String.lpszW;
1698         case StringType_NONE:
1699         case StringType_EMPTY:
1700         default:
1701                 return NULL;
1702         }
1703
1704         return NULL;
1705 }
1706
1707 /**
1708    \details Return the expected size of the utf8 string after
1709    conversion to utf16 by iconv() function.
1710
1711    \param inbuf pointer to the input string
1712
1713    \return expected length of the converted string
1714
1715    \note This routine is based upon utf8_pull() function from
1716    samba4/lib/util/charset/iconv.c
1717  */
1718 size_t get_utf8_utf16_conv_length(const char *inbuf)
1719 {
1720         size_t          in_left;
1721         size_t          out_left;
1722         size_t          max_out;
1723         const uint8_t   *c = (const uint8_t *) inbuf;
1724
1725         /* Sanity checks */
1726         if (!inbuf) return 0;
1727
1728         in_left = strlen(inbuf);
1729         out_left = in_left;
1730         out_left = ( out_left * 3);
1731         /* includes null-termination bytes */
1732         max_out = out_left + 2;
1733
1734         while (in_left >= 1 && out_left >= 2) {
1735                 if ((c[0] & 0x80) == 0) {
1736                         c += 1;
1737                         in_left -= 1;
1738                         out_left -= 2;
1739                         continue;
1740                 }
1741
1742                 if ((c[0] & 0xe0) == 0xc0) {
1743                         if (in_left < 2 || (c[1] & 0xc0) != 0x80) {
1744                                 return -1;
1745                         }
1746                         c += 2;
1747                         in_left -= 2;
1748                         out_left -= 2;
1749                         continue;
1750                 }
1751
1752                 if ((c[0] & 0xf0) == 0xe0) {
1753                         if (in_left < 3 ||
1754                             (c[1] & 0xc0) != 0x80 ||
1755                             (c[2] & 0xc0) != 0x80) {
1756                                 return -1;
1757                         }
1758                         c += 3;
1759                         in_left -= 3;
1760                         out_left -= 2;
1761                         continue;
1762                 }
1763
1764                 if ((c[0] & 0xf8) == 0xf0) {
1765                         unsigned int codepoint;
1766                         if (in_left < 4 ||
1767                             (c[1] & 0xc0) != 0x80 ||
1768                             (c[2] & 0xc0) != 0x80 ||
1769                             (c[3] & 0xc0) != 0x80) {
1770                                 return -1;
1771                         }
1772                         codepoint = 
1773                                 (c[3]&0x3f) | 
1774                                 ((c[2]&0x3f)<<6) | 
1775                                 ((c[1]&0x3f)<<12) |
1776                                 ((c[0]&0x7)<<18);
1777                         if (codepoint < 0x10000) {
1778                                 c += 4;
1779                                 in_left -= 4;
1780                                 out_left -= 2;
1781                                 continue;
1782                         }
1783
1784                         codepoint -= 0x10000;
1785
1786                         if (out_left < 4) {
1787                                 return -1;
1788                         }
1789
1790                         c += 4;
1791                         in_left -= 4;
1792                         out_left -= 4;
1793                         continue;
1794                 }
1795                 
1796                 /* we don't handle 5 byte sequences */
1797                 return -1;
1798         }
1799
1800         if (in_left > 0) {
1801                 return -1;
1802         }
1803
1804         return (max_out - out_left);
1805 }
1806
1807 struct PropertyValue_r* get_PropertyValue_PropertyRow(struct PropertyRow_r *aRow, enum MAPITAGS ulPropTag)
1808 {
1809         uint32_t        i;
1810
1811         if (!aRow) {
1812                 return NULL;
1813         }
1814
1815         for (i = 0; i < aRow->cValues; i++) {
1816                 if (ulPropTag == aRow->lpProps[i].ulPropTag) {
1817                         return (&aRow->lpProps[i]);
1818                 }
1819         }
1820
1821         return NULL;
1822 }
1823
1824 _PUBLIC_ struct PropertyValue_r *get_PropertyValue_PropertyRowSet(struct PropertyRowSet_r *RowSet, 
1825                                                                   enum MAPITAGS ulPropTag)
1826 {
1827         uint32_t        i;
1828         uint32_t        j;
1829
1830         /* Sanity Checks */
1831         if (!RowSet) return NULL;
1832
1833         for (i = 0; i != RowSet->cRows; i++) {
1834                 for (j = 0; j < RowSet->aRow[i].cValues; j++) {
1835                         if (ulPropTag == RowSet->aRow[i].lpProps[j].ulPropTag) {
1836                                 return (&RowSet->aRow[i].lpProps[j]);
1837                         }
1838                 }
1839         }
1840
1841         return NULL;
1842 }
1843
1844 _PUBLIC_ const void *get_PropertyValue_PropertyRowSet_data(struct PropertyRowSet_r *RowSet,
1845                                                            uint32_t ulPropTag)
1846 {
1847         struct PropertyValue_r *lpProp;
1848
1849         lpProp = get_PropertyValue_PropertyRowSet(RowSet, ulPropTag);
1850         return get_PropertyValue(lpProp, ulPropTag);
1851 }
1852
1853 _PUBLIC_ bool set_PropertyValue(struct PropertyValue_r *lpProp, const void *data)
1854 {
1855         if (data == NULL) {
1856                 lpProp->ulPropTag = (lpProp->ulPropTag & 0xffff0000) | PT_ERROR;
1857                 lpProp->value.err = MAPI_E_NOT_FOUND;
1858                 return false;
1859         }
1860         switch (lpProp->ulPropTag & 0xFFFF) {
1861         case PT_SHORT:
1862                 lpProp->value.i = *((const uint16_t *)data);
1863                 break;
1864         case PT_BOOLEAN:
1865                 lpProp->value.b = *((const uint8_t *)data);
1866                 break;
1867         case PT_LONG:
1868                 lpProp->value.l = *((const uint32_t *)data);
1869                 break;
1870         case PT_STRING8:
1871                 lpProp->value.lpszA = (const char *) data;
1872                 break;
1873         case PT_BINARY:
1874         case PT_SVREID:
1875                 lpProp->value.bin = *((const struct Binary_r *)data);
1876                 break;
1877         case PT_UNICODE:
1878                 lpProp->value.lpszW = (const char *) data;
1879                 break;
1880         case PT_CLSID:
1881                 lpProp->value.lpguid = (struct FlatUID_r *) data;
1882                 break;
1883         case PT_SYSTIME:
1884                 lpProp->value.ft = *((const struct FILETIME *) data);
1885                 break;
1886         case PT_ERROR:
1887                 lpProp->value.err = *((enum MAPISTATUS *)data);
1888                 break;
1889         case PT_MV_SHORT:
1890                 lpProp->value.MVi = *((const struct ShortArray_r *)data);
1891                 break;
1892         case PT_MV_LONG:
1893                 lpProp->value.MVl = *((const struct LongArray_r *)data);
1894                 break;
1895         case PT_MV_STRING8:
1896                 lpProp->value.MVszA = *((const struct StringArray_r *)data);
1897                 break;
1898         case PT_MV_BINARY:
1899                 lpProp->value.MVbin = *((const struct BinaryArray_r *)data);
1900                 break;
1901         case PT_MV_CLSID:
1902                 lpProp->value.MVguid = *((const struct FlatUIDArray_r *)data);
1903                 break;
1904         case PT_MV_UNICODE:
1905                 lpProp->value.MVszW = *((const struct StringArrayW_r *)data);
1906                 break;
1907         case PT_MV_SYSTIME:
1908                 lpProp->value.MVft = *((const struct DateTimeArray_r *)data);
1909                 break;
1910         case PT_NULL:
1911                 lpProp->value.null = *((const uint32_t *)data);
1912                 break;
1913         default:
1914                 lpProp->ulPropTag = (lpProp->ulPropTag & 0xffff0000) | PT_ERROR;
1915                 lpProp->value.err = MAPI_E_NOT_FOUND;
1916
1917                 return false;
1918         }
1919
1920         return true;
1921 }
1922
1923 _PUBLIC_ const void *get_PropertyValue(struct PropertyValue_r *lpProps, enum MAPITAGS ulPropTag)
1924 {
1925         uint32_t        i;
1926
1927         /* Sanity checks */
1928         if (!lpProps) return NULL;
1929
1930         for (i = 0; lpProps[i].ulPropTag; i++) {
1931                 if (ulPropTag == lpProps[i].ulPropTag) {
1932                         return get_PropertyValue_data(&lpProps[i]);
1933                 }
1934         }
1935         return NULL;
1936 }
1937
1938 _PUBLIC_ const void *get_PropertyValue_data(struct PropertyValue_r *lpProps)
1939 {
1940         if (lpProps->ulPropTag == 0) {
1941                 return NULL;
1942         }
1943
1944         switch(lpProps->ulPropTag & 0xFFFF) {
1945         case PT_SHORT:
1946                 return (const void *)&lpProps->value.i;
1947         case PT_BOOLEAN:
1948                 return (const void *)&lpProps->value.b;
1949         case PT_STRING8:
1950                 return (const void *)lpProps->value.lpszA;
1951         case PT_UNICODE:
1952                 return (const void *)lpProps->value.lpszW;
1953         case PT_SYSTIME:
1954                 return (const void *)(struct FILETIME *)&lpProps->value.ft;
1955         case PT_ERROR:
1956                 return (const void *)&lpProps->value.err;
1957         case PT_LONG:
1958                 return (const void *)&lpProps->value.l;
1959         case PT_CLSID:
1960                 return (const void *)lpProps->value.lpguid;
1961         case PT_BINARY:
1962         case PT_SVREID:
1963                 return (const void *)&lpProps->value.bin;
1964         case PT_MV_SHORT:
1965                 return (const void *)(struct ShortArray_r *)&lpProps->value.MVi;
1966         case PT_MV_LONG:
1967                 return (const void *)(struct LongArray_r *)&lpProps->value.MVl;
1968         case PT_MV_STRING8:
1969                 return (const void *)(struct StringArray_r *)&lpProps->value.MVszA;
1970         case PT_MV_UNICODE:
1971                 return (const void *)(struct StringArrayW_r *)&lpProps->value.MVszW;
1972         case PT_MV_BINARY:
1973                 return (const void *)(struct BinaryArray_r *)&lpProps->value.MVbin;
1974         case PT_MV_SYSTIME:
1975                 return (const void *)(struct DateTimeArray_r *)&lpProps->value.MVft;
1976         case PT_NULL:
1977                 return (const void *)&lpProps->value.null;
1978         default:
1979                 return NULL;
1980         }
1981 }
1982
1983 /**
1984    \details add a PropertyValue_r structure to a PropertyRow_r array
1985
1986    \param aRow pointer to the PropertyRow_r array where propValue should be appended
1987    \param propValue the PropertyValue_r structure to add to aRow
1988
1989    \return MAPI_E_SUCCESS on success, otherwise MAPI_E_INVALID_PARAMETER.
1990  */
1991 _PUBLIC_ enum MAPISTATUS PropertyRow_addprop(struct PropertyRow_r *aRow, struct PropertyValue_r propValue)
1992 {
1993         TALLOC_CTX              *mem_ctx;
1994         uint32_t                cValues;
1995         struct PropertyValue_r  lpProp;
1996         uint32_t                i;
1997         
1998         /* Sanity checks */
1999         OPENCHANGE_RETVAL_IF(!aRow, MAPI_E_INVALID_PARAMETER, NULL);
2000
2001         mem_ctx = (TALLOC_CTX *) aRow;
2002
2003         /* If the property tag already exist, overwrite its value */
2004         for (i = 0; i < aRow->cValues; i++) {
2005                 if (aRow->lpProps[i].ulPropTag == propValue.ulPropTag) {
2006                         aRow->lpProps[i] = propValue;
2007                         return MAPI_E_SUCCESS;
2008                 }
2009         }
2010
2011         cValues = aRow->cValues + 1;
2012         aRow->lpProps = talloc_realloc(mem_ctx, aRow->lpProps, struct PropertyValue_r, cValues);
2013         lpProp = aRow->lpProps[cValues-1];
2014         lpProp.ulPropTag = propValue.ulPropTag;
2015         lpProp.dwAlignPad = 0;
2016         set_PropertyValue(&(lpProp), get_PropertyValue_data(&propValue));
2017         aRow->cValues = cValues;
2018         aRow->lpProps[cValues - 1] = lpProp;
2019
2020         return MAPI_E_SUCCESS;
2021 }
2022
2023 _PUBLIC_ const void *find_PropertyValue_data(struct PropertyRow_r *aRow, uint32_t mapitag)
2024 {
2025         uint32_t i;
2026
2027         if (!aRow) {
2028                 return NULL;
2029         }
2030
2031         for (i = 0; i < aRow->cValues; i++) {
2032                 if (aRow->lpProps[i].ulPropTag == mapitag) {
2033                         return get_PropertyValue_data(&(aRow->lpProps[i]));
2034                 }
2035         }
2036         return NULL;
2037 }
2038
2039 /**
2040    \details Append a PropertyValue_r structure to given PropertyRowSet_r
2041
2042    \param mem_ctx pointer to the memory context
2043    \param RowSet pointer to the PropertyRowSet_r array to update
2044    \param value the PropertyValue_r to append within SRowSet
2045
2046    \return 0 on success, otherwise 1
2047  */
2048 _PUBLIC_ uint32_t PropertyRowSet_propcpy(TALLOC_CTX *mem_ctx, struct PropertyRowSet_r *RowSet, struct PropertyValue_r value)
2049 {
2050         uint32_t                rows;
2051         uint32_t                cValues;
2052         struct PropertyValue_r  lpProp;
2053
2054         /* Sanity checks */
2055         if (!RowSet) return 1;
2056
2057         for (rows = 0; rows < RowSet->cRows; rows++) {
2058                 cValues = RowSet->aRow[rows].cValues + 1;
2059                 RowSet->aRow[rows].lpProps = talloc_realloc(mem_ctx, RowSet->aRow[rows].lpProps, struct PropertyValue_r, cValues);
2060                 lpProp = RowSet->aRow[rows].lpProps[cValues-1];
2061                 lpProp.ulPropTag = value.ulPropTag;
2062                 lpProp.dwAlignPad = 0;
2063                 set_PropertyValue(&(lpProp), (void *)&value.value);
2064                 RowSet->aRow[rows].cValues = cValues;
2065                 RowSet->aRow[rows].lpProps[cValues - 1] = lpProp;
2066         }
2067         return 0;
2068 }
2069
2070 /**
2071    \details Convenience function to convert a PropertyValue_r structure into a SPropValue structure.
2072
2073    \param propvalue pointer to the PropertyValue_r structure to copy data to
2074    \param spropvalue pointer to the SPropValue structure to copy data from
2075  */
2076 _PUBLIC_ void cast_PropertyValue_to_SPropValue(struct PropertyValue_r *propvalue, struct SPropValue *spropvalue)
2077 {
2078         spropvalue->ulPropTag = propvalue->ulPropTag;
2079
2080         switch (propvalue->ulPropTag & 0xFFFF) {
2081         case PT_BOOLEAN:
2082                 spropvalue->value.b = propvalue->value.b;
2083                 break;
2084         case PT_I2:
2085                 spropvalue->value.i = propvalue->value.i;
2086                 break;
2087         case PT_LONG:
2088                 spropvalue->value.l = propvalue->value.l;
2089                 break;
2090         case PT_STRING8:
2091                 spropvalue->value.lpszA = propvalue->value.lpszA;
2092                 break;
2093         case PT_UNICODE:
2094                 spropvalue->value.lpszW = propvalue->value.lpszW;
2095                 break;
2096         case PT_SYSTIME:
2097                 propvalue->value.ft = propvalue->value.ft;
2098                 break;
2099         case PT_CLSID:
2100                 spropvalue->value.lpguid = propvalue->value.lpguid;
2101                 break;
2102         case PT_SVREID:
2103         case PT_BINARY:
2104                 spropvalue->value.bin = propvalue->value.bin;
2105                 break;
2106         case PT_ERROR:
2107                 spropvalue->value.err = propvalue->value.err;
2108                 break;
2109         case PT_MV_LONG:
2110                 spropvalue->value.MVl = propvalue->value.MVl;
2111                 break;
2112         case PT_MV_STRING8:
2113                 spropvalue->value.MVszA = propvalue->value.MVszA;
2114                 break;
2115         case PT_MV_UNICODE:
2116                 spropvalue->value.MVszW = propvalue->value.MVszW;
2117                 break;
2118         case PT_MV_CLSID:
2119                 spropvalue->value.MVguid = propvalue->value.MVguid;
2120                 break;
2121         case PT_MV_BINARY:
2122                 spropvalue->value.MVbin = propvalue->value.MVbin;
2123                 break;
2124         default:
2125                 printf("unhandled conversion case in cast_PropvalueValue(): 0x%x\n", (propvalue->ulPropTag & 0xFFFF));
2126                 OPENCHANGE_ASSERT();
2127         }
2128 }
2129
2130 /**
2131    \details Convenience function to convert a PropertyRow_r structure into a SRow structure.
2132
2133    \param mem_ctx pointer to the allocation context for structure members
2134    \param proprow pointer to the PropertyRow_r structure to copy data to
2135    \param srow pointer to the SRow structure to copy data from
2136  */
2137 _PUBLIC_ void cast_PropertyRow_to_SRow(TALLOC_CTX *mem_ctx, struct PropertyRow_r *proprow, struct SRow *srow)
2138 {
2139         uint32_t i;
2140
2141         srow->cValues = proprow->cValues;
2142         srow->lpProps = talloc_array(mem_ctx, struct SPropValue, srow->cValues);
2143         for (i = 0; i < srow->cValues; i++) {
2144                 cast_PropertyValue_to_SPropValue(proprow->lpProps + i, srow->lpProps + i);
2145         }
2146 }
2147
2148 /**
2149    \details Convenience function to convert a PropertyRowSet_r structure into a SRowSet structure.
2150
2151    \param mem_ctx pointer to the allocation context for structure members
2152    \param prowset pointer to the PropertyRowSet_r structure to copy data to
2153    \param setrowset pointer to the SRowSet structure to copy data from
2154  */
2155 _PUBLIC_ void cast_PropertyRowSet_to_SRowSet(TALLOC_CTX *mem_ctx, struct PropertyRowSet_r *prowset, struct SRowSet *srowset)
2156 {
2157         uint32_t i;
2158
2159         srowset->cRows = prowset->cRows;
2160         srowset->aRow = talloc_array(mem_ctx, struct SRow, srowset->cRows);
2161         for (i = 0; i < srowset->cRows; i++) {
2162                 cast_PropertyRow_to_SRow(mem_ctx, prowset->aRow + i, srowset->aRow + i);
2163         }
2164 }