Passing Parameters (Windows CE 5.0)
Arguments to the method or property being invoked are passed in the DISPPARAMS structure. This structure consists of the following:
- A pointer to an array of parameters represented as variants
- A pointer to an array of DISPIDs for named parameters
- The number of parameters in each array
For example:
typedef struct FARSTRUCT tagDISPPARAMS{
VARIANTARG FAR* rgvarg; // Array of parameters.
DISPID FAR* rgdispidNamedArgs; // Dispatch IDs of named parameters.
unsigned int cArgs; // Number of parameters.
unsigned int cNamedArgs; // Number of named parameters.
} DISPPARAMS;
The parameters are passed in the array rgvarg[ ], with the number of parameters passed in cArgs.
The parameters in the array should be placed from last to first, so rgvarg[0] has the last parameter and rgvarg[cArgs 1] has the first parameter. The method or property can change the values of elements within the array rgvarg, but only if it has set the VT_BYREF flag. Otherwise, consider the elements as read-only.
A dispatch invocation can have named parameters as well as positional parameters.
If cNamedArgs is 0, all the elements of rgvarg[ ] represent positional parameters.
If cNamedArgs is not 0, each element of rgdispidNamedArgs[ ] contains the DISPID of a named parameter, and the value of the parameter is in the matching element of rgvarg[ ].
The DISPIDs of the named parameters are always contiguous in rgdispidNamedArgs, and their values are in the first cNamedArgs elements of rgvarg.
Named parameters cannot be accessed positionally, and positional parameters cannot be named.
The DISPID of a parameter is its zero-based position in the parameter list.
If you include the DISPID with each named parameter, you can pass the named parameters to IDispatch::Invoke in any order.
For example, if a method is to be invoked with two positional parameters, followed by three named parameters (A, B, and C), using the following hypothetical syntax, then cArgs would be 5, and cNamedArgs would be 3.
The first positional parameter would be in rgvarg[4].****The second positional parameter would be in rgvarg[3].
The ordering of named parameters is not important to the IDispatch implementation, but these parameters are generally passed in reverse order.
The parameter A would be in rgvarg[2], with the DISPID of A in rgdispidNamedArgs[2].
The parameter B would be in rgvarg[1], with the corresponding DISPID in rgdispidNamedArgs[1].
The parameter C would be in rgvarg[0], with the DISPID corresponding to C in rgdispidNamedArgs[0].
You can also use Invoke on members with optional parameters, but all optional parameters must be of type VARIANT.
As with required parameters, the contents of the parameter vector depend on whether the parameters are positional or named. The invoked member must ensure that the parameters are valid. Invoke merely passes the DISPPARAMS structure it receives.
Omitting named parameters is straightforward. You would pass the parameters in rgvarg and their DISPIDs in rgdispidNamedArgs.
To omit the parameter named B (in the preceding example) you would set rgvarg[0] to the value of C, with its DISPID in rgdispidNamedArgs[0]; and rgvarg[1] to the value of A, with its DISPID in rgdispidNamedArgs[1]. The subsequent positional parameters would occupy elements 2 and 3 of the arrays. In this case, cArgs is 4 and cNamedArgs is 2.
If the parameters were positional (unnamed), you would set cArgs to the total number of possible parameters, cNamedArgs to 0, and pass VT_ERROR as the type of the omitted parameters, with the status code DISP_E_PARAMNOTFOUND as the value.
The calling code is responsible for releasing all strings and objects referred to by rgvarg[ ] or placed in *pVarResult.
As with other parameters that are passed by value, if the invoked member must maintain access to a string after returning, you should copy the string. Similarly, if the member needs access to a passed-object pointer after returning, it must call the IUnknown::AddRef function on the object.
A common example occurs when an object property is changed to refer to a new object, using the DISPATCH_PROPERTYPUTREF flag.
For those implementing Invoke, Automation provides the DispGetParam function to retrieve parameters from the parameter vector and coerce them to the proper type.
See Also
Automation | DispGetParam | DISPPARAMS | IDispatch::Invoke | VARIANT | IUnknown::AddRef
Send Feedback on this topic to the authors