2 OpenChange MAPI implementation.
4 Copyright (C) Julien Kerihuel 2005 - 2008.
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/proto_private.h>
23 #include <libmapi/mapitags.h>
24 #include <gen_ndr/ndr_property.h>
30 \brief Functions for manipulating MAPI properties
33 _PUBLIC_ struct SPropTagArray *set_SPropTagArray(TALLOC_CTX *mem_ctx,
34 uint32_t PropCount, ...)
36 struct SPropTagArray *SPropTagArray;
41 aulPropTag = talloc_array(mem_ctx, uint32_t, PropCount);
43 va_start(ap, PropCount);
44 for (i = 0; i < PropCount; i++) {
45 aulPropTag[i] = va_arg(ap, int);
49 SPropTagArray = talloc(mem_ctx, struct SPropTagArray);
50 SPropTagArray->aulPropTag = aulPropTag;
51 SPropTagArray->cValues = PropCount;
56 \details Add a property tag to an existing properties array
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
62 \return MAPI_E_SUCCESS on success, otherwise -1.
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
69 _PUBLIC_ enum MAPISTATUS SPropTagArray_add(TALLOC_CTX *mem_ctx,
70 struct SPropTagArray *SPropTagArray,
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);
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;
82 return MAPI_E_SUCCESS;
85 _PUBLIC_ const void *get_SPropValue(struct SPropValue *lpProps,
90 for (i = 0; lpProps[i].ulPropTag; i++) {
91 if (ulPropTag == lpProps[i].ulPropTag) {
92 return get_SPropValue_data(&lpProps[i]);
98 _PUBLIC_ struct SPropValue *get_SPropValue_SRowSet(struct SRowSet *RowSet,
105 if (!RowSet) return NULL;
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]);
118 _PUBLIC_ const void *get_SPropValue_SRowSet_data(struct SRowSet *RowSet,
121 struct SPropValue *lpProp;
123 lpProp = get_SPropValue_SRowSet(RowSet, ulPropTag);
124 return get_SPropValue(lpProp, ulPropTag);
127 _PUBLIC_ enum MAPISTATUS set_default_error_SPropValue_SRow(struct SRow *aRow, uint32_t ulPropTag, void *data)
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;
138 return MAPI_E_NOT_FOUND;
141 _PUBLIC_ struct SPropValue *get_SPropValue_SRow(struct SRow *aRow,
146 for (i = 0; i < aRow->cValues; i++) {
147 if (ulPropTag == aRow->lpProps[i].ulPropTag) {
148 return (&aRow->lpProps[i]);
155 _PUBLIC_ const void *get_SPropValue_SRow_data(struct SRow *aRow,
158 struct SPropValue *lpProp;
160 lpProp = get_SPropValue_SRow(aRow, ulPropTag);
161 return get_SPropValue(lpProp, ulPropTag);
165 Create a MAPITAGS array from a SRow entry
168 enum MAPITAGS *get_MAPITAGS_SRow(TALLOC_CTX *mem_ctx, struct SRow *aRow)
170 enum MAPITAGS *mapitags;
173 mapitags = talloc_array(mem_ctx, enum MAPITAGS, aRow->cValues + 1);
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;
186 Remove MAPITAGS entries from a MAPITAGS array
189 uint32_t MAPITAGS_delete_entries(enum MAPITAGS *mapitags, uint32_t final_count, uint32_t PropCount, ...)
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]) {
202 for (j = count; mapitags[j]; j++) {
203 mapitags[j] = (mapitags[j+1]) ? mapitags[j+1] : 0;
213 _PUBLIC_ const void *find_SPropValue_data(struct SRow *aRow, uint32_t mapitag)
217 for (i = 0; i < aRow->cValues; i++) {
218 if (aRow->lpProps[i].ulPropTag == mapitag) {
219 return get_SPropValue_data(&(aRow->lpProps[i]));
225 _PUBLIC_ const void *find_mapi_SPropValue_data(
226 struct mapi_SPropValue_array *properties, uint32_t mapitag)
230 for (i = 0; i < properties->cValues; i++) {
231 if (properties->lpProps[i].ulPropTag == mapitag) {
232 return get_mapi_SPropValue_data(&properties->lpProps[i]);
238 _PUBLIC_ const void *get_mapi_SPropValue_data(struct mapi_SPropValue *lpProp)
240 if (lpProp->ulPropTag == 0) {
243 switch(lpProp->ulPropTag & 0xFFFF) {
245 return (const void *)(uint8_t *)&lpProp->value.b;
247 return (const void *)(uint16_t *)&lpProp->value.i;
249 return (const void *)&lpProp->value.l;
251 return (const void *)&lpProp->value.dbl;
253 return (const void *)&lpProp->value.d;
255 return (const void *)(struct FILETIME *)&lpProp->value.ft;
257 return (const void *)&lpProp->value.err;
259 return (const void *)lpProp->value.lpszA;
261 return (const void *)lpProp->value.lpszW;
263 return (const void *)(struct SBinary_short *)&lpProp->value.bin;
265 return (const void *)(struct mapi_MV_LONG_STRUCT *)&lpProp->value.MVl;
267 return (const void *)(struct mapi_SLPSTRArray *)&lpProp->value.MVszA;
269 return (const void *)(struct mapi_SBinaryArray *)&lpProp->value.MVbin;
275 _PUBLIC_ const void *get_SPropValue_data(struct SPropValue *lpProps)
277 if (lpProps->ulPropTag == 0) {
281 switch(lpProps->ulPropTag & 0xFFFF) {
283 return (const void *)&lpProps->value.b;
285 return (const void *)&lpProps->value.d;
287 return (const void *)lpProps->value.lpszA;
289 return (const void *)lpProps->value.lpszW;
291 return (const void *)(struct FILETIME *)&lpProps->value.ft;
293 return (const void *)&lpProps->value.err;
295 return (const void *)&lpProps->value.l;
297 return (const void *)&lpProps->value.dbl;
299 return (const void *)(struct GUID *)&lpProps->value.lpguid;
301 return (const void *)&lpProps->value.bin;
303 return (const void *)(struct LongArray_r *)&lpProps->value.MVl;
305 return (const void *)(struct StringArray_r *)&lpProps->value.MVszA;
307 return (const void *)(struct BinaryArray_r *)&lpProps->value.MVbin;
313 _PUBLIC_ bool set_SPropValue_proptag(struct SPropValue *lpProps, uint32_t aulPropTag, const void *data)
315 lpProps->ulPropTag = aulPropTag;
316 lpProps->dwAlignPad = 0x0;
318 return (set_SPropValue(lpProps, data));
321 _PUBLIC_ struct SPropValue *add_SPropValue(TALLOC_CTX *mem_ctx, struct SPropValue *lpProps, uint32_t *cValues, uint32_t aulPropTag, const void * data)
323 lpProps = talloc_realloc(mem_ctx, lpProps, struct SPropValue, *cValues + 2);
325 set_SPropValue_proptag(&lpProps[*cValues], aulPropTag, data);
326 *cValues = *cValues + 1;
331 _PUBLIC_ bool set_SPropValue(struct SPropValue *lpProps, const void *data)
334 lpProps->value.err = MAPI_E_NOT_FOUND;
337 switch (lpProps->ulPropTag & 0xFFFF) {
339 lpProps->value.i = *((const uint16_t *)data);
342 lpProps->value.l = *((const uint32_t *)data);
345 lpProps->value.d = *((const uint64_t *)data);
348 lpProps->value.b = *((const uint8_t *)data);
351 lpProps->value.lpszA = (const char *) data;
354 lpProps->value.bin = *((const struct Binary_r *)data);
357 lpProps->value.lpszW = (const char *) data;
360 lpProps->value.lpguid = (struct FlatUID_r *) data;
363 lpProps->value.ft = *((const struct FILETIME *) data);
366 lpProps->value.err = *((const uint32_t *)data);
369 lpProps->value.err = *((const uint32_t *)data);
372 lpProps->value.MVl = *((const struct LongArray_r *)data);
375 lpProps->value.MVszA = *((const struct StringArray_r *)data);
378 lpProps->value.MVbin = *((const struct BinaryArray_r *)data);
381 lpProps->value.MVguid = *((const struct FlatUIDArray_r *)data);
384 lpProps->value.MVszW = *((const struct WStringArray_r *)data);
387 lpProps->value.MVft = *((const struct DateTimeArray_r *)data);
390 lpProps->value.null = *((const uint32_t *)data);
393 lpProps->value.null = *((const uint32_t *)data);
396 lpProps->value.err = MAPI_E_NOT_FOUND;
404 _PUBLIC_ uint32_t get_mapi_property_size(struct mapi_SPropValue *lpProp)
406 switch(lpProp->ulPropTag & 0xFFFF) {
408 return sizeof (uint8_t);
410 return sizeof (uint16_t);
413 return sizeof (uint32_t);
416 return sizeof (uint64_t);
418 return strlen(lpProp->value.lpszA) + 1;
420 return strlen(lpProp->value.lpszW) * 2 + 2;
422 return sizeof (struct FILETIME);
424 return (lpProp->value.bin.cb + sizeof(uint16_t));
430 convenient function which cast a SPropValue structure in a mapi_SPropValue one and return the associated size
433 _PUBLIC_ uint32_t cast_mapi_SPropValue(struct mapi_SPropValue *mapi_sprop, struct SPropValue *sprop)
435 mapi_sprop->ulPropTag = sprop->ulPropTag;
437 switch(sprop->ulPropTag & 0xFFFF) {
439 mapi_sprop->value.b = sprop->value.b;
440 return sizeof(uint8_t);
442 mapi_sprop->value.i = sprop->value.i;
443 return sizeof(uint16_t);
445 mapi_sprop->value.l = sprop->value.l;
446 return sizeof(uint32_t);
448 mapi_sprop->value.dbl = sprop->value.dbl;
449 return sizeof(uint64_t);
451 mapi_sprop->value.lpszA = sprop->value.lpszA;
452 if (!mapi_sprop->value.lpszA) return 0;
453 return (strlen(sprop->value.lpszA) + 1);
455 mapi_sprop->value.lpszW = sprop->value.lpszW;
456 if (!mapi_sprop->value.lpszW) return 0;
457 return (strlen(sprop->value.lpszW) * 2 + 2);
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));
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));
471 mapi_sprop->value.MVszA.cValues = sprop->value.MVszA.cValues;
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;
489 _PUBLIC_ uint32_t cast_SPropValue(struct mapi_SPropValue *mapi_sprop, struct SPropValue *sprop)
491 sprop->ulPropTag = mapi_sprop->ulPropTag;
493 switch(sprop->ulPropTag & 0xFFFF) {
495 sprop->value.b = mapi_sprop->value.b;
496 return sizeof(uint8_t);
498 sprop->value.i = mapi_sprop->value.i;
499 return sizeof(uint16_t);
501 sprop->value.l = mapi_sprop->value.l;
502 return sizeof(uint32_t);
504 sprop->value.dbl = mapi_sprop->value.dbl;
505 return sizeof(uint64_t);
507 sprop->value.lpszA = mapi_sprop->value.lpszA;
508 if (!mapi_sprop->value.lpszA) return 0;
509 return (strlen(sprop->value.lpszA) + 1);
511 sprop->value.lpszW = mapi_sprop->value.lpszW;
512 if (!sprop->value.lpszW) return 0;
513 return (strlen(mapi_sprop->value.lpszW) * 2 + 2);
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));
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));
528 sprop->value.MVszA.cValues = mapi_sprop->value.MVszA.cValues;
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;
543 _PUBLIC_ enum MAPISTATUS SRow_addprop(struct SRow *aRow, struct SPropValue SPropValue)
547 struct SPropValue lpProp;
550 MAPI_RETVAL_IF(!aRow, MAPI_E_INVALID_PARAMETER, NULL);
552 mem_ctx = (TALLOC_CTX *) aRow;
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;
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;
571 return MAPI_E_SUCCESS;
574 _PUBLIC_ uint32_t SRowSet_propcpy(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, struct SPropValue SPropValue)
578 struct SPropValue lpProp;
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;
593 _PUBLIC_ void mapi_SPropValue_array_named(mapi_object_t *obj,
594 struct mapi_SPropValue_array *props)
597 enum MAPISTATUS retval;
598 struct MAPINAMEID *nameid;
603 mem_ctx = talloc_init("mapi_SPropValue_array_named");
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;
614 /* Display property given its propID */
615 switch (nameid->ulKind) {
617 props->lpProps[i].ulPropTag = (nameid->kind.lid << 16) |
618 (props->lpProps[i].ulPropTag & 0x0000FFFF);
621 /* MNID_STRING named properties don't have propIDs */
629 talloc_free(mem_ctx);
632 _PUBLIC_ enum MAPISTATUS get_mapi_SPropValue_array_date_timeval(struct timeval *t,
633 struct mapi_SPropValue_array *properties,
636 const struct FILETIME *filetime;
639 filetime = (const struct FILETIME *) find_mapi_SPropValue_data(properties, mapitag);
642 return MAPI_E_NOT_FOUND;
645 time = filetime->dwHighDateTime;
647 time |= filetime->dwLowDateTime;
648 nttime_to_timeval(t, time);
650 return MAPI_E_SUCCESS;
653 _PUBLIC_ enum MAPISTATUS get_mapi_SPropValue_date_timeval(struct timeval *t,
654 struct SPropValue lpProp)
656 const struct FILETIME *filetime;
659 filetime = (const struct FILETIME *) get_SPropValue_data(&lpProp);
662 return MAPI_E_NOT_FOUND;
665 time = filetime->dwHighDateTime;
667 time |= filetime->dwLowDateTime;
668 nttime_to_timeval(t, time);
670 return MAPI_E_SUCCESS;
673 _PUBLIC_ bool set_SPropValue_proptag_date_timeval(struct SPropValue *lpProps, uint32_t aulPropTag, const struct timeval *t)
675 struct FILETIME filetime;
678 time = timeval_to_nttime(t);
680 filetime.dwLowDateTime = (time << 32) >> 32;
681 filetime.dwHighDateTime = time >> 32;
683 return set_SPropValue_proptag(lpProps, aulPropTag, &filetime);
688 \details Retrieve a RecurrencePattern structure from a binary blob
690 \param mem_ctx pointer to the memory context
691 \param bin pointer to the Binary_r structure with non-mapped
694 \return Allocated RecurrencePattern structure on success,
697 \note Developers must free the allocated RecurrencePattern when
700 _PUBLIC_ struct RecurrencePattern *get_RecurrencePattern(TALLOC_CTX *mem_ctx,
701 struct Binary_r *bin)
703 struct RecurrencePattern *RecurrencePattern = NULL;
704 struct ndr_pull *ndr;
705 enum ndr_err_code ndr_err_code;
708 if (!bin) return NULL;
709 if (!bin->cb) return NULL;
710 if (!bin->lpb) return NULL;
712 ndr = talloc_zero(mem_ctx, struct ndr_pull);
714 ndr->data = bin->lpb;
715 ndr->data_size = bin->cb;
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);
724 if (ndr_err_code != NDR_ERR_SUCCESS) {
725 talloc_free(RecurrencePattern);
729 return RecurrencePattern;
734 \details Retrieve a TimeZoneStruct structure from a binary blob
736 \param mem_ctx pointer to the memory context
737 \param bin pointer to the Binary_r structure with raw
740 \return Allocated TimeZoneStruct structure on success, otherwise
743 \note Developers must free the allocated TimeZoneStruct when
746 _PUBLIC_ struct TimeZoneStruct *get_TimeZoneStruct(TALLOC_CTX *mem_ctx,
747 struct Binary_r *bin)
749 struct TimeZoneStruct *TimeZoneStruct = NULL;
750 struct ndr_pull *ndr;
751 enum ndr_err_code ndr_err_code;
754 if (!bin) return NULL;
755 if (!bin->cb) return NULL;
756 if (!bin->lpb) return NULL;
758 ndr = talloc_zero(mem_ctx, struct ndr_pull);
760 ndr->data = bin->lpb;
761 ndr->data_size = bin->cb;
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);
770 if (ndr_err_code != NDR_ERR_SUCCESS) {
771 talloc_free(TimeZoneStruct);
775 return TimeZoneStruct;
780 \details Retrieve a GlobalObjectId structure from a binary blob
782 \param mem_ctx pointer to the memory context
783 \param bin pointer to the Binary_r structure with raw
786 \return Allocated GlobalObjectId structure on success, otherwise
789 \note Developers must free the allocated GlobalObjectId when
792 _PUBLIC_ struct GlobalObjectId *get_GlobalObjectId(TALLOC_CTX *mem_ctx,
793 struct Binary_r *bin)
795 struct GlobalObjectId *GlobalObjectId = NULL;
796 struct ndr_pull *ndr;
797 enum ndr_err_code ndr_err_code;
800 if (!bin) return NULL;
801 if (!bin->cb) return NULL;
802 if (!bin->lpb) return NULL;
804 ndr = talloc_zero(mem_ctx, struct ndr_pull);
806 ndr->data = bin->lpb;
807 ndr->data_size = bin->cb;
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);
816 if (ndr_err_code != NDR_ERR_SUCCESS) {
817 talloc_free(GlobalObjectId);
821 return GlobalObjectId;