DPA_SaveStream

This function saves items from a DPA to a stream.

Declaration

HRESULT
DPA_SaveStream (
    HDPA pdpa,
    PFNDPASTREAM pfn,
    IStream *pstm,
    PVOID pvInstData);

The callback function has the prototype:

typedef HRESULT (*PFNDPASTREAM) (
    DPASTREAMINFO *pinfo,
    IStream *pstm,
    PVOID pvInstData);

The information structure for the callback function has the form:

typedef struct _DPASTREAMINFO {
    int iPos;
    PVOID pvItem;
} DPASTREAMINFO; 

Parameters

The pdpa argument provides a handle to the DPA.

The pfn argument provides the address of a callback function that writes successive items to the stream.

The pstm argument provides the address of an IStream interface for access to the stream.

The pvInstData argument provides a caller-specific context for each invocation of the callback function.

Return Value

The function returns S_OK (zero) for success, with all items saved to the given stream. It returns S_FALSE (1) for a partial success in which only some items were saved to the given stream. Any other value is an error code to describe a failure.

Behaviour

The function writes to the given stream, at its current seek position, a 12-byte DPASTREAMHEADER structure:

typedef struct _DPASTREAMHEADER {
    DWORD dwSize;
    DWORD dwVersion;
    int cpItems;
} DPASTREAMHEADER; 

Should the function succeed, the dwSize member will record the size of the stream, measured in bytes, counting the header and whatever arbitrary-sized items that follow, and the cpItems member will record the number of those items. The dwVersion member is always 1. At the outset however, the function does not know how much data or how many items will get written successfully to the stream. It therefore writes this header the first time as a dummy, with zero as both the size and the count.

The function then calls the callback function repeatedly to get the DPA’s items written sequentially to the stream. When this is done, even with only partial success, the function notes how much data was written to the stream, and for how many items. It rewrites the header at the beginning of the stream, this time with the known dwSize and cpItems, then returns to the end of the stream.

Callback Function

Each invocation of the callback function is responsible for saving one item. The 0-based index for this item is provided as the iPos member of a DPASTREAMINFO structure. The address of the item is provided as the pvItem member. This may be NULL, for an empty item. Also provided as arguments to the callback function are the pstm and pvInstData arguments, as given to to the DPA_SaveStream function.

The callback function returns S_OK to indicate success at saving the desired item. DPA_SaveStream then advances to the next item. A successful save of the last item in the DPA results in DPA_SaveStream declaring a full success, returning S_OK.

The callback function returns any negative error code to report its failure at saving the desired item and to direct that DPA_SaveStream not ask to save any more items. This causes DPA_SaveStream to declare a partial success, returning S_FALSE.

Behaviour if the callback function returns any positive value may best be treated as undefined.

Error Details

In version 6.10 and higher, the function returns E_INVALIDARG is the pdpa argument is NULL. Earlier versions check that pdpa is plausibly a DPA handle (meaning specifically that it must be an address at which the bytes of a DPA structure are writable).

Historically, the function also returns E_INVALIDARG if either the pfn or pstm arguments are not valid as addresses for reading at least one byte. These checks are removed entirely in versions 5.82 and 6.0 starting from Windows XP SP2. However, less strict defences are reinstated in the version 5.82 from Windows Vista and higher, and in version 6.10 and higher: the function returns E_INVALIDARG if either pfn or pstm is NULL.

The function returns error codes from the given stream’s Seek or Write methods, if these fail when noting the stream’s initial seek position or when first writing the header or when noting the stream’s seek position after items have been written.

Availability

The DPA_SaveStream function is exported from COMCTL32.DLL as ordinal 10 in version 4.71 and higher. The implementation for version 6.10 and higher is built into a statically linked library and thence is also exported from the Internet Explorer module IERTUTIL.DLL as ordinal 88 in version 7.0 and higher.

Though this function dates from as long ago as 1997, it was still not documented by Microsoft in the MSDN Library at least as late as the CD edition dated January 2004.

Microsoft documented this function for the MSDN on-line in April 2005, apparently after a contributor to a blog by Dave Massy (at Microsoft) cited this function as a counter-example to Massy’s claim that Internet Explorer uses no Windows API functions that were not by then documented by Microsoft. This article now follows Microsoft’s nomenclature as much as possible.

Microsoft’s name for the DPASTREAMINFO structure has long been knowable even without formal documentation from Microsoft. The DPA_SaveStream function is called from BROWSEUI.DLL, SHDOCVW.DLL and SHELL32.DLL, almost certainly from one source file used for all three executables. The callback function is written in C++ and the decorated name, as seen in Microsoft’s symbol files for these DLLs, therefore includes the name of the information structure.

The DPASTREAMHEADER structure and its members are not documented, and the names used here are invented. Indeed, the naming of the dwVersion member as providing some sort of version number is mere supposition. That the header is left undocumented is not unreasonable if the point is made clear that the stream written by DPA_SaveStream is to be interpreted only by DPA_LoadStream, for the internal structure of the header would then be an implementation detail of this pair of DPA functions.