相关描述符

相关描述符是一个格式字符串,用于描述基于与另一个参数相关的一个参数的表达式。 处理与 [size_is()]、 [length_is()]、 [switch_is()] 和 [iid_is()] 等属性相关的语义需要相关描述符。 相关描述符用于数组、大小指针、联合和接口指针。 最终表达式值可以是大小、长度、联合歧视或指向 IID 的指针。 就格式字符串而言,相关描述符用于数组、联合和接口指针。 大小指针以格式字符串描述为指向数组的指针。

有两个执行基本表达式计算的例程:NdrpComputeConformance 用于大小、开关和 IID* ,而 NdrpComputeVariance 用于长度。 还有一个例程用于对拒绝攻击功能执行相关值验证。

关联描述符旨在仅支持非常有限的表达式。 对于复杂的情况,编译器会生成一个表达式计算例程,以便在需要时由引擎调用。

相关描述符具有以下格式:

correlation_type<1>
correlation_operator<1>
offset<2>
[robust_flags<2>]

相关描述符correlation_type<1> 由两个小数组成:前 4 位描述可在何处找到表达式,下 4 位描述表达式的类型。

上部小数可以有以下五个值之一:

00  FC_NORMAL_CONFORMANCE
10  FC_POINTER_CONFORMANCE
20  FC_TOP_LEVEL_CONFORMANCE
80  FC_TOP_LEVEL_MULTID_CONFORMANCE
40  FC_CONSTANT_CONFORMANCE

FC_NORMAL_CONFORMANCE

符合性的正常情况,例如结构字段中所述的一种情况。

FC_POINTER_CONFORMANCE

对于特性化指针(size_is()length_is())是结构中的字段。 这会影响设置基本内存指针的方式。

FC_TOP_LEVEL_CONFORMANCE

对于另一个参数描述的顶级一致性。

FC_TOP_LEVEL_MULTID_CONFORMANCE

对于由另一个参数描述的多维数组的顶级一致性。

注意

多维大小的数组和指针触发切换到 –Oicf

 

FC_CONSTANT_CONFORMANCE

对于常量值。 编译器预先计算用户提供的常量表达式中的值。 在这种情况下,一致性说明中的后续 3 个字节包含描述符合性大小的较长的 3 个字节。 无需进一步计算。

较低的大小提供需要从内存中提取的值的类型:

FC_LONG | FC_ULONG | 
FC_SHORT | FC_USHORT | 
FC_SMALL | FC_USMALL | 
FC_HYPER

注意

不支持 64 位表达式。 FC_HYPER仅用于 64 位平台上的 iid_is(),以提取 IID* 的指针值。

对于以下情况,编译器将类型大小设置为零:上面提到的常量表达式,以及何时需要调用计算表达式例程,例如,使用FC_CONSTANT_CONFORMANCE和FC_CALLBACK时。

 

size_is_op<1> 字段允许将下列作之一应用于符合性变量:

FC_DEREFERENCE | 
FC_DIV_2 | FC_MULT_2 | FC_SUB_1 | FC_ADD_1 | 
FC_CALLBACK

FC_DEREFERENCE常量用于关联,例如 [size_is(*pL)]。 算术运算符只使用指示的常量。 FC_CALLBACK常量指示需要调用表达式计算例程。

偏移量<2> 字段通常是表达式参数变量的相对内存偏移量。 它也可以是表达式计算例程索引。 如本文档前面所述,对于常量表达式,它是实际最终表达式值的一部分。

偏移量<2> 字段解释为内存偏移量取决于表达式的复杂性、表达式变量的位置,以及在数组的情况下,数组是否实际上是特性化指针。

如果数组是特性化指针,且一致性变量是结构中的字段,则偏移字段包含结构开头到符合性描述字段的偏移量。 如果数组不是特性化指针,并且一致性变量是结构中的字段,则偏移字段包含结构不一致部分末尾到符合性描述字段的偏移量。 通常,符合性数组位于结构末尾。

对于顶级一致性,偏移字段包含从堆栈上存根的第一个参数位置到描述一致性的参数的偏移量。 这在 –Os 模式下不使用。 偏移字段的解释还有其他例外情况;这些类型的说明描述了此类异常。

当偏移量<2> 与FC_CALLBACK一起使用时,它包含编译器生成的表达式计算例程表中的索引。 存根消息将传递到评估例程,然后计算一致性值,并将其分配给存根消息的 MaxCount 字段。

Windows 2000 添加了 robust_flags<2 个> 字段,以支持 /可靠的,例如拒绝攻击功能。 第一个字节上定义了以下标志:

typedef  struct  _NDR_CORRELATION_FLAGS
  {
  unsigned char   Early     : 1;
  unsigned char   Split     : 1;
  unsigned char   IsIidIs   : 1;
  unsigned char   DontCheck : 1;
  unsigned char   Unused    : 4;
  } NDR_CORRELATION_FLAGS;

“早期”标志表示早期关联与后期关联。 早期关联是在描述的参数之前,例如,大小参数位于大小指针参数之前。 延迟关联是表达式参数位于相关参数之后时。 引擎立即对早期关联值执行验证,后期关联值存储在未合并完成后进行检查。

Split 标志指示 [in] 和 [out] 参数之间的异步拆分。 例如,大小参数可以是 [in],而大小指针可能是 [out]。 在 DCOM 异步上下文中,这些参数恰好在不同的堆栈上,因此引擎必须注意这一点。

IsIidIs 标志指示 iid_is() 关联。 NdrComputeConformance 例程被欺骗为获取指向 IID 的指针作为表达式值,但验证例程无法比较此类值(它们是指针),因此标志指示需要比较实际的 IID。

方差说明和其他数组属性

方差说明字段格式与一致性说明字段相同。 区别在于 NDR 引擎使用不同的存根消息字段作为临时变量。 对于方差说明,它是计算的长度,相应的字段称为 ActualLength。

使用方差时,起始偏移量通常为零,并相应地优化引擎。 如果 first_is() 属性应用于一个符合性的不同数组,则强制对表达式计算例程的回调。