2 OpenChange MAPI implementation.
4 Copyright (C) Julien Kerihuel 2005 - 2011.
5 Copyright (C) Gregory Schiro 2006
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.
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.
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/>.
21 #include "libmapi/libmapi.h"
22 #include "libmapi/libmapi_private.h"
23 #include <gen_ndr/ndr_property.h>
29 \brief Functions for manipulating MAPI properties
34 \details Create a property tag array
36 \param mem_ctx talloc memory context to use for allocation
37 \param PropCount the number of properties in the array
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:
43 struct SPropTagArray *array
44 array = set_SPropTagArray(mem_ctx, 2, PR_ENTRYID, PR_DISPLAY_NAME);
47 _PUBLIC_ struct SPropTagArray *set_SPropTagArray(TALLOC_CTX *mem_ctx,
48 uint32_t PropCount, ...)
50 struct SPropTagArray *SPropTagArray;
55 aulPropTag = talloc_array(mem_ctx, uint32_t, PropCount);
57 va_start(ap, PropCount);
58 for (i = 0; i < PropCount; i++) {
59 aulPropTag[i] = va_arg(ap, int);
63 SPropTagArray = talloc(mem_ctx, struct SPropTagArray);
64 SPropTagArray->aulPropTag = (enum MAPITAGS *) aulPropTag;
65 SPropTagArray->cValues = PropCount;
70 \details Add a property tag to an existing properties array
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
76 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
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
82 _PUBLIC_ enum MAPISTATUS SPropTagArray_add(TALLOC_CTX *mem_ctx,
83 struct SPropTagArray *SPropTagArray,
84 enum MAPITAGS aulPropTag)
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);
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;
97 return MAPI_E_SUCCESS;
101 \details Delete a property tag from an existing properties array
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
107 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
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
113 _PUBLIC_ enum MAPISTATUS SPropTagArray_delete(TALLOC_CTX *mem_ctx,
114 struct SPropTagArray *SPropTagArray,
117 uint32_t i, removed = 0;
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);
124 for (i = 0; i < SPropTagArray->cValues; i++) {
125 if (SPropTagArray->aulPropTag[i] == aulPropTag) {
128 else if (removed > 0) {
129 SPropTagArray->aulPropTag[i-removed] = SPropTagArray->aulPropTag[i];
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;
138 return MAPI_E_SUCCESS;
142 \details Return the index of a property tag in an existing properties array
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)
148 \return MAPI_E_SUCCESS on success, otherwise MAPI error.
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
154 _PUBLIC_ enum MAPISTATUS SPropTagArray_find(struct SPropTagArray SPropTagArray,
155 enum MAPITAGS aulPropTag,
161 OPENCHANGE_RETVAL_IF(!propIdx, MAPI_E_INVALID_PARAMETER, NULL);
163 for (i = 0; i < SPropTagArray.cValues; i++) {
164 if (SPropTagArray.aulPropTag[i] == aulPropTag) {
166 return MAPI_E_SUCCESS;
170 return MAPI_E_NOT_FOUND;
173 _PUBLIC_ const void *get_SPropValue(struct SPropValue *lpProps,
174 enum MAPITAGS ulPropTag)
179 if (!lpProps) return NULL;
181 for (i = 0; lpProps[i].ulPropTag; i++) {
182 if (ulPropTag == lpProps[i].ulPropTag) {
183 return get_SPropValue_data(&lpProps[i]);
189 _PUBLIC_ struct SPropValue *get_SPropValue_SRowSet(struct SRowSet *RowSet,
196 if (!RowSet) return NULL;
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]);
209 _PUBLIC_ const void *get_SPropValue_SRowSet_data(struct SRowSet *RowSet,
212 struct SPropValue *lpProp;
214 lpProp = get_SPropValue_SRowSet(RowSet, ulPropTag);
215 return get_SPropValue(lpProp, ulPropTag);
218 _PUBLIC_ enum MAPISTATUS set_default_error_SPropValue_SRow(struct SRow *aRow, enum MAPITAGS ulPropTag, void *data)
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;
229 return MAPI_E_NOT_FOUND;
232 _PUBLIC_ struct SPropValue *get_SPropValue_SRow(struct SRow *aRow,
241 for (i = 0; i < aRow->cValues; i++) {
242 if (ulPropTag == aRow->lpProps[i].ulPropTag) {
243 return (&aRow->lpProps[i]);
250 _PUBLIC_ const void *get_SPropValue_SRow_data(struct SRow *aRow,
253 struct SPropValue *lpProp;
255 lpProp = get_SPropValue_SRow(aRow, ulPropTag);
256 return get_SPropValue(lpProp, ulPropTag);
260 Create a MAPITAGS array from a SRow entry
263 enum MAPITAGS *get_MAPITAGS_SRow(TALLOC_CTX *mem_ctx,
265 uint32_t *actual_count)
267 enum MAPITAGS *mapitags;
270 mapitags = talloc_array(mem_ctx, enum MAPITAGS, aRow->cValues + 1);
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;
278 mapitags[idx] = (enum MAPITAGS) 0;
285 Remove MAPITAGS entries from a MAPITAGS array
288 uint32_t MAPITAGS_delete_entries(enum MAPITAGS *mapitags, uint32_t final_count, uint32_t PropCount, ...)
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]) {
301 for (j = count; mapitags[j]; j++) {
302 mapitags[j] = (mapitags[j+1]) ? mapitags[j+1] : (enum MAPITAGS) 0;
312 _PUBLIC_ const void *find_SPropValue_data(struct SRow *aRow, uint32_t mapitag)
320 for (i = 0; i < aRow->cValues; i++) {
321 if (aRow->lpProps[i].ulPropTag == mapitag) {
322 return get_SPropValue_data(&(aRow->lpProps[i]));
328 _PUBLIC_ const void *find_mapi_SPropValue_data(
329 struct mapi_SPropValue_array *properties, uint32_t mapitag)
337 for (i = 0; i < properties->cValues; i++) {
338 if (properties->lpProps[i].ulPropTag == mapitag) {
339 return get_mapi_SPropValue_data(&properties->lpProps[i]);
345 _PUBLIC_ const void *get_mapi_SPropValue_data(struct mapi_SPropValue *lpProp)
350 if (lpProp->ulPropTag == 0) {
353 switch(lpProp->ulPropTag & 0xFFFF) {
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;
361 return (const void *)&lpProp->value.dbl;
363 return (const void *)&lpProp->value.d;
365 return (const void *)(struct FILETIME *)&lpProp->value.ft;
367 return (const void *)&lpProp->value.err;
369 return (const void *)lpProp->value.lpszA;
371 return (const void *)lpProp->value.lpszW;
373 return (const void *)(struct SBinary_short *)&lpProp->value.bin;
375 return (const void *)(struct mapi_MV_LONG_STRUCT *)&lpProp->value.MVl;
377 return (const void *)(struct mapi_SLPSTRArray *)&lpProp->value.MVszA;
379 return (const void *)(struct mapi_SLPSTRArrayW *)&lpProp->value.MVszW;
381 return (const void *)(struct mapi_SBinaryArray *)&lpProp->value.MVbin;
387 _PUBLIC_ const void *get_SPropValue_data(struct SPropValue *lpProps)
389 if (lpProps->ulPropTag == 0) {
393 switch(lpProps->ulPropTag & 0xFFFF) {
395 return (const void *)&lpProps->value.i;
397 return (const void *)&lpProps->value.b;
399 return (const void *)&lpProps->value.d;
401 return (const void *)lpProps->value.lpszA;
403 return (const void *)lpProps->value.lpszW;
405 return (const void *)(struct FILETIME *)&lpProps->value.ft;
407 return (const void *)&lpProps->value.err;
409 return (const void *)&lpProps->value.l;
411 return (const void *)&lpProps->value.dbl;
413 return (const void *)lpProps->value.lpguid;
416 return (const void *)&lpProps->value.bin;
418 return (const void *)&lpProps->value.object;
420 return (const void *)(struct ShortArray_r *)&lpProps->value.MVi;
422 return (const void *)(struct LongArray_r *)&lpProps->value.MVl;
424 return (const void *)(struct StringArray_r *)&lpProps->value.MVszA;
426 return (const void *)(struct StringArrayW_r *)&lpProps->value.MVszW;
428 return (const void *)(struct BinaryArray_r *)&lpProps->value.MVbin;
430 return (const void *)(struct DateTimeArray_r *)&lpProps->value.MVft;
432 return (const void *)&lpProps->value.null;
438 _PUBLIC_ bool set_SPropValue_proptag(struct SPropValue *lpProps, enum MAPITAGS aulPropTag, const void *data)
440 lpProps->ulPropTag = aulPropTag;
441 lpProps->dwAlignPad = 0x0;
443 return (set_SPropValue(lpProps, data));
446 _PUBLIC_ struct SPropValue *add_SPropValue(TALLOC_CTX *mem_ctx,
447 struct SPropValue *lpProps,
449 enum MAPITAGS aulPropTag,
452 lpProps = talloc_realloc(mem_ctx, lpProps, struct SPropValue, *cValues + 2);
454 set_SPropValue_proptag(&lpProps[*cValues], aulPropTag, data);
455 *cValues = *cValues + 1;
460 _PUBLIC_ bool set_mapi_SPropValue(TALLOC_CTX *mem_ctx, struct mapi_SPropValue *lpProps, const void *data)
463 lpProps->ulPropTag = (lpProps->ulPropTag & 0xffff0000) | PT_ERROR;
464 lpProps->value.err = MAPI_E_NOT_FOUND;
467 switch (lpProps->ulPropTag & 0xFFFF) {
469 lpProps->value.i = *((const uint16_t *)data);
472 lpProps->value.l = *((const uint32_t *)data);
475 lpProps->value.dbl = *((const double *)data);
478 lpProps->value.d = *((const uint64_t *)data);
481 lpProps->value.b = *((const uint8_t *)data);
484 lpProps->value.lpszA = (const char *) data;
488 struct Binary_r *bin;
490 bin = (struct Binary_r *)data;
491 lpProps->value.bin.cb = (uint16_t)bin->cb;
492 lpProps->value.bin.lpb = (void *)bin->lpb;
496 lpProps->value.lpszW = (const char *) data;
499 lpProps->value.lpguid = *((struct GUID *) data);
502 lpProps->value.ft = *((const struct FILETIME *) data);
505 lpProps->value.err = *((const uint32_t *)data);
508 lpProps->value.MVl = *((const struct mapi_MV_LONG_STRUCT *)data);
511 lpProps->value.MVszA = *((const struct mapi_SLPSTRArray *)data);
514 lpProps->value.MVbin = *((const struct mapi_SBinaryArray *)data);
517 lpProps->value.MVguid = *((const struct mapi_SGuidArray *)data);
520 lpProps->value.MVszW = *((const struct mapi_SLPSTRArrayW *)data);
523 lpProps->ulPropTag = (lpProps->ulPropTag & 0xffff0000) | PT_ERROR;
524 lpProps->value.err = MAPI_E_NOT_FOUND;
532 _PUBLIC_ bool set_mapi_SPropValue_proptag(TALLOC_CTX *mem_ctx, struct mapi_SPropValue *lpProps, uint32_t aulPropTag, const void *data)
534 lpProps->ulPropTag = aulPropTag;
536 return (set_mapi_SPropValue(mem_ctx, lpProps, data));
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)
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;
549 _PUBLIC_ bool set_SPropValue(struct SPropValue *lpProps, const void *data)
552 lpProps->ulPropTag = (lpProps->ulPropTag & 0xffff0000) | PT_ERROR;
553 lpProps->value.err = MAPI_E_NOT_FOUND;
556 switch (lpProps->ulPropTag & 0xFFFF) {
558 lpProps->value.i = *((const uint16_t *)data);
561 lpProps->value.l = *((const uint32_t *)data);
564 lpProps->value.dbl = *((const double *)data);
567 lpProps->value.d = *((const uint64_t *)data);
570 lpProps->value.b = *((const uint8_t *)data);
573 lpProps->value.lpszA = (const char *) data;
577 lpProps->value.bin = *((const struct Binary_r *)data);
580 lpProps->value.lpszW = (const char *) data;
583 lpProps->value.lpguid = (struct FlatUID_r *) data;
586 lpProps->value.ft = *((const struct FILETIME *) data);
589 lpProps->value.err = *((enum MAPISTATUS *)data);
592 lpProps->value.MVi = *((const struct ShortArray_r *)data);
595 lpProps->value.MVl = *((const struct LongArray_r *)data);
598 lpProps->value.MVszA = *((const struct StringArray_r *)data);
601 lpProps->value.MVbin = *((const struct BinaryArray_r *)data);
604 lpProps->value.MVguid = *((const struct FlatUIDArray_r *)data);
607 lpProps->value.MVszW = *((const struct StringArrayW_r *)data);
610 lpProps->value.MVft = *((const struct DateTimeArray_r *)data);
613 lpProps->value.null = *((const uint32_t *)data);
616 lpProps->value.object = *((const uint32_t *)data);
619 lpProps->ulPropTag = (lpProps->ulPropTag & 0xffff0000) | PT_ERROR;
620 lpProps->value.err = MAPI_E_NOT_FOUND;
628 _PUBLIC_ uint32_t get_mapi_property_size(struct mapi_SPropValue *lpProp)
630 switch(lpProp->ulPropTag & 0xFFFF) {
632 return sizeof (uint8_t);
634 return sizeof (uint16_t);
637 return sizeof (uint32_t);
639 return sizeof (double);
641 return sizeof (uint64_t);
643 return strlen(lpProp->value.lpszA) + 1;
645 return get_utf8_utf16_conv_length(lpProp->value.lpszW);
647 return sizeof (struct FILETIME);
649 return (lpProp->value.bin.cb + sizeof(uint16_t));
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.
660 _PUBLIC_ void mapi_copy_spropvalues(TALLOC_CTX *mem_ctx, struct SPropValue *source_values, struct SPropValue *dest_values, uint32_t count)
663 struct SPropValue *source_value, *dest_value;
666 for (i = 0; i < count; i++) {
667 source_value = source_values + i;
668 dest_value = dest_values + i;
669 *dest_value = *source_value;
671 prop_type = (source_value->ulPropTag & 0xFFFF);
672 if ((prop_type & MV_FLAG)) {
673 DEBUG(5, ("multivalues not handled\n"));
679 dest_value->value.lpszA = talloc_strdup(mem_ctx, source_value->value.lpszA);
682 dest_value->value.lpszW = talloc_strdup(mem_ctx, source_value->value.lpszW);
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);
689 *dest_value = *source_value;
696 \details Convenience function to convert a SPropValue structure
697 into a mapi_SPropValue structure and return the associated size.
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
703 \return size of the converted data on success, otherwise 0
705 _PUBLIC_ uint32_t cast_mapi_SPropValue(TALLOC_CTX *mem_ctx,
706 struct mapi_SPropValue *mapi_sprop,
707 struct SPropValue *sprop)
709 mapi_sprop->ulPropTag = sprop->ulPropTag;
711 switch(sprop->ulPropTag & 0xFFFF) {
713 mapi_sprop->value.b = sprop->value.b;
714 return sizeof(uint8_t);
716 mapi_sprop->value.i = sprop->value.i;
717 return sizeof(uint16_t);
719 mapi_sprop->value.l = sprop->value.l;
720 return sizeof(uint32_t);
722 mapi_sprop->value.dbl = sprop->value.dbl;
723 return sizeof(double);
725 mapi_sprop->value.d = sprop->value.d;
726 return sizeof(uint64_t);
728 mapi_sprop->value.lpszA = sprop->value.lpszA;
729 if (!mapi_sprop->value.lpszA) return 0;
730 return (strlen(sprop->value.lpszA) + 1);
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));
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));
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));
744 mapi_sprop->value.err = sprop->value.err;
745 return sizeof(uint32_t);
750 b.data = sprop->value.lpguid->ab;
752 GUID_from_ndr_blob(&b, &mapi_sprop->value.lpguid);
753 return sizeof(struct GUID);
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));
764 mapi_sprop->value.MVszA.cValues = sprop->value.MVszA.cValues;
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;
780 mapi_sprop->value.MVszW.cValues = sprop->value.MVszW.cValues;
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);
796 mapi_sprop->value.MVbin.cValues = sprop->value.MVbin.cValues;
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);
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];
817 return sizeof(mapi_sprop->value.MVl.cValues) + (mapi_sprop->value.MVl.cValues * sizeof (uint32_t));
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;
830 GUID_from_ndr_blob(&b, &(mapi_sprop->value.MVguid.lpguid[i]));
832 return sizeof(mapi_sprop->value.MVguid.cValues) + (mapi_sprop->value.MVguid.cValues * sizeof (struct GUID));
835 printf("unhandled conversion case in cast_mapi_SPropValue(): 0x%x\n", (sprop->ulPropTag & 0xFFFF));
844 \details Convenience function to convert a mapi_SPropValue
845 structure into a SPropValue structure and return the associated
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
852 \return size of the converted data on success, otherwise 0
854 _PUBLIC_ uint32_t cast_SPropValue(TALLOC_CTX *mem_ctx,
855 struct mapi_SPropValue *mapi_sprop,
856 struct SPropValue *sprop)
858 sprop->ulPropTag = mapi_sprop->ulPropTag;
860 switch(sprop->ulPropTag & 0xFFFF) {
862 sprop->value.b = mapi_sprop->value.b;
863 return sizeof(uint8_t);
865 sprop->value.i = mapi_sprop->value.i;
866 return sizeof(uint16_t);
868 sprop->value.l = mapi_sprop->value.l;
869 return sizeof(uint32_t);
871 sprop->value.dbl = mapi_sprop->value.dbl;
872 return sizeof(double);
874 sprop->value.d = mapi_sprop->value.d;
875 return sizeof(uint64_t);
877 sprop->value.lpszA = mapi_sprop->value.lpszA;
878 if (!mapi_sprop->value.lpszA) return 0;
879 return (strlen(sprop->value.lpszA) + 1);
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));
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));
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));
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));
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));
906 sprop->value.err = (enum MAPISTATUS)mapi_sprop->value.err;
907 return sizeof(uint32_t);
913 sprop->value.MVl.cValues = mapi_sprop->value.MVl.cValues;
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);
928 sprop->value.MVszA.cValues = mapi_sprop->value.MVszA.cValues;
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;
943 sprop->value.MVszW.cValues = mapi_sprop->value.MVszW.cValues;
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]);
957 // conceptually we're copying mapi_SGuidArray over to FlatUIDArray_r
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;
966 sprop->value.MVguid.cValues = mapi_sprop->value.MVguid.cValues;
967 size += sizeof(uint32_t);
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) {
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));
985 sprop->value.MVbin.cValues = mapi_sprop->value.MVbin.cValues;
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);
996 sprop->value.MVbin.lpbin[i].lpb = NULL;
998 size += sizeof (uint32_t);
999 size += sprop->value.MVbin.lpbin[i].cb;
1004 printf("unhandled conversion case in cast_SPropValue(): 0x%x\n", (sprop->ulPropTag & 0xFFFF));
1005 OPENCHANGE_ASSERT();
1012 \details add a SPropValue structure to a SRow array
1014 \param aRow pointer to the SRow array where spropvalue should be
1016 \param spropvalue reference to the SPropValue structure to add to
1019 \return MAPI_E_SUCCESS on success, otherwise
1020 MAPI_E_INVALID_PARAMETER.
1022 _PUBLIC_ enum MAPISTATUS SRow_addprop(struct SRow *aRow, struct SPropValue spropvalue)
1024 TALLOC_CTX *mem_ctx;
1026 struct SPropValue lpProp;
1030 OPENCHANGE_RETVAL_IF(!aRow, MAPI_E_INVALID_PARAMETER, NULL);
1032 mem_ctx = (TALLOC_CTX *) aRow;
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;
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;
1051 return MAPI_E_SUCCESS;
1056 \details Append a SPropValue structure to given SRowSet
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
1062 \return 0 on success, otherwise 1
1064 _PUBLIC_ uint32_t SRowSet_propcpy(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, struct SPropValue spropvalue)
1068 struct SPropValue lpProp;
1071 if (!SRowSet) return 1;
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;
1086 _PUBLIC_ void mapi_SPropValue_array_named(mapi_object_t *obj,
1087 struct mapi_SPropValue_array *props)
1089 TALLOC_CTX *mem_ctx;
1090 enum MAPISTATUS retval;
1091 struct MAPINAMEID *nameid;
1096 mem_ctx = talloc_named(mapi_object_get_session(obj), 0, "mapi_SPropValue_array_named");
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;
1107 /* Display property given its propID */
1108 switch (nameid->ulKind) {
1110 props->lpProps[i].ulPropTag = (enum MAPITAGS)((nameid->kind.lid << 16) |
1111 ((int)props->lpProps[i].ulPropTag & 0x0000FFFF));
1114 /* MNID_STRING named properties don't have propIDs */
1118 talloc_free(nameid);
1122 talloc_free(mem_ctx);
1125 _PUBLIC_ enum MAPISTATUS get_mapi_SPropValue_array_date_timeval(struct timeval *t,
1126 struct mapi_SPropValue_array *properties,
1129 const struct FILETIME *filetime;
1132 filetime = (const struct FILETIME *) find_mapi_SPropValue_data(properties, mapitag);
1135 return MAPI_E_NOT_FOUND;
1138 time = filetime->dwHighDateTime;
1140 time |= filetime->dwLowDateTime;
1141 nttime_to_timeval(t, time);
1143 return MAPI_E_SUCCESS;
1146 _PUBLIC_ enum MAPISTATUS get_mapi_SPropValue_date_timeval(struct timeval *t,
1147 struct SPropValue lpProp)
1149 const struct FILETIME *filetime;
1152 filetime = (const struct FILETIME *) get_SPropValue_data(&lpProp);
1155 return MAPI_E_NOT_FOUND;
1158 time = filetime->dwHighDateTime;
1160 time |= filetime->dwLowDateTime;
1161 nttime_to_timeval(t, time);
1163 return MAPI_E_SUCCESS;
1166 _PUBLIC_ bool set_SPropValue_proptag_date_timeval(struct SPropValue *lpProps, enum MAPITAGS aulPropTag, const struct timeval *t)
1168 struct FILETIME filetime;
1171 time = timeval_to_nttime(t);
1173 filetime.dwLowDateTime = (time << 32) >> 32;
1174 filetime.dwHighDateTime = time >> 32;
1176 return set_SPropValue_proptag(lpProps, aulPropTag, &filetime);
1181 \details Retrieve a RecurrencePattern structure from a binary blob
1183 \param mem_ctx pointer to the memory context
1184 \param bin pointer to the Binary_r structure with non-mapped
1187 \return Allocated RecurrencePattern structure on success,
1190 \note Developers must free the allocated RecurrencePattern when
1193 _PUBLIC_ struct RecurrencePattern *get_RecurrencePattern(TALLOC_CTX *mem_ctx,
1194 struct Binary_r *bin)
1196 struct RecurrencePattern *RecurrencePattern = NULL;
1197 struct ndr_pull *ndr;
1198 enum ndr_err_code ndr_err_code;
1201 if (!bin) return NULL;
1202 if (!bin->cb) return NULL;
1203 if (!bin->lpb) return NULL;
1205 ndr = talloc_zero(mem_ctx, struct ndr_pull);
1207 ndr->data = bin->lpb;
1208 ndr->data_size = bin->cb;
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);
1216 if (ndr_err_code != NDR_ERR_SUCCESS) {
1217 talloc_free(RecurrencePattern);
1221 /*Copy DeletedInstanceDates and ModifiedInstanceDates into memory*/
1222 RecurrencePattern->DeletedInstanceDates = (uint32_t *) talloc_memdup(mem_ctx, RecurrencePattern->DeletedInstanceDates,
1223 sizeof(uint32_t) * RecurrencePattern->DeletedInstanceCount);
1225 RecurrencePattern->ModifiedInstanceDates = (uint32_t *) talloc_memdup(mem_ctx, RecurrencePattern->ModifiedInstanceDates,
1226 sizeof(uint32_t) * RecurrencePattern->ModifiedInstanceCount);
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);
1232 return RecurrencePattern;
1235 _PUBLIC_ size_t set_RecurrencePattern_size(const struct RecurrencePattern *rp)
1237 size_t size = SIZE_DFLT_RECURRENCEPATTERN;
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:
1252 DEBUG(0, ("%s: unrecognized pattern type: %d", __PRETTY_FUNCTION__, rp->PatternType));
1255 size += rp->DeletedInstanceCount * sizeof(uint32_t);
1256 size += rp->ModifiedInstanceCount * sizeof(uint32_t);
1261 _PUBLIC_ struct Binary_r *set_RecurrencePattern(TALLOC_CTX *mem_ctx, const struct RecurrencePattern *rp)
1263 struct Binary_r *bin = NULL;
1264 struct ndr_push *ndr;
1265 enum ndr_err_code ndr_err_code;
1269 if (!rp) return NULL;
1271 bin_size = set_RecurrencePattern_size(rp);
1272 bin = talloc_zero(mem_ctx, struct Binary_r);
1274 bin->lpb = talloc_array(bin, uint8_t, bin_size);
1276 ndr = talloc_zero(mem_ctx, struct ndr_push);
1278 ndr->data = bin->lpb;
1280 ndr_err_code = ndr_push_RecurrencePattern(ndr, NDR_SCALARS, rp);
1284 if (ndr_err_code != NDR_ERR_SUCCESS) {
1292 _PUBLIC_ struct AppointmentRecurrencePattern *get_AppointmentRecurrencePattern(TALLOC_CTX *mem_ctx,
1293 struct Binary_r *bin)
1295 struct AppointmentRecurrencePattern *arp = NULL;
1296 struct ndr_pull *ndr;
1297 enum ndr_err_code ndr_err_code;
1300 if (!bin) return NULL;
1301 if (!bin->cb) return NULL;
1302 if (!bin->lpb) return NULL;
1304 ndr = talloc_zero(mem_ctx, struct ndr_pull);
1306 ndr->data = bin->lpb;
1307 ndr->data_size = bin->cb;
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);
1315 if (ndr_err_code != NDR_ERR_SUCCESS) {
1320 /* Copy ExceptionInfo array into memory */
1321 arp->ExceptionInfo = (struct ExceptionInfo *) talloc_memdup(mem_ctx,arp->ExceptionInfo, sizeof(struct ExceptionInfo) * arp->ExceptionCount);
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);
1327 arp->RecurrencePattern.ModifiedInstanceDates = (uint32_t *) talloc_memdup(mem_ctx, arp->RecurrencePattern.ModifiedInstanceDates,
1328 sizeof(uint32_t) * arp->RecurrencePattern.ModifiedInstanceCount);
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);
1338 _PUBLIC_ size_t set_AppointmentRecurrencePattern_size(const struct AppointmentRecurrencePattern *arp)
1340 size_t size = SIZE_DFLT_APPOINTMENTRECURRENCEPATTERN;
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 +
1349 size += arp->ReservedBlock1Size * sizeof(uint32_t);
1350 /* size += arp->ReservedBlock2Size * sizeof(uint32_t); */
1355 _PUBLIC_ struct Binary_r *set_AppointmentRecurrencePattern(TALLOC_CTX *mem_ctx, const struct AppointmentRecurrencePattern *arp)
1357 struct Binary_r *bin = NULL;
1358 struct ndr_push *ndr;
1359 enum ndr_err_code ndr_err_code;
1363 if (!arp) return NULL;
1365 ndr = ndr_push_init_ctx(mem_ctx);
1366 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
1368 bin_size = set_AppointmentRecurrencePattern_size(arp);
1369 talloc_free(ndr->data);
1370 ndr->data = talloc_array(ndr, uint8_t, bin_size);
1372 ndr_err_code = ndr_push_AppointmentRecurrencePattern(ndr, NDR_SCALARS, arp);
1373 if (ndr_err_code != NDR_ERR_SUCCESS) {
1377 bin = talloc_zero(mem_ctx, struct Binary_r);
1379 bin->lpb = ndr->data;
1380 talloc_steal(bin, bin->lpb);
1387 _PUBLIC_ size_t set_ExceptionInfo_size(const struct ExceptionInfo *exc_info)
1389 size_t size = SIZE_DFLT_EXCEPTIONINFO;
1391 if ((exc_info->OverrideFlags & ARO_SUBJECT)) {
1392 size += 3 * sizeof(uint16_t); /* SubjectLength + SubjectLength2 + Subject */
1394 if ((exc_info->OverrideFlags & ARO_MEETINGTYPE)) {
1395 size += sizeof(uint32_t);
1397 if ((exc_info->OverrideFlags & ARO_REMINDERDELTA)) {
1398 size += sizeof(uint32_t);
1400 if ((exc_info->OverrideFlags & ARO_REMINDER)) {
1401 size += sizeof(uint32_t);
1403 if ((exc_info->OverrideFlags & ARO_LOCATION)) {
1404 size += 2 * sizeof(uint16_t); /* LocationLength + LocationLength2 */
1405 size += sizeof(uint32_t); /* Location */
1407 if ((exc_info->OverrideFlags & ARO_BUSYSTATUS)) {
1408 size += sizeof(uint32_t);
1410 if ((exc_info->OverrideFlags & ARO_ATTACHMENT)) {
1411 size += sizeof(uint32_t);
1413 if ((exc_info->OverrideFlags & ARO_SUBTYPE)) {
1414 size += sizeof(uint32_t);
1416 if ((exc_info->OverrideFlags & ARO_APPTCOLOR)) {
1417 size += sizeof(uint32_t);
1424 \details Retrieve a TimeZoneStruct structure from a binary blob
1426 \param mem_ctx pointer to the memory context
1427 \param bin pointer to the Binary_r structure with raw
1430 \return Allocated TimeZoneStruct structure on success, otherwise
1433 \note Developers must free the allocated TimeZoneStruct when
1436 _PUBLIC_ struct TimeZoneStruct *get_TimeZoneStruct(TALLOC_CTX *mem_ctx,
1437 struct Binary_r *bin)
1439 struct TimeZoneStruct *TimeZoneStruct = NULL;
1440 struct ndr_pull *ndr;
1441 enum ndr_err_code ndr_err_code;
1444 if (!bin) return NULL;
1445 if (!bin->cb) return NULL;
1446 if (!bin->lpb) return NULL;
1448 ndr = talloc_zero(mem_ctx, struct ndr_pull);
1450 ndr->data = bin->lpb;
1451 ndr->data_size = bin->cb;
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);
1459 if (ndr_err_code != NDR_ERR_SUCCESS) {
1460 talloc_free(TimeZoneStruct);
1464 return TimeZoneStruct;
1469 \details Retrieve a PtypServerId structure from a binary blob
1471 \param mem_ctx pointer to the memory context
1472 \param bin pointer to the Binary_r structure with raw PtypServerId data
1474 \return Allocated PtypServerId structure on success, otherwise
1477 \note Developers must free the allocated PtypServerId when
1480 _PUBLIC_ struct PtypServerId *get_PtypServerId(TALLOC_CTX *mem_ctx, struct Binary_r *bin)
1482 struct PtypServerId *PtypServerId = NULL;
1483 struct ndr_pull *ndr;
1484 enum ndr_err_code ndr_err_code;
1487 if (!bin) return NULL;
1488 if (!bin->cb) return NULL;
1489 if (!bin->lpb) return NULL;
1491 ndr = talloc_zero(mem_ctx, struct ndr_pull);
1493 ndr->data = bin->lpb;
1494 ndr->data_size = bin->cb;
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);
1502 if (ndr_err_code != NDR_ERR_SUCCESS) {
1503 talloc_free(PtypServerId);
1507 return PtypServerId;
1511 \details Retrieve a GlobalObjectId structure from a binary blob
1513 \param mem_ctx pointer to the memory context
1514 \param bin pointer to the Binary_r structure with raw
1517 \return Allocated GlobalObjectId structure on success, otherwise
1520 \note Developers must free the allocated GlobalObjectId when
1523 _PUBLIC_ struct GlobalObjectId *get_GlobalObjectId(TALLOC_CTX *mem_ctx,
1524 struct Binary_r *bin)
1526 struct GlobalObjectId *GlobalObjectId = NULL;
1527 struct ndr_pull *ndr;
1528 enum ndr_err_code ndr_err_code;
1531 if (!bin) return NULL;
1532 if (!bin->cb) return NULL;
1533 if (!bin->lpb) return NULL;
1535 ndr = talloc_zero(mem_ctx, struct ndr_pull);
1537 ndr->data = bin->lpb;
1538 ndr->data_size = bin->cb;
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);
1546 if (ndr_err_code != NDR_ERR_SUCCESS) {
1547 talloc_free(GlobalObjectId);
1551 return GlobalObjectId;
1555 \details Retrieve a MessageEntryId structure from a binary blob
1557 \param mem_ctx pointer to the memory context
1558 \param bin pointer to the Binary_r structure with raw
1561 \return Allocated MessageEntryId structure on success, otherwise
1564 \note Developers must free the allocated MessageEntryId when
1567 _PUBLIC_ struct MessageEntryId *get_MessageEntryId(TALLOC_CTX *mem_ctx, struct Binary_r *bin)
1569 struct MessageEntryId *MessageEntryId = NULL;
1570 struct ndr_pull *ndr;
1571 enum ndr_err_code ndr_err_code;
1574 if (!bin) return NULL;
1575 if (!bin->cb) return NULL;
1576 if (!bin->lpb) return NULL;
1578 ndr = talloc_zero(mem_ctx, struct ndr_pull);
1580 ndr->data = bin->lpb;
1581 ndr->data_size = bin->cb;
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);
1589 if (ndr_err_code != NDR_ERR_SUCCESS) {
1590 talloc_free(MessageEntryId);
1594 return MessageEntryId;
1598 \details Retrieve a FolderEntryId structure from a binary blob
1600 \param mem_ctx pointer to the memory context
1601 \param bin pointer to the Binary_r structure with raw FolderEntryId data
1603 \return Allocated FolderEntryId structure on success, otherwise
1606 \note Developers must free the allocated FolderEntryId when
1609 _PUBLIC_ struct FolderEntryId *get_FolderEntryId(TALLOC_CTX *mem_ctx, struct Binary_r *bin)
1611 struct FolderEntryId *FolderEntryId = NULL;
1612 struct ndr_pull *ndr;
1613 enum ndr_err_code ndr_err_code;
1616 if (!bin) return NULL;
1617 if (!bin->cb) return NULL;
1618 if (!bin->lpb) return NULL;
1620 ndr = talloc_zero(mem_ctx, struct ndr_pull);
1622 ndr->data = bin->lpb;
1623 ndr->data_size = bin->cb;
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);
1631 if (ndr_err_code != NDR_ERR_SUCCESS) {
1632 talloc_free(FolderEntryId);
1636 return FolderEntryId;
1640 \details Retrieve a AddressBookEntryId structure from a binary blob
1642 \param mem_ctx pointer to the memory context
1643 \param bin pointer to the Binary_r structure with raw AddressBookEntryId data
1645 \return Allocated AddressBookEntryId structure on success, otherwise NULL
1647 \note Developers must free the allocated AddressBookEntryId when finished.
1649 _PUBLIC_ struct AddressBookEntryId *get_AddressBookEntryId(TALLOC_CTX *mem_ctx, struct Binary_r *bin)
1651 struct AddressBookEntryId *AddressBookEntryId = NULL;
1652 struct ndr_pull *ndr;
1653 enum ndr_err_code ndr_err_code;
1656 if (!bin) return NULL;
1657 if (!bin->cb) return NULL;
1658 if (!bin->lpb) return NULL;
1660 ndr = talloc_zero(mem_ctx, struct ndr_pull);
1662 ndr->data = bin->lpb;
1663 ndr->data_size = bin->cb;
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);
1671 if (ndr_err_code != NDR_ERR_SUCCESS) {
1672 talloc_free(AddressBookEntryId);
1676 return AddressBookEntryId;
1680 \details Return the effective value used in a TypedString
1683 \param tstring pointer to TypedString structure
1685 \return pointer to a valid string on success, otherwise NULL
1687 _PUBLIC_ const char *get_TypedString(struct TypedString *tstring)
1689 if (!tstring) return NULL;
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:
1708 \details Return the expected size of the utf8 string after
1709 conversion to utf16 by iconv() function.
1711 \param inbuf pointer to the input string
1713 \return expected length of the converted string
1715 \note This routine is based upon utf8_pull() function from
1716 samba4/lib/util/charset/iconv.c
1718 size_t get_utf8_utf16_conv_length(const char *inbuf)
1723 const uint8_t *c = (const uint8_t *) inbuf;
1726 if (!inbuf) return 0;
1728 in_left = strlen(inbuf);
1730 out_left = ( out_left * 3);
1731 /* includes null-termination bytes */
1732 max_out = out_left + 2;
1734 while (in_left >= 1 && out_left >= 2) {
1735 if ((c[0] & 0x80) == 0) {
1742 if ((c[0] & 0xe0) == 0xc0) {
1743 if (in_left < 2 || (c[1] & 0xc0) != 0x80) {
1752 if ((c[0] & 0xf0) == 0xe0) {
1754 (c[1] & 0xc0) != 0x80 ||
1755 (c[2] & 0xc0) != 0x80) {
1764 if ((c[0] & 0xf8) == 0xf0) {
1765 unsigned int codepoint;
1767 (c[1] & 0xc0) != 0x80 ||
1768 (c[2] & 0xc0) != 0x80 ||
1769 (c[3] & 0xc0) != 0x80) {
1777 if (codepoint < 0x10000) {
1784 codepoint -= 0x10000;
1796 /* we don't handle 5 byte sequences */
1804 return (max_out - out_left);
1807 struct PropertyValue_r* get_PropertyValue_PropertyRow(struct PropertyRow_r *aRow, enum MAPITAGS ulPropTag)
1815 for (i = 0; i < aRow->cValues; i++) {
1816 if (ulPropTag == aRow->lpProps[i].ulPropTag) {
1817 return (&aRow->lpProps[i]);
1824 _PUBLIC_ struct PropertyValue_r *get_PropertyValue_PropertyRowSet(struct PropertyRowSet_r *RowSet,
1825 enum MAPITAGS ulPropTag)
1831 if (!RowSet) return NULL;
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]);
1844 _PUBLIC_ const void *get_PropertyValue_PropertyRowSet_data(struct PropertyRowSet_r *RowSet,
1847 struct PropertyValue_r *lpProp;
1849 lpProp = get_PropertyValue_PropertyRowSet(RowSet, ulPropTag);
1850 return get_PropertyValue(lpProp, ulPropTag);
1853 _PUBLIC_ bool set_PropertyValue(struct PropertyValue_r *lpProp, const void *data)
1856 lpProp->ulPropTag = (lpProp->ulPropTag & 0xffff0000) | PT_ERROR;
1857 lpProp->value.err = MAPI_E_NOT_FOUND;
1860 switch (lpProp->ulPropTag & 0xFFFF) {
1862 lpProp->value.i = *((const uint16_t *)data);
1865 lpProp->value.b = *((const uint8_t *)data);
1868 lpProp->value.l = *((const uint32_t *)data);
1871 lpProp->value.lpszA = (const char *) data;
1875 lpProp->value.bin = *((const struct Binary_r *)data);
1878 lpProp->value.lpszW = (const char *) data;
1881 lpProp->value.lpguid = (struct FlatUID_r *) data;
1884 lpProp->value.ft = *((const struct FILETIME *) data);
1887 lpProp->value.err = *((enum MAPISTATUS *)data);
1890 lpProp->value.MVi = *((const struct ShortArray_r *)data);
1893 lpProp->value.MVl = *((const struct LongArray_r *)data);
1896 lpProp->value.MVszA = *((const struct StringArray_r *)data);
1899 lpProp->value.MVbin = *((const struct BinaryArray_r *)data);
1902 lpProp->value.MVguid = *((const struct FlatUIDArray_r *)data);
1905 lpProp->value.MVszW = *((const struct StringArrayW_r *)data);
1908 lpProp->value.MVft = *((const struct DateTimeArray_r *)data);
1911 lpProp->value.null = *((const uint32_t *)data);
1914 lpProp->ulPropTag = (lpProp->ulPropTag & 0xffff0000) | PT_ERROR;
1915 lpProp->value.err = MAPI_E_NOT_FOUND;
1923 _PUBLIC_ const void *get_PropertyValue(struct PropertyValue_r *lpProps, enum MAPITAGS ulPropTag)
1928 if (!lpProps) return NULL;
1930 for (i = 0; lpProps[i].ulPropTag; i++) {
1931 if (ulPropTag == lpProps[i].ulPropTag) {
1932 return get_PropertyValue_data(&lpProps[i]);
1938 _PUBLIC_ const void *get_PropertyValue_data(struct PropertyValue_r *lpProps)
1940 if (lpProps->ulPropTag == 0) {
1944 switch(lpProps->ulPropTag & 0xFFFF) {
1946 return (const void *)&lpProps->value.i;
1948 return (const void *)&lpProps->value.b;
1950 return (const void *)lpProps->value.lpszA;
1952 return (const void *)lpProps->value.lpszW;
1954 return (const void *)(struct FILETIME *)&lpProps->value.ft;
1956 return (const void *)&lpProps->value.err;
1958 return (const void *)&lpProps->value.l;
1960 return (const void *)lpProps->value.lpguid;
1963 return (const void *)&lpProps->value.bin;
1965 return (const void *)(struct ShortArray_r *)&lpProps->value.MVi;
1967 return (const void *)(struct LongArray_r *)&lpProps->value.MVl;
1969 return (const void *)(struct StringArray_r *)&lpProps->value.MVszA;
1971 return (const void *)(struct StringArrayW_r *)&lpProps->value.MVszW;
1973 return (const void *)(struct BinaryArray_r *)&lpProps->value.MVbin;
1975 return (const void *)(struct DateTimeArray_r *)&lpProps->value.MVft;
1977 return (const void *)&lpProps->value.null;
1984 \details add a PropertyValue_r structure to a PropertyRow_r array
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
1989 \return MAPI_E_SUCCESS on success, otherwise MAPI_E_INVALID_PARAMETER.
1991 _PUBLIC_ enum MAPISTATUS PropertyRow_addprop(struct PropertyRow_r *aRow, struct PropertyValue_r propValue)
1993 TALLOC_CTX *mem_ctx;
1995 struct PropertyValue_r lpProp;
1999 OPENCHANGE_RETVAL_IF(!aRow, MAPI_E_INVALID_PARAMETER, NULL);
2001 mem_ctx = (TALLOC_CTX *) aRow;
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;
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;
2020 return MAPI_E_SUCCESS;
2023 _PUBLIC_ const void *find_PropertyValue_data(struct PropertyRow_r *aRow, uint32_t mapitag)
2031 for (i = 0; i < aRow->cValues; i++) {
2032 if (aRow->lpProps[i].ulPropTag == mapitag) {
2033 return get_PropertyValue_data(&(aRow->lpProps[i]));
2040 \details Append a PropertyValue_r structure to given PropertyRowSet_r
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
2046 \return 0 on success, otherwise 1
2048 _PUBLIC_ uint32_t PropertyRowSet_propcpy(TALLOC_CTX *mem_ctx, struct PropertyRowSet_r *RowSet, struct PropertyValue_r value)
2052 struct PropertyValue_r lpProp;
2055 if (!RowSet) return 1;
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;
2071 \details Convenience function to convert a PropertyValue_r structure into a SPropValue structure.
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
2076 _PUBLIC_ void cast_PropertyValue_to_SPropValue(struct PropertyValue_r *propvalue, struct SPropValue *spropvalue)
2078 spropvalue->ulPropTag = propvalue->ulPropTag;
2080 switch (propvalue->ulPropTag & 0xFFFF) {
2082 spropvalue->value.b = propvalue->value.b;
2085 spropvalue->value.i = propvalue->value.i;
2088 spropvalue->value.l = propvalue->value.l;
2091 spropvalue->value.lpszA = propvalue->value.lpszA;
2094 spropvalue->value.lpszW = propvalue->value.lpszW;
2097 propvalue->value.ft = propvalue->value.ft;
2100 spropvalue->value.lpguid = propvalue->value.lpguid;
2104 spropvalue->value.bin = propvalue->value.bin;
2107 spropvalue->value.err = propvalue->value.err;
2110 spropvalue->value.MVl = propvalue->value.MVl;
2113 spropvalue->value.MVszA = propvalue->value.MVszA;
2116 spropvalue->value.MVszW = propvalue->value.MVszW;
2119 spropvalue->value.MVguid = propvalue->value.MVguid;
2122 spropvalue->value.MVbin = propvalue->value.MVbin;
2125 printf("unhandled conversion case in cast_PropvalueValue(): 0x%x\n", (propvalue->ulPropTag & 0xFFFF));
2126 OPENCHANGE_ASSERT();
2131 \details Convenience function to convert a PropertyRow_r structure into a SRow structure.
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
2137 _PUBLIC_ void cast_PropertyRow_to_SRow(TALLOC_CTX *mem_ctx, struct PropertyRow_r *proprow, struct SRow *srow)
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);
2149 \details Convenience function to convert a PropertyRowSet_r structure into a SRowSet structure.
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
2155 _PUBLIC_ void cast_PropertyRowSet_to_SRowSet(TALLOC_CTX *mem_ctx, struct PropertyRowSet_r *prowset, struct SRowSet *srowset)
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);