The Header
The following header represents one of the header styles that can be generated by the current version of MIDL. For convenience, the full list of header fields is provided here.
(–Oif header)
handle_type<1>
Oi_flags<1>
[rpc_flags<4>]
proc_num<2>
stack_size<2>
[explicit_handle_description<>]
constant_client_buffer_size<2>
constant_server_buffer_size<2>
INTERPRETER_OPT_FLAGS<1>
number_of_params<1>
Extensions starting with Windows 2000: <8> for 32-bit, <12> for 64-bit)
extension_version<1>
INTERPRETER_OPT_FLAGS2<1>
ClientCorrHint<2>
ServerCorrHint<2>
NotifyIndex<2>
[ FloatDoubleMask<2> ]
The extension_version<1> provides the size of the extension section, in bytes. Doing so makes it possible for the current NDR engine to step over the extension section correctly even if the section were to come from a later compiler version with more fields than the current engine understands.
The INTERPRETER_OPT_FLAGS2 are defined as follow:
typedef struct
{
unsigned char HasNewCorrDesc : 1; // 0x01
unsigned char ClientCorrCheck : 1; // 0x02
unsigned char ServerCorrCheck : 1; // 0x04
unsigned char HasNotify : 1; // 0x08
unsigned char HasNotify2 : 1; // 0x10
unsigned char Unused : 3;
} INTERPRETER_OPT_FLAGS2, *PINTERPRETER_OPT_FLAGS2;
The HasNewCorrDesc member indicates whether new correlation descriptors are used in the format strings generated by the compiler. The new correlation descriptor is related to the denial-of-attack functionality. The ClientCorrCheck and ServerCorrCheck members are set when the routine needs the correlation check on the indicated side.
The HasNotify and HasNotify2 flags indicate that the routine uses the notify feature as defined by the [notify] and [notify_flag] attributes, respectively.
The ClientCorrHint member is a cache size hint on the client side and ServerCorrHint is a hint on the server side. When the size comes out as zero, a default size should be used.
The NotifyIndex element is an index to a notify routine, if one is used.
The FloatDoubleMask element addresses the issue of a floating point argument for 64-bit Windows. This field is generated only for 64-bit stubs. The mask is needed for the assembly routines that download/upload registers from/to the virtual stack to handle floating-point arguments and registers properly. The mask consist of 2 bits per argument, or rather per floating-point register. The coding is as follows: The least significant bits correspond to the first FP register, the next 2 bits correspond to the second register, and so on.
Note
For object routines, the first argument ends up in the second register due to this pointer being first. For each register the meaning of bits is as shown in the following table.
Bits | Meaning |
---|---|
01 | A float value should be loaded to the register. |
10 | A double value should be loaded to the register. |
00 and 11 are invalid values for the bits.
Currently there are eight FP registers in an Intel Architecture 64-bit processor, hence the mask can have only 16b lowest bits set. The mask size has been set to a total of 16 bits based on the C-compiler mask remaining unchanged.
Header Streamlining for Performance
To simplify code and improve performance, the compiler attempts to generate a fixed size header whenever possible. In particular, the following header is used for async DCOM:
typedef struct _NDR_DCOM_OI2_PROC_HEADER
{
unsigned char HandleType; // The Oi header
INTERPRETER_FLAGS OldOiFlags; //
unsigned short RpcFlagsLow; //
unsigned short RpcFlagsHi; //
unsigned short ProcNum; //
unsigned short StackSize; //
// expl handle descr is never generated //
unsigned short ClientBufferSize; // The Oi2 header
unsigned short ServerBufferSize; //
INTERPRETER_OPT_FLAGS Oi2Flags; //
unsigned char NumberParams; //
} NDR_DCOM_OI2_PROC_HEADER, *PNDR_DCOM_OI2_PROC_HEADER;