Add sanity check to get_SPropValue_SRowSet, prevents the function
[jelmer/openchange-proposed.git/.git] / libmapi / property.c
1 /*
2    OpenChange MAPI implementation.
3
4    Copyright (C) Julien Kerihuel 2005 - 2008.
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/proto_private.h>
23 #include <libmapi/mapitags.h>
24 #include <gen_ndr/ndr_property.h>
25 #include <param.h>
26
27 /**
28    \file property.c
29
30    \brief Functions for manipulating MAPI properties
31  */
32
33 _PUBLIC_ struct SPropTagArray *set_SPropTagArray(TALLOC_CTX *mem_ctx, 
34                                                  uint32_t PropCount, ...)
35 {
36         struct SPropTagArray    *SPropTagArray;
37         va_list                 ap;
38         uint32_t                i;
39         uint32_t                *aulPropTag;
40
41         aulPropTag = talloc_array(mem_ctx, uint32_t, PropCount);
42
43         va_start(ap, PropCount);
44         for (i = 0; i < PropCount; i++) {
45                 aulPropTag[i] = va_arg(ap, int);
46         }
47         va_end(ap);
48
49         SPropTagArray = talloc(mem_ctx, struct SPropTagArray);
50         SPropTagArray->aulPropTag = aulPropTag;
51         SPropTagArray->cValues = PropCount;
52         return SPropTagArray;
53 }
54
55 /**
56    \details Add a property tag to an existing properties array
57
58    \param mem_ctx talloc memory context to use for allocation
59    \param SPropTagArray existing properties array to add to
60    \param aulPropTag the property tag to add
61
62    \return MAPI_E_SUCCESS on success, otherwise -1.
63
64    \note Developers should call GetLastError() to retrieve the last
65    MAPI error code. Possible MAPI error codes are:
66    - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized
67    - MAPI_E_INVALID_PARAMETER: SPropTagArray parameter is not correctly set
68 */
69 _PUBLIC_ enum MAPISTATUS SPropTagArray_add(TALLOC_CTX *mem_ctx, 
70                                            struct SPropTagArray *SPropTagArray, 
71                                            uint32_t aulPropTag)
72 {
73         MAPI_RETVAL_IF(!mem_ctx, MAPI_E_NOT_INITIALIZED, NULL);
74         MAPI_RETVAL_IF(!SPropTagArray, MAPI_E_INVALID_PARAMETER, NULL);
75         MAPI_RETVAL_IF(!SPropTagArray->cValues, MAPI_E_INVALID_PARAMETER, NULL);
76
77         SPropTagArray->cValues += 1;
78         SPropTagArray->aulPropTag = talloc_realloc(mem_ctx, SPropTagArray->aulPropTag,
79                                                    uint32_t, SPropTagArray->cValues);
80         SPropTagArray->aulPropTag[SPropTagArray->cValues - 1] = aulPropTag;
81
82         return MAPI_E_SUCCESS;
83 }
84
85 _PUBLIC_ const void *get_SPropValue(struct SPropValue *lpProps, 
86                                     uint32_t ulPropTag)
87 {
88         uint32_t        i;
89
90         for (i = 0; lpProps[i].ulPropTag; i++) {
91                 if (ulPropTag == lpProps[i].ulPropTag) {
92                         return get_SPropValue_data(&lpProps[i]);
93                 }
94         }
95         return NULL;
96 }
97
98 _PUBLIC_ struct SPropValue *get_SPropValue_SRowSet(struct SRowSet *RowSet, 
99                                                    uint32_t ulPropTag)
100 {
101         uint32_t        i;
102         uint32_t        j;
103
104         /* Sanity Checks */
105         if (!RowSet) return NULL;
106
107         for (i = 0; i != RowSet->cRows; i++) {
108                 for (j = 0; j < RowSet->aRow[i].cValues; j++) {
109                         if (ulPropTag == RowSet->aRow[i].lpProps[j].ulPropTag) {
110                                 return (&RowSet->aRow[i].lpProps[j]);
111                         }
112                 }
113         }
114
115         return NULL;
116 }
117
118 _PUBLIC_ const void *get_SPropValue_SRowSet_data(struct SRowSet *RowSet,
119                                                  uint32_t ulPropTag)
120 {
121         struct SPropValue *lpProp;
122
123         lpProp = get_SPropValue_SRowSet(RowSet, ulPropTag);
124         return get_SPropValue(lpProp, ulPropTag);
125 }
126
127 _PUBLIC_ enum MAPISTATUS set_default_error_SPropValue_SRow(struct SRow *aRow, uint32_t ulPropTag, void *data)
128 {
129         uint32_t        i;
130
131         for (i = 0; i < aRow->cValues; i++) {
132                 if ((ulPropTag & 0xFFFF0000) == (aRow->lpProps[i].ulPropTag & 0xFFFF0000) &&
133                     (aRow->lpProps[i].ulPropTag & 0xFFFF) == 0xA) {
134                         set_SPropValue_proptag(&(aRow->lpProps[i]), ulPropTag, data);
135                         return MAPI_E_SUCCESS;
136                 }
137         }
138         return MAPI_E_NOT_FOUND;
139 }
140
141 _PUBLIC_ struct SPropValue *get_SPropValue_SRow(struct SRow *aRow,
142                                                 uint32_t ulPropTag)
143 {
144         uint32_t        i;
145
146         for (i = 0; i < aRow->cValues; i++) {
147                 if (ulPropTag == aRow->lpProps[i].ulPropTag) {
148                         return (&aRow->lpProps[i]);
149                 }
150         }
151
152         return NULL;
153 }
154
155 _PUBLIC_ const void *get_SPropValue_SRow_data(struct SRow *aRow,
156                                               uint32_t ulPropTag)
157 {
158         struct SPropValue *lpProp;
159
160         lpProp = get_SPropValue_SRow(aRow, ulPropTag);
161         return get_SPropValue(lpProp, ulPropTag);
162 }
163
164 /*
165   Create a MAPITAGS array from a SRow entry
166  */
167
168 enum MAPITAGS *get_MAPITAGS_SRow(TALLOC_CTX *mem_ctx, struct SRow *aRow)
169 {
170         enum MAPITAGS   *mapitags;
171         uint32_t        count, idx;
172
173         mapitags = talloc_array(mem_ctx, enum MAPITAGS, aRow->cValues + 1);
174
175         for (count = 0, idx=0; count < aRow->cValues; count++) {
176                 if ((aRow->lpProps[count].ulPropTag & 0xFFFF) != PT_ERROR) {
177                         mapitags[idx] = aRow->lpProps[count].ulPropTag;
178                         idx++;
179                 }
180         }
181         mapitags[idx] = 0;
182         return mapitags;
183 }
184
185 /*
186   Remove MAPITAGS entries from a MAPITAGS array
187 */
188
189 uint32_t MAPITAGS_delete_entries(enum MAPITAGS *mapitags, uint32_t final_count, uint32_t PropCount, ...)
190 {
191         va_list                 ap;
192         uint32_t                i,j;
193         uint32_t                aulPropTag;
194         uint32_t                count = 0;
195         
196         va_start(ap, PropCount);
197         for (i = 0; i != PropCount; i++) {
198                 aulPropTag = va_arg(ap, uint32_t);
199                 for (count = 0; mapitags[count]; count++) {
200                         if (aulPropTag == (uint32_t)mapitags[count]) {
201                                 final_count -= 1;
202                                 for (j = count; mapitags[j]; j++) {
203                                         mapitags[j] = (mapitags[j+1]) ? mapitags[j+1] : 0;
204                                 }
205                         }
206                 }
207         }
208         va_end(ap);
209
210         return final_count;
211 }
212
213 _PUBLIC_ const void *find_SPropValue_data(struct SRow *aRow, uint32_t mapitag)
214 {
215         uint32_t i;
216
217         for (i = 0; i < aRow->cValues; i++) {
218                 if (aRow->lpProps[i].ulPropTag == mapitag) {
219                         return get_SPropValue_data(&(aRow->lpProps[i]));
220                 }
221         }
222         return NULL;
223 }
224
225 _PUBLIC_ const void *find_mapi_SPropValue_data(
226                                         struct mapi_SPropValue_array *properties, uint32_t mapitag)
227 {
228         uint32_t i;
229
230         for (i = 0; i < properties->cValues; i++) {
231                 if (properties->lpProps[i].ulPropTag == mapitag) {
232                         return get_mapi_SPropValue_data(&properties->lpProps[i]);
233                 }
234         }
235         return NULL;
236 }
237
238 _PUBLIC_ const void *get_mapi_SPropValue_data(struct mapi_SPropValue *lpProp)
239 {
240         if (lpProp->ulPropTag == 0) {
241                 return NULL;
242         }
243         switch(lpProp->ulPropTag & 0xFFFF) {
244         case PT_BOOLEAN:
245                 return (const void *)(uint8_t *)&lpProp->value.b;
246         case PT_I2:
247                 return (const void *)(uint16_t *)&lpProp->value.i;
248         case PT_LONG:
249                 return (const void *)&lpProp->value.l;
250         case PT_DOUBLE:
251                 return (const void *)&lpProp->value.dbl;
252         case PT_I8:
253                 return (const void *)&lpProp->value.d;
254         case PT_SYSTIME:
255                 return (const void *)(struct FILETIME *)&lpProp->value.ft;
256         case PT_ERROR:
257                 return (const void *)&lpProp->value.err;
258         case PT_STRING8:
259                 return (const void *)lpProp->value.lpszA;
260         case PT_UNICODE:
261                 return (const void *)lpProp->value.lpszW;
262         case PT_BINARY:
263                 return (const void *)(struct SBinary_short *)&lpProp->value.bin;
264         case PT_MV_LONG:
265                 return (const void *)(struct mapi_MV_LONG_STRUCT *)&lpProp->value.MVl;
266         case PT_MV_STRING8:
267                 return (const void *)(struct mapi_SLPSTRArray *)&lpProp->value.MVszA;
268         case PT_MV_BINARY:
269                 return (const void *)(struct mapi_SBinaryArray *)&lpProp->value.MVbin;
270         default:
271                 return NULL;
272         }
273 }
274
275 _PUBLIC_ const void *get_SPropValue_data(struct SPropValue *lpProps)
276 {
277         if (lpProps->ulPropTag == 0) {
278                 return NULL;
279         }
280
281         switch(lpProps->ulPropTag & 0xFFFF) {
282         case PT_BOOLEAN:
283                 return (const void *)&lpProps->value.b;
284         case PT_I8:
285                 return (const void *)&lpProps->value.d;
286         case PT_STRING8:
287                 return (const void *)lpProps->value.lpszA;
288         case PT_UNICODE:
289                 return (const void *)lpProps->value.lpszW;
290         case PT_SYSTIME:
291                 return (const void *)(struct FILETIME *)&lpProps->value.ft;
292         case PT_ERROR:
293                 return (const void *)&lpProps->value.err;
294         case PT_LONG:
295                 return (const void *)&lpProps->value.l;
296         case PT_DOUBLE:
297                 return (const void *)&lpProps->value.dbl;
298         case PT_CLSID:
299                 return (const void *)(struct GUID *)&lpProps->value.lpguid;
300         case PT_BINARY:
301                 return (const void *)&lpProps->value.bin;
302         case PT_MV_LONG:
303                 return (const void *)(struct LongArray_r *)&lpProps->value.MVl;
304         case PT_MV_STRING8:
305                 return (const void *)(struct StringArray_r *)&lpProps->value.MVszA;
306         case PT_MV_BINARY:
307                 return (const void *)(struct BinaryArray_r *)&lpProps->value.MVbin;
308         default:
309                 return NULL;
310         }
311 }
312
313 _PUBLIC_ bool set_SPropValue_proptag(struct SPropValue *lpProps, uint32_t aulPropTag, const void *data)
314 {
315         lpProps->ulPropTag = aulPropTag;
316         lpProps->dwAlignPad = 0x0;
317
318         return (set_SPropValue(lpProps, data));
319 }
320
321 _PUBLIC_ struct SPropValue *add_SPropValue(TALLOC_CTX *mem_ctx, struct SPropValue *lpProps, uint32_t *cValues, uint32_t aulPropTag, const void * data)
322 {
323         lpProps = talloc_realloc(mem_ctx, lpProps, struct SPropValue, *cValues + 2);
324
325         set_SPropValue_proptag(&lpProps[*cValues], aulPropTag, data);
326         *cValues = *cValues + 1;
327
328         return lpProps;
329 }
330
331 _PUBLIC_ bool set_SPropValue(struct SPropValue *lpProps, const void *data)
332 {
333         if (data == NULL) {
334                 lpProps->value.err = MAPI_E_NOT_FOUND;
335                 return false;
336         }
337         switch (lpProps->ulPropTag & 0xFFFF) {
338         case PT_SHORT:
339                 lpProps->value.i = *((const uint16_t *)data);
340                 break;
341         case PT_LONG:
342                 lpProps->value.l = *((const uint32_t *)data);
343                 break;
344         case PT_I8:
345                 lpProps->value.d = *((const uint64_t *)data);
346                 break;
347         case PT_BOOLEAN:
348                 lpProps->value.b = *((const uint8_t *)data);
349                 break;
350         case PT_STRING8:
351                 lpProps->value.lpszA = (const char *) data;
352                 break;
353         case PT_BINARY:
354                 lpProps->value.bin = *((const struct Binary_r *)data);
355                 break;
356         case PT_UNICODE:
357                 lpProps->value.lpszW = (const char *) data;
358                 break;
359         case PT_CLSID:
360                 lpProps->value.lpguid = (struct FlatUID_r *) data;
361                 break;
362         case PT_SYSTIME:
363                 lpProps->value.ft = *((const struct FILETIME *) data);
364                 break;
365         case PT_ERROR:
366                 lpProps->value.err = *((const uint32_t *)data);
367                 break;
368         case PT_MV_SHORT:
369                 lpProps->value.err = *((const uint32_t *)data);
370                 break;
371         case PT_MV_LONG:
372                 lpProps->value.MVl = *((const struct LongArray_r *)data);
373                 break;
374         case PT_MV_STRING8:
375                 lpProps->value.MVszA = *((const struct StringArray_r *)data);
376                 break;
377         case PT_MV_BINARY:
378                 lpProps->value.MVbin = *((const struct BinaryArray_r *)data);
379                 break;
380         case PT_MV_CLSID:
381                 lpProps->value.MVguid = *((const struct FlatUIDArray_r *)data);
382                 break;
383         case PT_MV_UNICODE:
384                 lpProps->value.MVszW = *((const struct WStringArray_r *)data);
385                 break;
386         case PT_MV_SYSTIME:
387                 lpProps->value.MVft = *((const struct DateTimeArray_r *)data);
388                 break;
389         case PT_NULL:
390                 lpProps->value.null = *((const uint32_t *)data);
391                 break;
392         case PT_OBJECT:
393                 lpProps->value.null = *((const uint32_t *)data);
394                 break;
395         default:
396                 lpProps->value.err = MAPI_E_NOT_FOUND;
397
398                 return false;
399         }
400
401         return true;
402 }
403
404 _PUBLIC_ uint32_t get_mapi_property_size(struct mapi_SPropValue *lpProp)
405 {
406         switch(lpProp->ulPropTag & 0xFFFF) {
407         case PT_BOOLEAN:
408                 return sizeof (uint8_t);
409         case PT_I2:
410                 return sizeof (uint16_t);
411         case PT_LONG:
412         case PT_ERROR:
413                 return sizeof (uint32_t);
414         case PT_DOUBLE:
415         case PT_I8:
416                 return sizeof (uint64_t);
417         case PT_STRING8:
418                 return strlen(lpProp->value.lpszA) + 1;
419         case PT_UNICODE:
420                 return strlen(lpProp->value.lpszW) * 2 + 2;
421         case PT_SYSTIME:
422                 return sizeof (struct FILETIME);
423         case PT_BINARY:
424                 return (lpProp->value.bin.cb + sizeof(uint16_t));
425         }
426         return 0;
427 }
428
429 /*
430   convenient function which cast a SPropValue structure in a mapi_SPropValue one and return the associated size
431 */
432
433 _PUBLIC_ uint32_t cast_mapi_SPropValue(struct mapi_SPropValue *mapi_sprop, struct SPropValue *sprop)
434 {
435         mapi_sprop->ulPropTag = sprop->ulPropTag;
436
437         switch(sprop->ulPropTag & 0xFFFF) {
438         case PT_BOOLEAN:
439                 mapi_sprop->value.b = sprop->value.b;
440                 return sizeof(uint8_t);
441         case PT_I2:
442                 mapi_sprop->value.i = sprop->value.i;
443                 return sizeof(uint16_t);
444         case PT_LONG:
445                 mapi_sprop->value.l = sprop->value.l;
446                 return sizeof(uint32_t);
447         case PT_DOUBLE:
448                 mapi_sprop->value.dbl = sprop->value.dbl;
449                 return sizeof(uint64_t);
450         case PT_STRING8:
451                 mapi_sprop->value.lpszA = sprop->value.lpszA;
452                 if (!mapi_sprop->value.lpszA) return 0;
453                 return (strlen(sprop->value.lpszA) + 1);
454         case PT_UNICODE:
455                 mapi_sprop->value.lpszW = sprop->value.lpszW;
456                 if (!mapi_sprop->value.lpszW) return 0;
457                 return (strlen(sprop->value.lpszW) * 2 + 2);
458         case PT_SYSTIME:
459                 mapi_sprop->value.ft.dwLowDateTime = sprop->value.ft.dwLowDateTime;
460                 mapi_sprop->value.ft.dwHighDateTime = sprop->value.ft.dwHighDateTime;
461                 return (sizeof (struct FILETIME));
462         case PT_BINARY:
463                 mapi_sprop->value.bin.cb = sprop->value.bin.cb;
464                 mapi_sprop->value.bin.lpb = sprop->value.bin.lpb;
465                 return (mapi_sprop->value.bin.cb + sizeof(uint16_t));
466         case PT_MV_STRING8:
467                 {
468                         uint32_t        i;
469                         uint32_t        size = 0;
470
471                         mapi_sprop->value.MVszA.cValues = sprop->value.MVszA.cValues;
472                         size += 4;
473
474                         mapi_sprop->value.MVszA.strings = talloc_array(global_mapi_ctx->mem_ctx, struct mapi_LPSTR, mapi_sprop->value.MVszA.cValues);
475                         for (i = 0; i < mapi_sprop->value.MVszA.cValues; i++) {
476                                 mapi_sprop->value.MVszA.strings[i].lppszA = sprop->value.MVszA.lppszA[i];
477                                 size += strlen(mapi_sprop->value.MVszA.strings[i].lppszA) + 1;
478                         }
479                         return size;
480                 }
481         }
482         return 0;
483
484 }
485
486 /*
487  *
488  */
489 _PUBLIC_ uint32_t cast_SPropValue(struct mapi_SPropValue *mapi_sprop, struct SPropValue *sprop)
490 {
491         sprop->ulPropTag = mapi_sprop->ulPropTag;
492
493         switch(sprop->ulPropTag & 0xFFFF) {
494         case PT_BOOLEAN:
495                 sprop->value.b = mapi_sprop->value.b;
496                 return sizeof(uint8_t);
497         case PT_I2:
498                 sprop->value.i = mapi_sprop->value.i;
499                 return sizeof(uint16_t);
500         case PT_LONG:
501                 sprop->value.l = mapi_sprop->value.l;
502                 return sizeof(uint32_t);
503         case PT_DOUBLE:
504                 sprop->value.dbl = mapi_sprop->value.dbl;
505                 return sizeof(uint64_t);
506         case PT_STRING8:
507                 sprop->value.lpszA = mapi_sprop->value.lpszA;
508                 if (!mapi_sprop->value.lpszA) return 0;
509                 return (strlen(sprop->value.lpszA) + 1);
510         case PT_UNICODE:
511                 sprop->value.lpszW = mapi_sprop->value.lpszW;
512                 if (!sprop->value.lpszW) return 0;
513                 return (strlen(mapi_sprop->value.lpszW) * 2 + 2);
514         case PT_SYSTIME:
515                 sprop->value.ft.dwLowDateTime = mapi_sprop->value.ft.dwLowDateTime;
516                 sprop->value.ft.dwHighDateTime = mapi_sprop->value.ft.dwHighDateTime;
517                 return (sizeof (struct FILETIME));
518         case PT_BINARY:
519                 sprop->value.bin.cb = mapi_sprop->value.bin.cb;
520                 sprop->value.bin.lpb = mapi_sprop->value.bin.lpb;
521                 return (sprop->value.bin.cb + sizeof(uint16_t));
522
523         case PT_MV_STRING8:
524                 {
525                 uint32_t        i;
526                 uint32_t        size = 0;
527
528                 sprop->value.MVszA.cValues = mapi_sprop->value.MVszA.cValues;
529                 size += 4;
530
531                 sprop->value.MVszA.lppszA = talloc_array(global_mapi_ctx->mem_ctx, const char *, sprop->value.MVszA.cValues);
532                 for (i = 0; i < sprop->value.MVszA.cValues; i++) {
533                         sprop->value.MVszA.lppszA[i] = mapi_sprop->value.MVszA.strings[i].lppszA;
534                         size += strlen(sprop->value.MVszA.lppszA[i]) + 1;
535                 }
536                 return size;
537                 }
538         }
539         return 0;
540 }
541
542
543 _PUBLIC_ enum MAPISTATUS SRow_addprop(struct SRow *aRow, struct SPropValue SPropValue)
544 {
545         TALLOC_CTX              *mem_ctx;
546         uint32_t                cValues;
547         struct SPropValue       lpProp;
548         uint32_t                i;
549         
550         MAPI_RETVAL_IF(!aRow, MAPI_E_INVALID_PARAMETER, NULL);
551
552         mem_ctx = (TALLOC_CTX *) aRow;
553
554         /* If the property tag already exist, overwrite its value */
555         for (i = 0; i < aRow->cValues; i++) {
556                 if (aRow->lpProps[i].ulPropTag == SPropValue.ulPropTag) {
557                         aRow->lpProps[i] = SPropValue;
558                         return MAPI_E_SUCCESS;
559                 }
560         }
561
562         cValues = aRow->cValues + 1;
563         aRow->lpProps = talloc_realloc(mem_ctx, aRow->lpProps, struct SPropValue, cValues);
564         lpProp = aRow->lpProps[cValues-1];
565         lpProp.ulPropTag = SPropValue.ulPropTag;
566         lpProp.dwAlignPad = 0;
567         set_SPropValue(&(lpProp), get_SPropValue_data(&SPropValue));
568         aRow->cValues = cValues;
569         aRow->lpProps[cValues - 1] = lpProp;
570
571         return MAPI_E_SUCCESS;
572 }
573
574 _PUBLIC_ uint32_t SRowSet_propcpy(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, struct SPropValue SPropValue)
575 {
576         uint32_t        rows;
577         uint32_t        cValues;
578         struct SPropValue lpProp;
579
580         for (rows = 0; rows < SRowSet->cRows; rows++) {
581                 cValues = SRowSet->aRow[rows].cValues + 1;
582                 SRowSet->aRow[rows].lpProps = talloc_realloc(mem_ctx, SRowSet->aRow[rows].lpProps, struct SPropValue, cValues);
583                 lpProp = SRowSet->aRow[rows].lpProps[cValues-1];
584                 lpProp.ulPropTag = SPropValue.ulPropTag;
585                 lpProp.dwAlignPad = 0;
586                 set_SPropValue(&(lpProp), (void *)&SPropValue.value);
587                 SRowSet->aRow[rows].cValues = cValues;
588                 SRowSet->aRow[rows].lpProps[cValues - 1] = lpProp;
589         }
590         return 0;
591 }
592
593 _PUBLIC_ void mapi_SPropValue_array_named(mapi_object_t *obj, 
594                                           struct mapi_SPropValue_array *props)
595 {
596         TALLOC_CTX              *mem_ctx;
597         enum MAPISTATUS         retval;
598         struct MAPINAMEID       *nameid;
599         uint32_t                propID;
600         uint16_t                count;
601         uint32_t                i;
602
603         mem_ctx = talloc_init("mapi_SPropValue_array_named");
604
605         for (i = 0; i < props->cValues; i++) {
606                 if ((props->lpProps[i].ulPropTag & 0xFFFF0000) > 0x80000000) {
607                         propID = props->lpProps[i].ulPropTag;
608                         propID = (propID & 0xFFFF0000) | PT_NULL;
609                         nameid = talloc_zero(mem_ctx, struct MAPINAMEID);
610                         retval = GetNamesFromIDs(obj, propID, &count, &nameid);
611                         if (retval != MAPI_E_SUCCESS) goto end;
612
613                         if (count) {
614                                 /* Display property given its propID */
615                                 switch (nameid->ulKind) {
616                                 case MNID_ID:
617                                         props->lpProps[i].ulPropTag = (nameid->kind.lid << 16) | 
618                                                 (props->lpProps[i].ulPropTag & 0x0000FFFF);
619                                         break;
620                                 case MNID_STRING:
621                                         /* MNID_STRING named properties don't have propIDs */
622                                         break;
623                                 }
624                         }
625                         talloc_free(nameid);
626                 }
627         }
628 end:
629         talloc_free(mem_ctx);
630 }
631
632 _PUBLIC_ enum MAPISTATUS get_mapi_SPropValue_array_date_timeval(struct timeval *t,
633                                                                 struct mapi_SPropValue_array *properties,
634                                                                 uint32_t mapitag)
635 {
636         const struct FILETIME   *filetime;
637         NTTIME                  time;
638         
639         filetime = (const struct FILETIME *) find_mapi_SPropValue_data(properties, mapitag);
640         if (!filetime) {
641                 t = NULL;
642                 return MAPI_E_NOT_FOUND;
643         }
644
645         time = filetime->dwHighDateTime;
646         time = time << 32;
647         time |= filetime->dwLowDateTime;
648         nttime_to_timeval(t, time);
649         
650         return MAPI_E_SUCCESS;  
651 }
652
653 _PUBLIC_ enum MAPISTATUS get_mapi_SPropValue_date_timeval(struct timeval *t, 
654                                                           struct SPropValue lpProp)
655 {
656         const struct FILETIME   *filetime;
657         NTTIME                  time;
658         
659         filetime = (const struct FILETIME *) get_SPropValue_data(&lpProp);
660         if (!filetime) {
661                 t = NULL;
662                 return MAPI_E_NOT_FOUND;
663         }
664
665         time = filetime->dwHighDateTime;
666         time = time << 32;
667         time |= filetime->dwLowDateTime;
668         nttime_to_timeval(t, time);
669         
670         return MAPI_E_SUCCESS;
671 }
672
673 _PUBLIC_ bool set_SPropValue_proptag_date_timeval(struct SPropValue *lpProps, uint32_t aulPropTag, const struct timeval *t) 
674 {
675         struct FILETIME filetime;
676         NTTIME          time;
677         
678         time = timeval_to_nttime(t);
679
680         filetime.dwLowDateTime = (time << 32) >> 32;
681         filetime.dwHighDateTime = time >> 32;
682
683         return set_SPropValue_proptag(lpProps, aulPropTag, &filetime);
684 }
685
686
687 /**
688    \details Retrieve a RecurrencePattern structure from a binary blob
689
690    \param mem_ctx pointer to the memory context
691    \param bin pointer to the Binary_r structure with non-mapped
692    reccurrence data
693
694    \return Allocated RecurrencePattern structure on success,
695    otherwise NULL
696
697    \note Developers must free the allocated RecurrencePattern when
698    finished.
699  */
700 _PUBLIC_ struct RecurrencePattern *get_RecurrencePattern(TALLOC_CTX *mem_ctx, 
701                                                          struct Binary_r *bin)
702 {
703         struct RecurrencePattern        *RecurrencePattern = NULL;
704         struct ndr_pull                 *ndr;
705         enum ndr_err_code               ndr_err_code;
706         
707         /* Sanity checks */
708         if (!bin) return NULL;
709         if (!bin->cb) return NULL;
710         if (!bin->lpb) return NULL;
711
712         ndr = talloc_zero(mem_ctx, struct ndr_pull);
713         ndr->offset = 0;
714         ndr->data = bin->lpb;
715         ndr->data_size = bin->cb;
716
717         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
718         ndr->iconv_convenience = smb_iconv_convenience_init(mem_ctx, "CP850", "UTF8", true);
719         RecurrencePattern = talloc_zero(mem_ctx, struct RecurrencePattern);
720         ndr_err_code = ndr_pull_RecurrencePattern(ndr, NDR_SCALARS, RecurrencePattern);
721
722         talloc_free(ndr);
723
724         if (ndr_err_code != NDR_ERR_SUCCESS) {
725                 talloc_free(RecurrencePattern);
726                 return NULL;
727         }
728
729         return RecurrencePattern;
730 }
731
732
733 /**
734    \details Retrieve a TimeZoneStruct structure from a binary blob
735
736    \param mem_ctx pointer to the memory context
737    \param bin pointer to the Binary_r structure with raw
738    TimeZoneStruct data
739
740    \return Allocated TimeZoneStruct structure on success, otherwise
741    NULL
742
743    \note Developers must free the allocated TimeZoneStruct when
744    finished.
745  */
746 _PUBLIC_ struct TimeZoneStruct *get_TimeZoneStruct(TALLOC_CTX *mem_ctx, 
747                                                    struct Binary_r *bin)
748 {
749         struct TimeZoneStruct   *TimeZoneStruct = NULL;
750         struct ndr_pull         *ndr;
751         enum ndr_err_code       ndr_err_code;
752
753         /* Sanity checks */
754         if (!bin) return NULL;
755         if (!bin->cb) return NULL;
756         if (!bin->lpb) return NULL;
757
758         ndr = talloc_zero(mem_ctx, struct ndr_pull);
759         ndr->offset = 0;
760         ndr->data = bin->lpb;
761         ndr->data_size = bin->cb;
762
763         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
764         ndr->iconv_convenience = smb_iconv_convenience_init(mem_ctx, "CP850", "UTF8", true);
765         TimeZoneStruct = talloc_zero(mem_ctx, struct TimeZoneStruct);
766         ndr_err_code = ndr_pull_TimeZoneStruct(ndr, NDR_SCALARS, TimeZoneStruct);
767
768         talloc_free(ndr);
769         
770         if (ndr_err_code != NDR_ERR_SUCCESS) {
771                 talloc_free(TimeZoneStruct);
772                 return NULL;
773         }
774
775         return TimeZoneStruct;
776 }
777
778
779 /**
780    \details Retrieve a GlobalObjectId structure from a binary blob
781
782    \param mem_ctx pointer to the memory context
783    \param bin pointer to the Binary_r structure with raw
784    GlobalObjectId data
785
786    \return Allocated GlobalObjectId structure on success, otherwise
787    NULL
788
789    \note Developers must free the allocated GlobalObjectId when
790    finished.
791  */
792 _PUBLIC_ struct GlobalObjectId *get_GlobalObjectId(TALLOC_CTX *mem_ctx,
793                                                    struct Binary_r *bin)
794 {
795         struct GlobalObjectId   *GlobalObjectId = NULL;
796         struct ndr_pull         *ndr;
797         enum ndr_err_code       ndr_err_code;
798
799         /* Sanity checks */
800         if (!bin) return NULL;
801         if (!bin->cb) return NULL;
802         if (!bin->lpb) return NULL;
803
804         ndr = talloc_zero(mem_ctx, struct ndr_pull);
805         ndr->offset = 0;
806         ndr->data = bin->lpb;
807         ndr->data_size = bin->cb;
808
809         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
810         ndr->iconv_convenience = smb_iconv_convenience_init(mem_ctx, "CP850", "UTF8", true);
811         GlobalObjectId = talloc_zero(mem_ctx, struct GlobalObjectId);
812         ndr_err_code = ndr_pull_GlobalObjectId(ndr, NDR_SCALARS, GlobalObjectId);
813
814         talloc_free(ndr);
815
816         if (ndr_err_code != NDR_ERR_SUCCESS) {
817                 talloc_free(GlobalObjectId);
818                 return NULL;
819         }
820
821         return GlobalObjectId;
822 }