Validating Parameters to Interface Methods

Interface method implementers can perform two types of validation:

The type of validation performed depends on the caller. When the caller is MAPI or a service provider, debug validation is adequate because MAPI and service providers are expected to pass parameters correctly. When the caller is a client, however, full validation is recommended. Service providers cannot and should not count on clients to always pass appropriate parameters.

MAPI performs debug validation in those interface implementations that are called internally or by service providers and full validation in the implementations that are called by clients. All functions and the utility interfaces, ITableData and IPropData, perform debug validation.

For every interface method, there are three macros that clients and service providers can call in their implementations. Clients and providers can use one macro for debug validation and the other two for full validation. One of the macros for full validation is called for methods that return HRESULT values and the other is called for methods that return unsigned long values.

These macros conform to a three part naming convention with each part separated by an underscore. The prefix identifies the macro being called, as described in the following table.

Macro name prefix Description
Validate Identifies a macro to be used for fully validating methods that return HRESULT values.
UlValidate Identifies a macro to be used for fully validating methods that return unsigned long values.
CheckParameters Identifies a macro to be used for performing debug validation.

The other two parts identify the interface and method being validated. For example, to fully validate IMAPIProp::GetProps, a method that returns an HRESULT value, service providers call Validate_IMAPIProp_GetProps. To perform debug validation for this method, service providers call CheckParameters_IMAPIProp_GetProps.

The parameters to these macros vary slightly depending on whether the call is being made in C or C++. As with calls made to interface methods, the first parameter in C must be a pointer to the object implementing the method. In C++, the this pointer should be the first parameter. The rest of the parameters are the same in either language; they are the same parameters that are passed to the method being validated. Therefore, the number and type of parameters passed to a validation macro varies depending on the method being validated. All parameters passed to the method must be passed to a validation macro.

The three types of validation macros are platform independent; they are guaranteed to work on both RISC and Intel platforms. Their predecessors, the ValidateParameters, UlValidateParameters, and CheckParameters functions, perform the same functionality as the macros. However, these functions are available only for Intel platforms. Clients and service providers operating on RISC platforms must use the validation macros.

The ValidateParameters and UlValidateParameters macros and functions:

The CheckParameters macro and function are intended to be used by service providers in method implementations that are called by MAPI. They do not perform any real checking of parameters; they supply assert statements. Because the parameters passed by MAPI should be assumed to be correct, service providers do not need to perform full validation in these methods.

The following code samples illustrate how to call the ValidateParameters macro in C and C++. The method being validated is IMAPITable::QueryRows, a method implemented by service providers that returns an HRESULT value and requires three parameters: the number of rows that are requested, a bitmask of flags, and the address of a pointer to an SRowSet structure.

For C, the validation occurs as follows:

STDMETHODIMP Table_QueryRows(LPTABLE lpTable, LONG lcRows, 
                             ULONG ulFlags, LPSRowSet FAR * lplprows)
{
    Validate_IMAPITable_QueryRows(lpTable, lcRows, ulFlags, lplprows);
 
    // rest of method implementation
}
 

For C++, this example would be written as follows:

STDMETHODIMP CTable::QueryRows(LONG lcRows, ULONG ulFlags,
                               LPSRowSet FAR * lplprows)
{
    Validate_IMAPITable_QueryRows(this, lcRows, ulFlags, lplprows);
 
    // rest of method implementation
}