19#include <winpr/assert.h> 
   20#include <winpr/collections.h> 
   21#include <winpr/wlog.h> 
   23#include <freerdp/log.h> 
   25#include <rdpear-common/ndr.h> 
   27#define TAG FREERDP_TAG("ndr") 
   29#define NDR_MAX_CONSTRUCTS 16 
   30#define NDR_MAX_DEFERRED 50 
   39  size_t indentLevels[16];
 
   42  size_t constructs[NDR_MAX_CONSTRUCTS];
 
   44  wHashTable* refPointers;
 
   51NdrContext* ndr_context_new(BOOL bigEndianDrep, BYTE version)
 
   53  NdrContext* ret = calloc(1, 
sizeof(*ret));
 
   57  ret->version = version;
 
   58  ret->bigEndianDrep = bigEndianDrep;
 
   60  ret->refPointers = HashTable_New(FALSE);
 
   61  if (!ret->refPointers)
 
   67  ndr_context_reset(ret);
 
   71void ndr_context_reset(NdrContext* context)
 
   73  WINPR_ASSERT(context);
 
   75  context->currentLevel = 0;
 
   76  context->constructLevel = -1;
 
   77  memset(context->indentLevels, 0, 
sizeof(context->indentLevels));
 
   79  if (context->refPointers)
 
   80    HashTable_Clear(context->refPointers);
 
   81  context->ndeferred = 0;
 
   82  context->refIdCounter = 0x20000;
 
   85NdrContext* ndr_context_copy(
const NdrContext* src)
 
   89  NdrContext* ret = calloc(1, 
sizeof(*ret));
 
   95  ret->refPointers = HashTable_New(FALSE);
 
   96  if (!ret->refPointers)
 
  102  ndr_context_reset(ret);
 
  106void ndr_context_free(NdrContext* context)
 
  110    HashTable_Free(context->refPointers);
 
  115static void ndr_context_bytes_read(NdrContext* context, 
size_t len)
 
  117  WINPR_ASSERT(context);
 
  118  context->indentLevels[context->currentLevel] += len;
 
  121static void ndr_context_bytes_written(NdrContext* context, 
size_t len)
 
  123  ndr_context_bytes_read(context, len);
 
  126NdrContext* ndr_read_header(
wStream* s)
 
  128  if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
 
  131  BYTE version = Stream_Get_UINT8(s);
 
  132  BYTE drep = Stream_Get_UINT8(s);
 
  133  UINT16 headerLen = Stream_Get_UINT16(s);
 
  135  if (headerLen < 4 || !Stream_CheckAndLogRequiredLength(TAG, s, headerLen - 4))
 
  139  Stream_Seek(s, headerLen - 4);
 
  141  return ndr_context_new((drep != 0x10), version);
 
  144BOOL ndr_write_header(NdrContext* context, 
wStream* s)
 
  146  WINPR_ASSERT(context);
 
  148  if (!Stream_EnsureRemainingCapacity(s, 8))
 
  151  Stream_Write_UINT8(s, context->version);
 
  152  Stream_Write_UINT8(s, context->bigEndianDrep ? 0x00 : 0x10);
 
  153  Stream_Write_UINT16(s, 0x8); 
 
  155  BYTE filler[] = { 0xcc, 0xcc, 0xcc, 0xcc };
 
  156  Stream_Write(s, filler, 
sizeof(filler));
 
  160BOOL ndr_skip_bytes(NdrContext* context, 
wStream* s, 
size_t nbytes)
 
  162  WINPR_ASSERT(context);
 
  164  if (!Stream_CheckAndLogRequiredLength(TAG, s, nbytes))
 
  167  context->indentLevels[context->currentLevel] += nbytes;
 
  168  Stream_Seek(s, nbytes);
 
  172BOOL ndr_read_align(NdrContext* context, 
wStream* s, 
size_t sz)
 
  174  WINPR_ASSERT(context);
 
  176  size_t rest = context->indentLevels[context->currentLevel] % sz;
 
  179    size_t padding = (sz - rest);
 
  180    if (!Stream_CheckAndLogRequiredLength(TAG, s, padding))
 
  183    Stream_Seek(s, padding);
 
  184    context->indentLevels[context->currentLevel] += padding;
 
  190BOOL ndr_write_align(NdrContext* context, 
wStream* s, 
size_t sz)
 
  192  WINPR_ASSERT(context);
 
  194  size_t rest = context->indentLevels[context->currentLevel] % sz;
 
  197    size_t padding = (sz - rest);
 
  199    if (!Stream_EnsureRemainingCapacity(s, padding))
 
  202    Stream_Zero(s, padding);
 
  203    context->indentLevels[context->currentLevel] += padding;
 
  209BOOL ndr_read_pickle(NdrContext* context, 
wStream* s)
 
  211  WINPR_ASSERT(context);
 
  216  if (!ndr_read_uint32(context, s, &v) || v != 0x20000)
 
  219  return ndr_read_uint32(context, s, &v); 
 
  222BOOL ndr_write_pickle(NdrContext* context, 
wStream* s)
 
  224  WINPR_ASSERT(context);
 
  227  if (!ndr_write_uint32(context, s, 0x20000))
 
  230  ndr_write_uint32(context, s, 0); 
 
  234BOOL ndr_read_constructed(NdrContext* context, 
wStream* s, 
wStream* target)
 
  236  WINPR_ASSERT(context);
 
  241  if (!ndr_read_uint32(context, s, &len))
 
  245  if (!ndr_skip_bytes(context, s, 4))
 
  249  if (!Stream_CheckAndLogRequiredLength(TAG, s, len))
 
  252  Stream_StaticInit(target, Stream_PointerAs(s, BYTE), len);
 
  257BOOL ndr_start_constructed(NdrContext* context, 
wStream* s)
 
  259  WINPR_ASSERT(context);
 
  261  if (!Stream_EnsureRemainingCapacity(s, 8))
 
  264  if (context->constructLevel == NDR_MAX_CONSTRUCTS)
 
  267  context->constructLevel++;
 
  268  context->constructs[context->constructLevel] = Stream_GetPosition(s);
 
  274BOOL ndr_end_constructed(NdrContext* context, 
wStream* s)
 
  276  WINPR_ASSERT(context);
 
  277  WINPR_ASSERT(context->constructs);
 
  278  WINPR_ASSERT(context->constructLevel >= 0);
 
  280  size_t offset = context->constructs[context->constructLevel];
 
  283  Stream_StaticInit(&staticS, Stream_Buffer(s) + offset, 4);
 
  286  const size_t len = Stream_GetPosition(s) - (offset + 8);
 
  287  if (len > UINT32_MAX)
 
  289  if (!ndr_write_uint32(context, &staticS, (UINT32)len))
 
  295static size_t ndr_hintsCount(
NdrMessageType msgType, 
const void* hints)
 
  297  WINPR_ASSERT(msgType);
 
  299  switch (msgType->arity)
 
  301    case NDR_ARITY_SIMPLE:
 
  303    case NDR_ARITY_ARRAYOF:
 
  306    case NDR_ARITY_VARYING_ARRAYOF:
 
  310      WINPR_ASSERT(0 && 
"unknown arity");
 
  315BOOL ndr_read_uint8(NdrContext* context, 
wStream* s, BYTE* v)
 
  317  WINPR_ASSERT(context);
 
  319  if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
 
  322  Stream_Read_UINT8(s, *v);
 
  324  ndr_context_bytes_read(context, 1);
 
  328BOOL ndr_read_uint8_(NdrContext* context, 
wStream* s, 
const void* hints, 
void* v)
 
  331  return ndr_read_uint8(context, s, (BYTE*)v);
 
  334BOOL ndr_write_uint8(NdrContext* context, 
wStream* s, BYTE v)
 
  336  if (!Stream_EnsureRemainingCapacity(s, 1))
 
  339  Stream_Write_UINT8(s, v);
 
  340  ndr_context_bytes_written(context, 1);
 
  344BOOL ndr_write_uint8_(NdrContext* context, 
wStream* s, 
const void* hints, 
const void* v)
 
  346  WINPR_ASSERT(context);
 
  351  return ndr_write_uint8(context, s, *(
const BYTE*)v);
 
  354const static NdrMessageDescr uint8_descr = { NDR_ARITY_SIMPLE, 1,    ndr_read_uint8_,
 
  355                                           ndr_write_uint8_, NULL, NULL };
 
  362#define SIMPLE_TYPE_IMPL(UPPERTYPE, LOWERTYPE)                                                \ 
  363  BOOL ndr_read_##LOWERTYPE(NdrContext* context, wStream* s, UPPERTYPE* v)                  \ 
  365    WINPR_ASSERT(context);                                                                \ 
  367    if (!Stream_CheckAndLogRequiredLength(TAG, s, sizeof(UPPERTYPE)))                     \ 
  370    if (!ndr_read_align(context, s, sizeof(UPPERTYPE)))                                   \ 
  373    if (context->bigEndianDrep)                                                           \ 
  374      Stream_Read_##UPPERTYPE##_BE(s, *v);                                              \ 
  376      Stream_Read_##UPPERTYPE(s, *v);                                                   \ 
  378    ndr_context_bytes_read(context, sizeof(UPPERTYPE));                                   \ 
  382  BOOL ndr_read_##LOWERTYPE##_(NdrContext* context, wStream* s, const void* hints, void* v) \ 
  384    WINPR_UNUSED(hints);                                                                  \ 
  385    return ndr_read_##LOWERTYPE(context, s, (UPPERTYPE*)v);                               \ 
  388  BOOL ndr_write_##LOWERTYPE(NdrContext* context, wStream* s, UPPERTYPE v)                  \ 
  390    if (!ndr_write_align(context, s, sizeof(UPPERTYPE)) ||                                \ 
  391        !Stream_EnsureRemainingCapacity(s, sizeof(UPPERTYPE)))                            \ 
  394    if (context->bigEndianDrep)                                                           \ 
  395      Stream_Write_##UPPERTYPE##_BE(s, v);                                              \ 
  397      Stream_Write_##UPPERTYPE(s, v);                                                   \ 
  399    ndr_context_bytes_written(context, sizeof(UPPERTYPE));                                \ 
  403  BOOL ndr_write_##LOWERTYPE##_(NdrContext* context, wStream* s, const void* hints,         \ 
  406    WINPR_ASSERT(context);                                                                \ 
  409    WINPR_UNUSED(hints);                                                                  \ 
  411    return ndr_write_##LOWERTYPE(context, s, *(const UPPERTYPE*)v);                       \ 
  414  const NdrMessageDescr ndr_##LOWERTYPE##_descr_s = { NDR_ARITY_SIMPLE,                     \ 
  416                                                    ndr_read_##LOWERTYPE##_,              \ 
  417                                                    ndr_write_##LOWERTYPE##_,             \ 
  421  NdrMessageType ndr_##LOWERTYPE##_descr(void)                                              \ 
  423    return &ndr_##LOWERTYPE##_descr_s;                                                    \ 
  426SIMPLE_TYPE_IMPL(UINT32, uint32)
 
  427SIMPLE_TYPE_IMPL(UINT16, uint16)
 
  428SIMPLE_TYPE_IMPL(UINT64, uint64)
 
  430#define ARRAY_OF_TYPE_IMPL(TYPE, UPPERTYPE)                                                        \ 
  431  BOOL ndr_read_##TYPE##Array(NdrContext* context, wStream* s, const void* hints, void* v)       \ 
  433    WINPR_ASSERT(context);                                                                     \ 
  435    WINPR_ASSERT(hints);                                                                       \ 
  436    return ndr_read_uconformant_array(context, s, hints, ndr_##TYPE##_descr(), v);             \ 
  439  BOOL ndr_write_##TYPE##Array(NdrContext* context, wStream* s, const void* hints,               \ 
  442    WINPR_ASSERT(context);                                                                     \ 
  444    WINPR_ASSERT(hints);                                                                       \ 
  445    const NdrArrayHints* ahints = (const NdrArrayHints*)hints;                                 \ 
  446    return ndr_write_uconformant_array(context, s, ahints->count, ndr_##TYPE##_descr(), v);    \ 
  448  void ndr_destroy_##TYPE##Array(NdrContext* context, const void* hints, void* obj)              \ 
  450    WINPR_ASSERT(context);                                                                     \ 
  452    WINPR_ASSERT(hints);                                                                       \ 
  453    const NdrArrayHints* ahints = (const NdrArrayHints*)hints;                                 \ 
  454    NdrMessageType descr = ndr_##TYPE##_descr();                                               \ 
  455    if (descr->destroyFn)                                                                      \ 
  457      UPPERTYPE* ptr = (UPPERTYPE*)obj;                                                      \ 
  458      for (UINT32 i = 0; i < ahints->count; i++, ptr++)                                      \ 
  459        descr->destroyFn(context, NULL, ptr);                                              \ 
  463  const NdrMessageDescr ndr_##TYPE##Array_descr_s = {                                            \ 
  464    NDR_ARITY_ARRAYOF,       sizeof(UPPERTYPE),         ndr_read_##TYPE##Array,                \ 
  465    ndr_write_##TYPE##Array, ndr_destroy_##TYPE##Array, NULL                                   \ 
  468  NdrMessageType ndr_##TYPE##Array_descr(void)                                                   \ 
  470    return &ndr_##TYPE##Array_descr_s;                                                         \ 
  473  BOOL ndr_read_##TYPE##VaryingArray(NdrContext* context, wStream* s, const void* hints,         \ 
  476    WINPR_ASSERT(context);                                                                     \ 
  478    WINPR_ASSERT(hints);                                                                       \ 
  479    return ndr_read_uconformant_varying_array(context, s, (const NdrVaryingArrayHints*)hints,  \ 
  480                                              ndr_##TYPE##_descr(), v);                        \ 
  482  BOOL ndr_write_##TYPE##VaryingArray(NdrContext* context, wStream* s, const void* hints,        \ 
  485    WINPR_ASSERT(context);                                                                     \ 
  487    WINPR_ASSERT(hints);                                                                       \ 
  488    return ndr_write_uconformant_varying_array(context, s, (const NdrVaryingArrayHints*)hints, \ 
  489                                               ndr_##TYPE##_descr(), v);                       \ 
  492  const NdrMessageDescr ndr_##TYPE##VaryingArray_descr_s = { NDR_ARITY_VARYING_ARRAYOF,          \ 
  494                                                           ndr_read_##TYPE##VaryingArray,      \ 
  495                                                           ndr_write_##TYPE##VaryingArray,     \ 
  499  NdrMessageType ndr_##TYPE##VaryingArray_descr(void)                                            \ 
  501    return &ndr_##TYPE##VaryingArray_descr_s;                                                  \ 
  504ARRAY_OF_TYPE_IMPL(uint8, BYTE)
 
  505ARRAY_OF_TYPE_IMPL(uint16, UINT16)
 
  507BOOL ndr_read_wchar(NdrContext* context, 
wStream* s, WCHAR* ptr)
 
  509  return ndr_read_uint16(context, s, (UINT16*)ptr);
 
  512BOOL ndr_read_uconformant_varying_array(NdrContext* context, 
wStream* s,
 
  516  WINPR_ASSERT(context);
 
  519  WINPR_ASSERT(itemType);
 
  520  WINPR_ASSERT(ptarget);
 
  526  if (!ndr_read_uint32(context, s, &maxCount) || !ndr_read_uint32(context, s, &offset) ||
 
  527      !ndr_read_uint32(context, s, &length))
 
  530  if ((length * itemType->itemSize) < hints->length)
 
  533  if ((maxCount * itemType->itemSize) < hints->maxLength)
 
  536  BYTE* target = (BYTE*)ptarget;
 
  537  for (UINT32 i = 0; i < length; i++, target += itemType->itemSize)
 
  539    if (!itemType->readFn(context, s, NULL, target))
 
  543  return ndr_read_align(context, s, 4);
 
  546BOOL ndr_write_uconformant_varying_array(NdrContext* context, 
wStream* s,
 
  550  WINPR_ASSERT(context);
 
  553  WINPR_ASSERT(itemType);
 
  556  if (!ndr_write_uint32(context, s, hints->maxLength) || !ndr_write_uint32(context, s, 0) ||
 
  557      !ndr_write_uint32(context, s, hints->length))
 
  560  const BYTE* src = (
const BYTE*)psrc;
 
  561  for (UINT32 i = 0; i < hints->length; i++, src += itemType->itemSize)
 
  563    if (!itemType->writeFn(context, s, NULL, src))
 
  573  WINPR_ASSERT(context);
 
  575  WINPR_ASSERT(itemType);
 
  576  WINPR_ASSERT(vtarget);
 
  580  if (!ndr_read_uint32(context, s, &count))
 
  583  if ((count * itemType->itemSize < hints->count))
 
  586  BYTE* target = (BYTE*)vtarget;
 
  587  for (UINT32 i = 0; i < count; i++, target += itemType->itemSize)
 
  589    if (!itemType->readFn(context, s, NULL, target))
 
  593  return ndr_read_align(context, s,  4);
 
  596BOOL ndr_write_uconformant_array(NdrContext* context, 
wStream* s, UINT32 len,
 
  599  WINPR_ASSERT(context);
 
  601  WINPR_ASSERT(itemType);
 
  604  size_t toWrite = len * itemType->itemSize;
 
  605  size_t padding = (4 - (toWrite % 4)) % 4;
 
  606  if (!ndr_write_uint32(context, s, len) || !Stream_EnsureRemainingCapacity(s, toWrite + padding))
 
  609  for (UINT32 i = 0; i < len; i++, ptr += itemType->itemSize)
 
  611    if (!itemType->writeFn(context, s, NULL, ptr))
 
  617    Stream_Zero(s, padding);
 
  618    ndr_context_bytes_written(context, padding);
 
  626  WINPR_ASSERT(context);
 
  629  WINPR_ASSERT(target);
 
  631#define NDR_MAX_STRUCT_DEFERRED 16 
  633  size_t ndeferred = 0;
 
  635  for (
size_t i = 0; i < descr->nfields; i++)
 
  639    ptr += field->structOffset;
 
  642    if (field->hintsField >= 0)
 
  645      WINPR_ASSERT((
size_t)field->hintsField < descr->nfields);
 
  646      const NdrFieldStruct* hintsField = &descr->fields[field->hintsField];
 
  648      hints = (BYTE*)target + hintsField->structOffset;
 
  651    switch (field->pointerType)
 
  653      case NDR_NOT_POINTER:
 
  654        if (!field->typeDescr->readFn(context, s, hints, ptr))
 
  656          WLog_ERR(TAG, 
"error when reading %s.%s", descr->name, field->name);
 
  661      case NDR_POINTER_NON_NULL:
 
  664        if (ndeferred >= NDR_MAX_STRUCT_DEFERRED)
 
  666          WLog_ERR(TAG, 
"too many deferred when calling ndr_read_struct_fromDescr for %s",
 
  671        deferred->name = field->name;
 
  672        deferred->hints = hints;
 
  673        deferred->target = ptr;
 
  674        deferred->msg = field->typeDescr;
 
  675        if (!ndr_read_refpointer(context, s, &deferred->ptrId))
 
  677          WLog_ERR(TAG, 
"error when reading %s.%s", descr->name, field->name);
 
  681        if (!deferred->ptrId && field->pointerType == NDR_POINTER_NON_NULL)
 
  683          WLog_ERR(TAG, 
"%s.%s can't be null", descr->name, field->name);
 
  690        WLog_ERR(TAG, 
"%s.%s unknown pointer type 0x%x", descr->name, field->name,
 
  696  return ndr_push_deferreds(context, deferreds, ndeferred);
 
  702  WINPR_ASSERT(context);
 
  708  size_t ndeferred = 0;
 
  710  for (
size_t i = 0; i < descr->nfields; i++)
 
  713    const BYTE* ptr = (
const BYTE*)src + field->structOffset;
 
  715    const void* hints = NULL;
 
  717    if (field->hintsField >= 0)
 
  720      WINPR_ASSERT((
size_t)field->hintsField < descr->nfields);
 
  721      const NdrFieldStruct* hintsField = &descr->fields[field->hintsField];
 
  723      hints = (
const BYTE*)src + hintsField->structOffset;
 
  726    switch (field->pointerType)
 
  729      case NDR_POINTER_NON_NULL:
 
  731        ndr_refid ptrId = NDR_PTR_NULL;
 
  733        ptr = *(WINPR_CAST_CONST_PTR_AWAY(ptr, 
const void**));
 
  735        if (!ptr && field->pointerType == NDR_POINTER_NON_NULL)
 
  737          WLog_ERR(TAG, 
"%s.%s can't be null", descr->name, field->name);
 
  741        if (!ndr_context_allocatePtr(context, ptr, &ptrId, &isNew))
 
  747          if (ndeferred >= NDR_MAX_STRUCT_DEFERRED)
 
  750                     "too many deferred when calling ndr_read_struct_fromDescr for %s",
 
  755          deferred->name = field->name;
 
  756          deferred->hints = WINPR_CAST_CONST_PTR_AWAY(hints, 
void*);
 
  757          deferred->target = WINPR_CAST_CONST_PTR_AWAY(ptr, 
void*);
 
  758          deferred->msg = field->typeDescr;
 
  762        if (!ndr_write_uint32(context, s, ptrId))
 
  766      case NDR_NOT_POINTER:
 
  767        if (!field->typeDescr->writeFn(context, s, hints, ptr))
 
  769          WLog_ERR(TAG, 
"error when writing %s.%s", descr->name, field->name);
 
  778  return ndr_push_deferreds(context, deferreds, ndeferred);
 
  781void ndr_struct_dump_fromDescr(wLog* logger, UINT32 lvl, 
size_t identLevel,
 
  784  char tabArray[30 + 1];
 
  785  size_t ntabs = (identLevel <= 30) ? identLevel : 30;
 
  787  memset(tabArray, 
'\t', ntabs);
 
  790  WLog_Print(logger, lvl, 
"%s%s", tabArray, descr->name);
 
  791  for (
size_t i = 0; i < descr->nfields; i++)
 
  794    const BYTE* ptr = (
const BYTE*)obj + field->structOffset;
 
  796    switch (field->pointerType)
 
  799      case NDR_POINTER_NON_NULL:
 
  800        ptr = *(WINPR_CAST_CONST_PTR_AWAY(ptr, 
const void**));
 
  802      case NDR_NOT_POINTER:
 
  805        WLog_ERR(TAG, 
"invalid field->pointerType");
 
  809    WLog_Print(logger, lvl, 
"%s*%s:", tabArray, field->name);
 
  810    if (field->typeDescr->dumpFn)
 
  811      field->typeDescr->dumpFn(logger, lvl, identLevel + 1, ptr);
 
  813      WLog_Print(logger, lvl, 
"%s\t<no dump function>", tabArray);
 
  817void ndr_struct_destroy(NdrContext* context, 
const NdrStructDescr* descr, 
void* pptr)
 
  819  WINPR_ASSERT(context);
 
  823  for (
size_t i = 0; i < descr->nfields; i++)
 
  826    void* ptr = (BYTE*)pptr + field->structOffset;
 
  829    if (field->hintsField >= 0)
 
  832      WINPR_ASSERT((
size_t)field->hintsField < descr->nfields);
 
  833      const NdrFieldStruct* hintsField = &descr->fields[field->hintsField];
 
  835      hints = (BYTE*)pptr + hintsField->structOffset;
 
  838    if (field->pointerType != NDR_NOT_POINTER)
 
  841    if (ptr && field->typeDescr->destroyFn)
 
  842      field->typeDescr->destroyFn(context, hints, ptr);
 
  844    if (field->pointerType != NDR_NOT_POINTER)
 
  849ndr_refid ndr_pointer_refid(
const void* ptr)
 
  851  return (ndr_refid)((ULONG_PTR)ptr);
 
  854BOOL ndr_read_refpointer(NdrContext* context, 
wStream* s, ndr_refid* refId)
 
  856  return ndr_read_uint32(context, s, refId);
 
  865static BOOL findValueRefFn(
const void* key, 
void* value, 
void* parg)
 
  869  FindValueArgs* args = (FindValueArgs*)parg;
 
  870  if (args->needle == value)
 
  872    *args->presult = (ndr_refid)(UINT_PTR)key;
 
  878BOOL ndr_context_allocatePtr(NdrContext* context, 
const void* ptr, ndr_refid* prefId, BOOL* pnewPtr)
 
  880  WINPR_ASSERT(context);
 
  882  FindValueArgs findArgs = { ptr, prefId };
 
  883  if (!HashTable_Foreach(context->refPointers, findValueRefFn, &findArgs))
 
  890  *prefId = context->refIdCounter + 4;
 
  891  if (!HashTable_Insert(context->refPointers, (
void*)(UINT_PTR)(*prefId), ptr))
 
  894  context->refIdCounter += 4;
 
  898BOOL ndr_read_pointedMessageEx(NdrContext* context, 
wStream* s, ndr_refid ptrId,
 
  901  WINPR_ASSERT(context);
 
  904  WINPR_ASSERT(target);
 
  910  void* ret = HashTable_GetItemValue(context->refPointers, (
void*)(UINT_PTR)ptrId);
 
  913    size_t itemCount = ndr_hintsCount(descr, hints);
 
  914    ret = calloc(itemCount, descr->itemSize);
 
  918    if (!descr->readFn(context, s, hints, ret) ||
 
  919        !HashTable_Insert(context->refPointers, (
void*)(UINT_PTR)ptrId, ret))
 
  921      if (descr->destroyFn)
 
  922        descr->destroyFn(context, hints, ret);
 
  932BOOL ndr_push_deferreds(NdrContext* context, 
NdrDeferredEntry* deferreds, 
size_t ndeferred)
 
  934  WINPR_ASSERT(context);
 
  935  WINPR_ASSERT(deferreds);
 
  940  if (context->ndeferred + ndeferred > NDR_MAX_DEFERRED)
 
  942    WLog_ERR(TAG, 
"too many deferred");
 
  946  for (
size_t i = ndeferred; i > 0; i--, context->ndeferred++)
 
  948    context->deferred[context->ndeferred] = deferreds[i - 1];
 
  953BOOL ndr_treat_deferred_read(NdrContext* context, 
wStream* s)
 
  955  WINPR_ASSERT(context);
 
  958  while (context->ndeferred)
 
  961    context->ndeferred--;
 
  963    WLog_VRB(TAG, 
"treating read deferred 0x%x for %s", current.ptrId, current.name);
 
  964    if (!ndr_read_pointedMessageEx(context, s, current.ptrId, current.msg, current.hints,
 
  965                                   (
void**)current.target))
 
  967      WLog_ERR(TAG, 
"error parsing deferred %s", current.name);
 
  975BOOL ndr_treat_deferred_write(NdrContext* context, 
wStream* s)
 
  977  WINPR_ASSERT(context);
 
  980  while (context->ndeferred)
 
  983    context->ndeferred--;
 
  985    WLog_VRB(TAG, 
"treating write deferred for %s", current.name);
 
  986    if (!current.msg->writeFn(context, s, current.hints, current.target))
 
  988      WLog_ERR(TAG, 
"error writing deferred %s", current.name);
 
  996BOOL ndr_write_data(NdrContext* context, 
wStream* s, 
const void* data, 
size_t sz)
 
  998  if (!Stream_EnsureRemainingCapacity(s, sz))
 
 1001  Stream_Write(s, data, sz);
 
 1002  ndr_context_bytes_written(context, sz);
 
hints for a conformant array
 
descriptor of a field in a structure
 
hints for a varying conformant array