Ручки
До двух частей в описании строки форматирования дескрипторов адресов процедуры. Первая часть — это поле handle_type<1> описания процедуры, используемое для указания неявных дескрипторов. Эта часть всегда присутствует. Вторая часть — это описание параметра любого явного дескриптора в процедуре. Оба описаны в следующих разделах, а также обсуждение дополнительной поддержки компилятора MIDL структуры дескриптора stub для проблем с дескриптором привязки.
Неявные дескрипторы
Если процедура использует неявный дескриптор для привязки, поле handle_type<1> описания процедуры содержит одно из трех допустимых ненулевого значения. Поддержка компилятора MIDL для неявных дескрипторов находится в поле IMPLICIT_HANDLE_INFO структуры дескриптора stub:
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 содержит адрес заглушки, определяемой переменной автоматического дескриптора.
Если процедура использует неявный примитивный дескриптор, элемент pPrimitiveHandle содержит адрес определенной переменной дескриптора, определенной примитивной.
Наконец, если процедура использует неявный универсальный дескриптор, элемент pGenericBindingInfo содержит адрес указателя на соответствующую структуру GENERIC_BINDING_INFO. Структура данных MIDL_STUB_DESC содержит указатель на коллекцию GENERIC_BINDING_PAIR структур. Запись в нулевой позиции этой коллекции зарезервирована для привязки и подпрограммы без привязки, соответствующие маркеру универсальной привязки, на который ссылается pGenericBindingInfo в IMPLICIT_HANDLE_INFO. Тип неявного дескриптора привязки указывается в строке формата.
Явные дескрипторы
Существует три возможных типа явных дескрипторов: контекст, универсальный и примитивный. В случае явного дескриптора (илииз] только дескриптор контекста, который обрабатывается таким же образом, данные дескриптора привязки отображаются как один из параметров процедуры. Ниже приведены три возможных описания.
Примитивный
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> имеет верхний флаг набитый и нижний размер набит. Флаг указывает, передается ли дескриптор указателем. Поле размера предоставляет размер определяемого пользователем типа дескриптора универсального типа. Этот размер ограничен 1, 2 или 4 байтами в 32-разрядных системах и 1, 2, 4 или 8 байтах в 64-разрядных системах.
Поле смещения<2> предоставляет смещение с начала стека указателя на данные заданного размера.
Поле binding_routine_pair_index<1> предоставляет индекс в поле aGenericBindingRoutinePairs дескриптора stub к привязке и несвязываемых указателей обычной функции для универсального дескриптора.
Заметка
Описание универсального дескриптора в формате типа — это только описание связанного типа данных.
Контекст
FC_BIND_CONTEXT flags<1> offset<2> context_rundown_routine_index<1> param_num<1>
Флаги<1> указать, как передается дескриптор и какой тип он есть. Допустимые флаги показаны в следующей таблице.
Зачаровывать | Флаг |
---|---|
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 дескриптора stub к подпрограмме rundown, используемой для этого дескриптора контекста. Компилятор всегда создает индекс. Для подпрограмм, которые не имеют подпрограммы запуска, это индекс в положение таблицы, в которой содержится значение NULL.
Для заглушки, встроенных в –Oi2, param_num<1> предоставляет порядковое число, начиная с нуля, указывая, какой дескриптор контекста он находится в данной процедуре.
Для предыдущих версий интерпретатора param_num<1> предоставляет номер параметра дескриптора контекста, начиная с нуля, в процедуре.
Заметка
Описание дескриптора контекста в строке формата типа не будет содержать смещение<2> в описании.
Новый заголовок Oif
Как упоминалось ранее, заголовок -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 указывает на это.