Handles
As many as two parts in the format string description of a procedure address handles. The first part is the handle_type<1> field of a procedure's description, used to indicate implicit handles. This part is always present. The second part is a parameter description of any explicit handle in the procedure. Both are explained in the following sections, along with a discussion of the additional MIDL compiler support of the Stub Descriptor structure for binding handle issues.
Implicit Handles
If a procedure uses an implicit handle for binding, the handle_type<1> field of the procedure's description contains one of three valid nonzero values. MIDL compiler support for implicit handles is found in the IMPLICIT_HANDLE_INFO field of the Stub Descriptor structure:
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;
If the procedure uses an auto handle, the pAutoHandle member contains the address of the stub defined–auto handle variable.
If the procedure uses an implicit primitive handle, the pPrimitiveHandle member contains the address of the stub defined–primitive handle variable.
Finally, if the procedure uses an implicit generic handle, the pGenericBindingInfo member holds the address of the pointer to the corresponding GENERIC_BINDING_INFO structure. The data structure MIDL_STUB_DESC contains a pointer to a collection of GENERIC_BINDING_PAIR structures. The entry in the zero position of this collection is reserved for the bind and unbind routines corresponding to the generic binding handle referenced by pGenericBindingInfo in IMPLICIT_HANDLE_INFO. The type of implicit binding handle is indicated in the format string.
Explicit Handles
There are three possible explicit handle types: context, generic, and primitive. In the case of an explicit handle (or an [out] only context handle, which is handled in the same way), the binding handle information appears as one of the procedure's parameters. The three possible descriptions are as follows.
Primitive
FC_BIND_PRIMITIVE, flag<1>, offset<2>.
The flag<1> indicates whether the handle is passed by a pointer.
The offset<2> provides the offset from the beginning of the stack to the primitive handle.
Note
A primitive handle description in the type format string is reduced to a single FC_IGNORE.
Generic
FC_BIND_GENERIC, flag_and_size<1>, offset<2>, binding_routine_pair_index<1>, FC_PAD
The flag_and _size<1> has the upper flag nibble and the lower size nibble. The flag indicates whether the handle is passed by a pointer. The size field provides the size of the user defined–generic handle type. This size is limited to be 1, 2 or 4 bytes on 32-bit systems and 1, 2, 4 or 8 bytes on 64-bit systems.
The offset<2> field provides the offset from the beginning of the stack of the pointer to the data of the size given.
The binding_routine_pair_index<1> field gives the index into the aGenericBindingRoutinePairs field of the Stub Descriptor to the bind and unbind routine function pointers for the generic handle.
Note
A generic handle description in the type format is the description of the related data type only.
Context
FC_BIND_CONTEXT flags<1> offset<2> context_rundown_routine_index<1> param_num<1>
The flags<1> indicate how the handle is passed and what type it is. Valid flags are shown in the following table.
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 |
The first four flags have always been present, the last four were added in Windows 2000.
The offset<2> field provides the offset from the start of the stack to the context handle.
The context_rundown_routine_index<1> provides an index into the apfnNdrRundownRoutines field of the Stub Descriptor to the rundown routine used for this context handle. The compiler always generates an index. For routines that do not have a rundown routine, this is an index to a table position that holds null.
For stubs built in –Oi2, the param_num<1> provides the ordinal count, starting at zero, specifying which context handle it is in the given procedure.
For previous versions of the interpreter, the param_num<1> provides the context handle's parameter number, starting at zero, in its procedure.
Note
A context handle description in the type format string will not have the offset<2> in the description.
The New –Oif Header
As mentioned previously, the –Oif header expands on the –Oi header. For convenience, all fields are shown here:
(The old header)
handle_type<1>
Oi_flags<1>
[rpc_flags<4>]
proc_num<2>
stack_size<2>
[explicit_handle_description<>]
(The –Oif extensions)
constant_client_buffer_size<2>
constant_server_buffer_size<2>
INTERPRETER_OPT_FLAGS<1>
number_of_params<1>
The constant_client_buffer_size<2> provides the size of the marshaling buffer that could have been pre-computed by the compiler. This may be only a partial size, as the ClientMustSize flag triggers the sizing.
The constant_server_buffer_size<2> provides the size of the marshaling buffer as precomputed by the compiler. This may be only a partial size, as the ServerMustSize flag triggers the sizing.
The INTERPRETER_OPT_FLAGS are defined in 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;
- The ServerMustSize bit is set if the server needs to perform a buffer sizing pass.
- The ClientMustSize bit is set if the client needs to perform a buffer sizing pass.
- The HasReturn bit is set if the procedure has a return value.
- The HasPipes bit is set if the pipe package needs to be used to support a pipe argument.
- The HasAsyncUuid bit is set if the procedure is an asynchronous DCOM procedure.
- The HasExtensions bit indicates that Windows 2000 and later extensions are used.
- The HasAsyncHandle bit indicates an asynchronous RPC procedure.
The HasAsyncHandle bit has been initially used for a different DCOM implementation of async support, and hence could not be used for the current style async support in DCOM. The HasAsyncUuid bit currently indicates this.