Маркеры
Целых две части в строковом описании формата дескрипторов адреса процедуры. Первая часть — это поле handle_type<1> описания процедуры, используемое для обозначения неявных дескрипторов. Эта часть присутствует всегда. Вторая часть — это описание параметра любого явного дескриптора в процедуре. Оба варианта описываются в следующих разделах, наряду с обсуждением дополнительной поддержки компилятором MIDL структуры дескриптора заглушки для проблем с дескриптором привязки.
Если процедура использует неявный дескриптор для привязки, поле handle_type<1> описания процедуры содержит одно из трех допустимых ненулевых значений. Поддержка компилятора MIDL для неявных дескрипторов находится в IMPLICIT_HANDLE_INFO поле структуры дескриптора заглушки:
typedef (__RPC_FAR * GENERIC_BINDING_ROUTINE)();
typedef struct
{
GENERIC_BINDING_ROUTINE pfnBind;
GENERIC_BINDING_ROUTINE pfnUnbind;
} GENERIC_BINDING_ROUTINE_PAIR;
typedef struct __GENERIC_BINDING_INFO
{
void __RPC_FAR* pObj;
unsigned char Size;
GENERIC_BINDING_ROUTINE pfnBind;
GENERIC_BINDING_ROUTINE pfnUnbind;
} GENERIC_BINDING_INFO, *PGENERIC_BINDING_INFO;
union
{
handle_t* pAutoHandle;
handle_t* pPrimitiveHandle;
PGENERIC_BINDING_INFO pGenericBindingInfo;
} IMPLICIT_HANDLE_INFO;
Если процедура использует автоматический дескриптор, элемент pAutoHandle содержит адрес переменной заглушки, определенной —auto handle.
Если процедура использует неявный дескриптор-примитив, член pPrimitiveHandle содержит адрес переменной дескриптора, определенной заглушки и примитивом.
Наконец, если процедура использует неявный универсальный дескриптор, член pGenericBindingInfo содержит адрес указателя на соответствующую структуру GENERIC_BINDING_INFO . Структура данных MIDL_STUB_DESC содержит указатель на коллекцию GENERIC_BINDING_PAIR структур. Запись в нулевой позиции этой коллекции зарезервирована для подпрограмм привязки и отмены привязки , соответствующих универсальному дескриптору привязки, на который ссылается pGenericBindingInfo в IMPLICIT_HANDLE_INFO. Тип неявного дескриптора привязки указывается в строке формата.
Существует три возможных типа явных дескрипторов: контекст, универсальный и примитивный. В случае явного дескриптора (или дескриптора контекста только [out], который обрабатывается таким же образом), сведения о дескрипторе привязки отображаются как один из параметров процедуры. Ниже приведены три возможных описания.
Примитивные
FC_BIND_PRIMITIVE, flag<1>, offset<2>.
Флаг<1> указывает, передается ли дескриптор указателем.
Смещение<2> обеспечивает смещение от начала стека до примитивного дескриптора.
Примечание
Примитивное описание дескриптора в строке формата типа сводится к одному FC_IGNORE.
Универсальный шаблон
FC_BIND_GENERIC, flag_and_size<1>, offset<2>, binding_routine_pair_index<1>, FC_PAD
Flag_and _size<1> имеет верхний флажок и нижний размер пера. Флаг указывает, передается ли дескриптор указателем. Поле size предоставляет размер определяемого пользователем универсального типа дескриптора. Этот размер ограничен 1, 2 или 4 байтами в 32-разрядных системах и 1, 2, 4 или 8 байтами в 64-разрядных системах.
Поле смещения<2> обеспечивает смещение от начала стека указателя к данным заданного размера.
Поле binding_routine_pair_index<1> передает индекс в полеGenericBindingRoutinePairs дескриптора stub для указателей функции bind и unbind для универсального дескриптора.
Примечание
Универсальное описание дескриптора в формате типа — это только описание связанного типа данных.
Контекст
FC_BIND_CONTEXT flags<1> offset<2> context_rundown_routine_index<1> param_num<1>
Флаги<1> указывают, как передается дескриптор и какой он тип. Допустимые флаги приведены в следующей таблице.
Hex | Flag |
---|---|
80 | HANDLE_PARAM_IS_VIA_PTR |
40 | HANDLE_PARAM_IS_IN |
20 | HANDLE_PARAM_IS_OUT |
21 | HANDLE_PARAM_IS_RETURN |
08 | NDR_STRICT_CONTEXT_HANDLE |
04 | NDR_CONTEXT_HANDLE_NO_SERIALIZE |
02 | NDR_CONTEXT_HANDLE_SERIALIZE |
01 | NDR_CONTEXT_HANDLE_CANNOT_BE_NULL |
Первые четыре флага всегда присутствовали, последние четыре были добавлены в Windows 2000.
Поле смещения<2> предоставляет смещение от начала стека до дескриптора контекста.
Context_rundown_routine_index<1> предоставляет индекс в поле apfnNdrRundownRoutines дескриптора заглушки для подпрограммы запуска, используемой для этого дескриптора контекста. Компилятор всегда создает индекс. Для подпрограмм, которые не имеют подпрограммы запуска, это индекс для позиции таблицы, в которой содержится значение NULL.
Для заглушки, встроенных в –Oi2, param_num<1> предоставляет порядковый номер, начиная с нуля, указывая, какой дескриптор контекста находится в данной процедуре.
Для предыдущих версий интерпретатора param_num<1> предоставляет в процедуре номер параметра дескриптора контекста, начиная с нуля.
Примечание
Описание дескриптора контекста в строке формата типа не будет иметь смещение<2> в описании.
Как упоминалось ранее, заголовок –Oif расширяется на заголовок –Oi . Для удобства здесь отображаются все поля:
(Старый заголовок)
handle_type<1>
Oi_flags<1>
[rpc_flags<4>]
proc_num<2>
stack_size<2>
[explicit_handle_description<>]
(Расширения –Oif )
constant_client_buffer_size<2>
constant_server_buffer_size<2>
INTERPRETER_OPT_FLAGS<1>
number_of_params<1>
Constant_client_buffer_size<2> предоставляет размер буфера маршалинга, который мог быть предварительно вычислен компилятором. Это может быть только частичный размер, так как флаг ClientMustSize активирует изменение размера.
Constant_server_buffer_size<2> предоставляет размер буфера маршалинга, предварительно вычисляемый компилятором. Это может быть только частичный размер, так как флаг ServerMustSize активирует изменение размера.
INTERPRETER_OPT_FLAGS определены в Ndrtypes.h:
typedef struct
{
unsigned char ServerMustSize : 1; // 0x01
unsigned char ClientMustSize : 1; // 0x02
unsigned char HasReturn : 1; // 0x04
unsigned char HasPipes : 1; // 0x08
unsigned char Unused : 1;
unsigned char HasAsyncUuid : 1; // 0x20
unsigned char HasExtensions : 1; // 0x40
unsigned char HasAsyncHandle : 1; // 0x80
} INTERPRETER_OPT_FLAGS, *PINTERPRETER_OPT_FLAGS;
- Бит ServerMustSize задается, если серверу необходимо выполнить проход изменения размера буфера.
- Бит ClientMustSize задается, если клиенту необходимо выполнить проход изменения размера буфера.
- Бит HasReturn задается, если процедура имеет возвращаемое значение.
- Бит HasPipes задается, если пакет канала необходимо использовать для поддержки аргумента канала.
- Бит HasAsyncUuid задается, если процедура является асинхронной процедурой DCOM.
- Бит HasExtensions указывает, что используются расширения Windows 2000 и более поздних версий.
- Бит HasAsyncHandle указывает на асинхронную процедуру RPC.
Бит HasAsyncHandle изначально использовался для другой реализации Асинхронной поддержки DCOM и поэтому не может использоваться для текущей поддержки асинхронного стиля в DCOM. Бит HasAsyncUuid в настоящее время указывает на это.