_PUBLIC_ enum ndr_err_code ndr_push_PAC_BUFFER_RAW(struct ndr_push *ndr, int ndr_flags, const struct PAC_BUFFER_RAW *r) { if (ndr_flags & NDR_SCALARS) { NDR_CHECK(ndr_push_align(ndr, 4)); NDR_CHECK(ndr_push_PAC_TYPE(ndr, NDR_SCALARS, r->type)); NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->ndr_size)); { uint32_t _flags_save_DATA_BLOB_REM = ndr->flags; ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8); NDR_CHECK(ndr_push_relative_ptr1(ndr, r->info)); ndr->flags = _flags_save_DATA_BLOB_REM; } NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0)); } if (ndr_flags & NDR_BUFFERS) { { uint32_t _flags_save_DATA_BLOB_REM = ndr->flags; ndr_set_flags(&ndr->flags, LIBNDR_FLAG_ALIGN8); if (r->info) { NDR_CHECK(ndr_push_relative_ptr2(ndr, r->info)); { struct ndr_push *_ndr_info; NDR_CHECK(ndr_push_subcontext_start(ndr, &_ndr_info, 0, NDR_ROUND(r->ndr_size, 8))); NDR_CHECK(ndr_push_DATA_BLOB_REM(_ndr_info, NDR_SCALARS, r->info)); NDR_CHECK(ndr_push_subcontext_end(ndr, _ndr_info, 0, NDR_ROUND(r->ndr_size, 8))); } } ndr->flags = _flags_save_DATA_BLOB_REM; } } return NDR_ERR_SUCCESS; }
NTSTATUS ndr_push_security_descriptor(struct ndr_push *ndr, int ndr_flags, const struct security_descriptor *r) { { uint32_t _flags_save_STRUCT = ndr->flags; ndr_set_flags(&ndr->flags, LIBNDR_FLAG_LITTLE_ENDIAN); if (ndr_flags & NDR_SCALARS) { NDR_CHECK(ndr_push_align(ndr, 4)); NDR_CHECK(ndr_push_security_descriptor_revision(ndr, NDR_SCALARS, r->revision)); NDR_CHECK(ndr_push_security_descriptor_type(ndr, NDR_SCALARS, r->type)); NDR_CHECK(ndr_push_relative_ptr1(ndr, r->owner_sid)); NDR_CHECK(ndr_push_relative_ptr1(ndr, r->group_sid)); NDR_CHECK(ndr_push_relative_ptr1(ndr, r->sacl)); NDR_CHECK(ndr_push_relative_ptr1(ndr, r->dacl)); } if (ndr_flags & NDR_BUFFERS) { if (r->owner_sid) { NDR_CHECK(ndr_push_relative_ptr2(ndr, r->owner_sid)); NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, r->owner_sid)); } if (r->group_sid) { NDR_CHECK(ndr_push_relative_ptr2(ndr, r->group_sid)); NDR_CHECK(ndr_push_dom_sid(ndr, NDR_SCALARS, r->group_sid)); } if (r->sacl) { NDR_CHECK(ndr_push_relative_ptr2(ndr, r->sacl)); NDR_CHECK(ndr_push_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->sacl)); } if (r->dacl) { NDR_CHECK(ndr_push_relative_ptr2(ndr, r->dacl)); NDR_CHECK(ndr_push_security_acl(ndr, NDR_SCALARS|NDR_BUFFERS, r->dacl)); } } ndr->flags = _flags_save_STRUCT; } return NT_STATUS_OK; }
/* push a relative object - stage2 start this is called during buffers processing */ _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_start(struct ndr_push *ndr, const void *p) { if (p == NULL) { return NDR_ERR_SUCCESS; } if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) { return ndr_push_relative_ptr2(ndr, p); } if (ndr->relative_end_offset == -1) { return ndr_push_error(ndr, NDR_ERR_RELATIVE, "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d", ndr->relative_end_offset); } NDR_CHECK(ndr_token_store(ndr, &ndr->relative_begin_list, p, ndr->offset)); return NDR_ERR_SUCCESS; }
/* push a relative object - stage2 start this is called during buffers processing */ _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_start(struct ndr_push *ndr, const void *p) { if (p == NULL) { return NDR_ERR_SUCCESS; } if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) { uint32_t relative_offset; size_t pad; size_t align = 1; if (ndr->offset < ndr->relative_base_offset) { return ndr_push_error(ndr, NDR_ERR_BUFSIZE, "ndr_push_relative_ptr2_start ndr->offset(%u) < ndr->relative_base_offset(%u)", ndr->offset, ndr->relative_base_offset); } relative_offset = ndr->offset - ndr->relative_base_offset; if (ndr->flags & LIBNDR_FLAG_NOALIGN) { align = 1; } else if (ndr->flags & LIBNDR_FLAG_ALIGN2) { align = 2; } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) { align = 4; } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) { align = 8; } pad = ndr_align_size(relative_offset, align); if (pad) { NDR_CHECK(ndr_push_zero(ndr, pad)); } return ndr_push_relative_ptr2(ndr, p); } if (ndr->relative_end_offset == -1) { return ndr_push_error(ndr, NDR_ERR_RELATIVE, "ndr_push_relative_ptr2_start RELATIVE_REVERSE flag set and relative_end_offset %d", ndr->relative_end_offset); } NDR_CHECK(ndr_token_store(ndr, &ndr->relative_begin_list, p, ndr->offset)); return NDR_ERR_SUCCESS; }
_PUBLIC_ NTSTATUS ndr_push_WbemQualifier(struct ndr_push *ndr, int ndr_flags, const struct WbemQualifier *r) { if (ndr_flags & NDR_SCALARS) { NDR_CHECK(ndr_push_align(ndr, 4)); NDR_CHECK(ndr_push_relative_ptr1(ndr, r->name)); NDR_CHECK(ndr_push_WBEM_FLAVOR_TYPE(ndr, NDR_SCALARS, r->flavors)); NDR_CHECK(ndr_push_CIMTYPE_ENUMERATION(ndr, NDR_SCALARS, r->cimtype)); NDR_CHECK(ndr_push_set_switch_value(ndr, &r->value, r->cimtype & CIM_TYPEMASK)); NDR_CHECK(ndr_push_CIMVAR(ndr, NDR_SCALARS, &r->value)); } if (ndr_flags & NDR_BUFFERS) { if (r->name) { uint32_t ofs; int32_t i; for (i = 0; i < arr_sizeof(qualifier_keys); ++i) if (qualifier_keys[i] && !strcmp(r->name, qualifier_keys[i])) break; if (i == arr_sizeof(qualifier_keys)) { if (!strncmp(qn_unknown, r->name, sizeof(qn_unknown) - 1)) i = atoi(r->name + sizeof(qn_unknown) - 1); else i = -1; } if (i >= 0) { ofs = ndr->offset; NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, r->name, &ndr->offset)); NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, 0x80000000 | i)); ndr->offset = ofs; } else { NDR_CHECK(ndr_push_relative_ptr2(ndr, r->name)); NDR_CHECK(ndr_push_CIMSTRING(ndr, NDR_SCALARS, &r->name)); } } NDR_CHECK(ndr_push_CIMVAR(ndr, NDR_BUFFERS, &r->value)); } return NT_STATUS_OK; }
/* push a relative object - stage2 end this is called during buffers processing */ _PUBLIC_ enum ndr_err_code ndr_push_relative_ptr2_end(struct ndr_push *ndr, const void *p) { uint32_t begin_offset = 0xFFFFFFFF; ssize_t len; uint32_t correct_offset = 0; uint32_t align = 1; uint32_t pad = 0; if (p == NULL) { return NDR_ERR_SUCCESS; } if (!(ndr->flags & LIBNDR_FLAG_RELATIVE_REVERSE)) { return NDR_ERR_SUCCESS; } if (ndr->flags & LIBNDR_FLAG_NO_NDR_SIZE) { /* better say more than calculation a too small buffer */ NDR_PUSH_ALIGN(ndr, 8); return NDR_ERR_SUCCESS; } if (ndr->relative_end_offset < ndr->offset) { return ndr_push_error(ndr, NDR_ERR_RELATIVE, "ndr_push_relative_ptr2_end:" "relative_end_offset %u < offset %u", ndr->relative_end_offset, ndr->offset); } NDR_CHECK(ndr_token_retrieve(&ndr->relative_begin_list, p, &begin_offset)); /* we have marshalled a buffer, see how long it was */ len = ndr->offset - begin_offset; if (len < 0) { return ndr_push_error(ndr, NDR_ERR_RELATIVE, "ndr_push_relative_ptr2_end:" "offset %u - begin_offset %u < 0", ndr->offset, begin_offset); } if (ndr->relative_end_offset < len) { return ndr_push_error(ndr, NDR_ERR_RELATIVE, "ndr_push_relative_ptr2_end:" "relative_end_offset %u < len %lld", ndr->offset, (long long)len); } /* the reversed offset is at the end of the main buffer */ correct_offset = ndr->relative_end_offset - len; /* TODO: remove this hack and let the idl use FLAG_ALIGN2 explicit */ align = 2; if (ndr->flags & LIBNDR_FLAG_ALIGN2) { align = 2; } else if (ndr->flags & LIBNDR_FLAG_ALIGN4) { align = 4; } else if (ndr->flags & LIBNDR_FLAG_ALIGN8) { align = 8; } pad = ndr_align_size(correct_offset, align); if (pad) { correct_offset += pad; correct_offset -= align; } if (correct_offset < begin_offset) { return ndr_push_error(ndr, NDR_ERR_RELATIVE, "ndr_push_relative_ptr2_end: " "correct_offset %u < begin_offset %u", correct_offset, begin_offset); } if (len > 0) { uint32_t clear_size = correct_offset - begin_offset; clear_size = MIN(clear_size, len); /* now move the marshalled buffer to the end of the main buffer */ memmove(ndr->data + correct_offset, ndr->data + begin_offset, len); if (clear_size) { /* and wipe out old buffer within the main buffer */ memset(ndr->data + begin_offset, '\0', clear_size); } } /* and set the end offset for the next buffer */ ndr->relative_end_offset = correct_offset; /* finally write the offset to the main buffer */ ndr->offset = correct_offset; NDR_CHECK(ndr_push_relative_ptr2(ndr, p)); /* restore to where we were in the main buffer */ ndr->offset = begin_offset; return NDR_ERR_SUCCESS; }