Ethereal-dev: Re: [Ethereal-dev] DCERPC support and improved SAMR

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Guy Harris <gharris@xxxxxxxxx>
Date: Mon, 4 Feb 2002 23:57:31 -0800
> The patch also makes each pointer (to structure) be evaluated twice,
> once with conformant_run==1    and once with conformant_run==0.
> This is to make the dissection of non-fixed arrays work properly.
> Currently only unidimensional conformant and unidimensional conformant and
> varying arrays are implemented.
> This is however completely transparent to the dissector in say samr and only
> visible in packet-dcerpc.c
> However, it means that subdissectors can only call dissect_ndr_xxx
> functions, or other handcrafted functions which are aware
> of when to dissect scalars and when not to.
> See dissect_ndr_ucarray()m dissect_ndr_ucvarray() and
> dissect_deferred_pointers()  for examples on how this interaction
> works.

This causes the reply to a SAMR_QUERY_DISPINFO call not to be dissected
completely correctly.

DISPLAY_INFO is defined as

    typedef [switch_type(unsigned short)] union {
      [case(1)] USER_DISPINFO_1_ARRAY users1;
      [case(2)] USER_DISPINFO_2_ARRAY users2;
      [case(3)] GROUP_DISPINFO_ARRAY groups;
      [case(4)] ASCII_DISPINFO_ARRAY ausers;
      [case(5)] ASCII_DISPINFO_ARRAY agroups;
    } DISPLAY_INFO;

The dissector disects the "switch_type" value (as "Level"), and then
dissects the info.

For level 1, USER_DISPINFO_1_ARRAY is defined as

    typedef struct {
      long count;
      [size_is(count), ptr]  USER_DISPINFO_1 *users;
    } USER_DISPINFO_1_ARRAY;

It dissects the "count" field as "Max Count" (but it's *not* a count
field for a conformant array, it's just a number called "count"), and
then dissects the pointer.

Then it dissects the Referent ID.

It *should* then dissect the max_count for the array to which "users"
points, but it doesn't, because, in "dissect_deferred_pointers()":

	the first pass, with "conformant_run" true, passes null as the
	tree pointer, so nothing is put into the protocol tree when
	"dissect_ndr_ucarray()" calls "dissect_ndr_uint32()" to get the
	max_count;

	the second pass, with "conformant_run false, doesn't dissect the
	max_count header;

so there's no pass where the max_count header is dissected and the
"tree" argument is non-null.