相互關聯描述項
相互關聯描述元是格式字串,可根據與另一個自變數相關的自變數來描述表達式。 處理與 [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> 字段的解譯,視表達式的複雜度、表達式變數的位置,以及陣列而言,陣列是否實際上是屬性指標而定。
如果陣列是屬性指標,且一致性變數是 結構中的欄位,則 offset 欄位會包含結構開頭到一致性描述欄位的位移。 如果陣列不是屬性指標,且一致性變數是 結構中的欄位,則 offset 欄位會包含結構不一致部分結尾到一致性描述字段的位移。 一般而言,一致性陣列位於 結構的結尾。
針對最上層一致性,位移字段包含從堆疊上第一個參數位置到描述一致性之參數的位移。 這不會用於 –Os 模式。 位移欄位的解譯還有其他例外狀況:這些類型的描述會說明這類例外狀況。
當位移<2> 搭配 FC_CALLBACK使用時,它會在編譯程式所產生的表達式評估例程數據表中包含索引。 存根訊息會傳遞至評估例程,然後計算一致性值,並將它指派給存根訊息的 MaxCount 字段。
Windows 2000 已新增 robust_flags<2> 字段,以支援 /robust,例如拒絕攻擊功能。 第一個字節上定義了下列旗標:
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;
「早期」旗標表示早期與晚期相互關聯。 早期相互關聯是在表達式自變數前面描述的自變數時,例如size自變數是在大小指標自變數之前。 晚期相互關聯是表達式自變數在相關自變數之後。 引擎會立即執行早期相互關聯值的驗證,延遲的相互關聯值會儲存在取消合併完成之後進行檢查。
Split 旗標表示 [in] 和 [out] 自變數之間的異步分割。 例如,size 自變數可能是 [in],而大小指標可能是 [out]。 在 DCOM 異步內容中,這些自變數會發生在不同的堆疊上,因此引擎必須注意這一點。
IsIidIs 旗標表示 iid_is() 相互關聯。 NdrComputeConformance 例程會欺騙取得 IID 的指標做為表達式值,但驗證例程無法比較這類值(這些值會是指針),因此旗標表示需要比較實際的 IID。
變數描述和其他數位屬性
變異數描述欄位格式與一致性描述欄位相同。 差異在於 NDR 引擎會使用不同的存根訊息欄位作為暫存變數。 在變異數描述的情況下,它是評估的長度,且對應的字段稱為 ActualLength。
使用變異數時,起始位移通常是零,而且引擎會據以微調。 如果 first_is() 屬性套用至一致不同的數位,則會強制對表達式評估例程的回呼。