| Home | Table of Contents | Please view with Internet Explorer (version 5.00 or higher) and enable scripting. For reasons, see Browsing This Web Site. |
COMCTL32 manages each Dynamic Pointer Array through a 14h-byte control structure, whose address serves as a handle to the DPA.
typedef struct _DPA {
int cpItems;
PVOID *pArray;
HANDLE hHeap;
int cpCapacity;
int cpGrow;
} DPA, *HDPA;
The cpItems member is the current size of the pointer array, measured as a number of pointers.
The pArray member is the address of the pointer array, or is NULL.
The hHeap member is a handle to the heap that provides memory for this DPA.
The cpCapacity member is the current capacity of the pointer array, measured as a number of pointers.
The cpGrow member is the allocation unit for the heap block that holds the pointer array, measured as a number of pointers.
The DPA structure, but not its internal detail, was documented as part of Microsoft’s documentation of DPA functions among the Settlement Program Interfaces in 2002. The names _DPA for the structure and HDPA for the handle are Microsoft’s. The names given above for the members of this structure are invented.
This omission of internal detail is entirely in keeping with a principle that the DPA is opaque, so that code outside the implementations of the DPA functions, or at least outside COMCTL32, may use the structure’s address as a handle but not interpret the structure. Microsoft’s own practice, however, is that various modules external to COMCTL32 interpret either or both of the cpItems and pArray members. Among these modules are BROWSEUI, EXPLORER, SHDOCVW, SHELL32 and SHLWAPI.
The most frequent use that Microsoft has for the internal detail is a very obvious one whose purpose is indeed not accommodated (directly) by the functional interface. The list represented by a DPA may be enumerated easily enough by calling DPA_GetPtr repeatedly, giving a successively higher index each time. If the list is known to be managed only in such a way that it cannot be sparse, then the first return of a NULL pointer indicates that all items have been seen, but otherwise, at what index should the enumeration stop? No one exported function returns anything from which to know, though a limiting index can be determined in steps, e.g., by calling DPA_InsertPtr to append a dummy item, remembering the index that is returned, and calling DPA_DeletePtr to remove the dummy. It can only be good that Microsoft’s programmers avoid such clumsiness by going directly to the cpItems member of the DPA.