Дескрипторы корреляции
Дескриптор корреляции — это строка формата, описывающая выражение на основе одного аргумента, связанного с другим аргументом. Дескриптор корреляции необходим для обработки семантики, связанной с атрибутами, такими как [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 бита описывают тип значения выражения.
Верхний nibble может иметь одно из следующих пяти значений:
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 байта длинного описания размера соответствия. Никаких дополнительных вычислений не требуется.
Нижний nibble дает тип значения, которое необходимо извлечь из памяти:
FC_LONG | FC_ULONG |
FC_SHORT | FC_USHORT |
FC_SMALL | FC_USMALL |
FC_HYPER
Заметка
64-разрядные выражения не поддерживаются. FC_HYPER используется только для iid_is() на 64-разрядных платформах для извлечения значения указателя для IID*.
Компилятор устанавливает значение типа nibble равным нулю для следующих случаев: константное выражение, указанное выше, и при вызове подпрограммы выражения оценки, например при использовании 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 сообщения заглушки.
Поле robust_flags<2> было добавлено для Windows 2000 для поддержки /надежных, таких как функция "отказ в атаке". На первом байте определены следующие флаги:
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;
Ранний флаг указывает на раннюю и позднюю корреляцию. Ранняя корреляция заключается в том, что аргумент выражения предшествует описанному аргументу, например аргумент размера перед аргументом указателя размера. Поздняя корреляция заключается в том, что аргумент выражения приходит после связанного аргумента. Модуль выполняет проверку ранних значений корреляции сразу, значения поздних корреляций хранятся для проверки после завершения отмены работы.
Флаг разделения указывает асинхронное разделение между аргументами [in] и [out]. Например, аргумент размера может быть [in], а указатель размера может быть [out]. В контексте асинхронного контекста DCOM эти аргументы будут находиться в разных стеках, поэтому обработчик должен знать об этом.
Флаг IsIidIs указывает iid_is() корреляции. Подпрограмма NdrComputeConformance обманывается для получения указателя на IID в качестве значения выражения, но подпрограмма проверки не может сравнить такие значения (они будут указателями) и поэтому флаг указывает на то, что фактические идентификаторы должны быть сравниваются.
Описание дисперсии и другие атрибуты массива
Формат поля описания дисперсии идентичен полю описания соответствия. Разница заключается в том, что другое поле сообщения заглушки используется подсистемой NDR в качестве временной переменной. В случае описания дисперсии вычисляется длина, а соответствующее поле называется ActualLength.
При дисперсии начальный смещение обычно равно нулю, и подсистема настраивается соответствующим образом. Если атрибут first_is() применяется к соответствующему массиву, обратный вызов к подпрограмме оценки выражений принудительно.