2 * Dynamic pointer array (DPA) implementation
4 * Copyright 1998 Eric Kohl
5 * 1998 Juergen Schmied <j.schmied@metronet.de>
6 * 2000 Eric Kohl for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 * These functions were involuntarily documented by Microsoft in 2002 as
24 * the outcome of an anti-trust suit brought by various U.S. governments.
25 * As a result the specifications on MSDN are inaccurate, incomplete
26 * and misleading. A much more complete (unofficial) documentation is
29 * http://members.ozemail.com.au/~geoffch/samples/win32/shell/comctl32
32 #define WIN32_NO_STATUS
34 #define COM_NO_WINDOWS_H
43 //#include "winuser.h"
44 //#include "commctrl.h"
48 #include <wine/debug.h>
50 WINE_DEFAULT_DEBUG_CHANNEL(dpa
);
61 typedef struct _STREAMDATA
66 } STREAMDATA
, *PSTREAMDATA
;
68 /**************************************************************************
69 * DPA_LoadStream [COMCTL32.9]
71 * Loads a dynamic pointer array from a stream
74 * phDpa [O] pointer to a handle to a dynamic pointer array
75 * loadProc [I] pointer to a callback function
76 * pStream [I] pointer to a stream
77 * pData [I] pointer to callback data
80 * Success: S_OK, S_FALSE - partial success
81 * Failure: HRESULT error code
84 * No more information available yet!
86 HRESULT WINAPI
DPA_LoadStream (HDPA
*phDpa
, PFNDPASTREAM loadProc
,
87 IStream
*pStream
, LPVOID pData
)
90 LARGE_INTEGER position
;
91 ULARGE_INTEGER initial_pos
;
92 STREAMDATA streamData
;
93 DPASTREAMINFO streamInfo
;
98 TRACE ("phDpa=%p loadProc=%p pStream=%p pData=%p\n",
99 phDpa
, loadProc
, pStream
, pData
);
101 if (!phDpa
|| !loadProc
|| !pStream
)
106 position
.QuadPart
= 0;
108 errCode
= IStream_Seek (pStream
, position
, STREAM_SEEK_CUR
, &initial_pos
);
112 memset(&streamData
, 0, sizeof(STREAMDATA
));
113 errCode
= IStream_Read (pStream
, &streamData
, sizeof(STREAMDATA
), &ulRead
);
117 TRACE ("dwSize=%u dwData2=%u dwItems=%u\n",
118 streamData
.dwSize
, streamData
.dwData2
, streamData
.dwItems
);
120 if (ulRead
< sizeof(STREAMDATA
) ||
121 streamData
.dwSize
< sizeof(STREAMDATA
) || streamData
.dwData2
!= 1) {
122 /* back to initial position */
123 position
.QuadPart
= initial_pos
.QuadPart
;
124 IStream_Seek (pStream
, position
, STREAM_SEEK_SET
, NULL
);
128 if (streamData
.dwItems
> (UINT_MAX
/ 2 / sizeof(VOID
*))) /* 536870911 */
129 return E_OUTOFMEMORY
;
132 hDpa
= DPA_Create (streamData
.dwItems
);
134 return E_OUTOFMEMORY
;
136 if (!DPA_Grow (hDpa
, streamData
.dwItems
))
137 return E_OUTOFMEMORY
;
139 /* load data from the stream into the dpa */
141 for (streamInfo
.iPos
= 0; streamInfo
.iPos
< streamData
.dwItems
; streamInfo
.iPos
++) {
142 errCode
= (loadProc
)(&streamInfo
, pStream
, pData
);
143 if (errCode
!= S_OK
) {
148 *ptr
= streamInfo
.pvItem
;
152 /* set the number of items */
153 hDpa
->nItemCount
= streamInfo
.iPos
;
155 /* store the handle to the dpa */
157 TRACE ("new hDpa=%p, errorcode=%x\n", hDpa
, errCode
);
163 /**************************************************************************
164 * DPA_SaveStream [COMCTL32.10]
166 * Saves a dynamic pointer array to a stream
169 * hDpa [I] handle to a dynamic pointer array
170 * saveProc [I] pointer to a callback function
171 * pStream [I] pointer to a stream
172 * pData [I] pointer to callback data
175 * Success: S_OK, S_FALSE - partial success
176 * Failure: HRESULT error code
179 * No more information available yet!
181 HRESULT WINAPI
DPA_SaveStream (const HDPA hDpa
, PFNDPASTREAM saveProc
,
182 IStream
*pStream
, LPVOID pData
)
184 LARGE_INTEGER position
;
185 ULARGE_INTEGER initial_pos
, curr_pos
;
186 STREAMDATA streamData
;
187 DPASTREAMINFO streamInfo
;
191 TRACE ("hDpa=%p saveProc=%p pStream=%p pData=%p\n",
192 hDpa
, saveProc
, pStream
, pData
);
194 if (!hDpa
|| !saveProc
|| !pStream
) return E_INVALIDARG
;
196 /* save initial position to write header after completion */
197 position
.QuadPart
= 0;
198 hr
= IStream_Seek (pStream
, position
, STREAM_SEEK_CUR
, &initial_pos
);
202 /* write empty header */
203 streamData
.dwSize
= sizeof(streamData
);
204 streamData
.dwData2
= 1;
205 streamData
.dwItems
= 0;
207 hr
= IStream_Write (pStream
, &streamData
, sizeof(streamData
), NULL
);
209 position
.QuadPart
= initial_pos
.QuadPart
;
210 IStream_Seek (pStream
, position
, STREAM_SEEK_SET
, NULL
);
214 /* no items - we're done */
215 if (hDpa
->nItemCount
== 0) return S_OK
;
218 for (streamInfo
.iPos
= 0; streamInfo
.iPos
< hDpa
->nItemCount
; streamInfo
.iPos
++) {
219 streamInfo
.pvItem
= *ptr
;
220 hr
= (saveProc
)(&streamInfo
, pStream
, pData
);
228 /* write updated header */
229 position
.QuadPart
= 0;
230 IStream_Seek (pStream
, position
, STREAM_SEEK_CUR
, &curr_pos
);
232 streamData
.dwSize
= curr_pos
.QuadPart
- initial_pos
.QuadPart
;
233 streamData
.dwData2
= 1;
234 streamData
.dwItems
= streamInfo
.iPos
;
236 position
.QuadPart
= initial_pos
.QuadPart
;
237 IStream_Seek (pStream
, position
, STREAM_SEEK_SET
, NULL
);
238 IStream_Write (pStream
, &streamData
, sizeof(streamData
), NULL
);
240 position
.QuadPart
= curr_pos
.QuadPart
;
241 IStream_Seek (pStream
, position
, STREAM_SEEK_SET
, NULL
);
247 /**************************************************************************
248 * DPA_Merge [COMCTL32.11]
250 * Merge two dynamic pointers arrays.
253 * hdpa1 [I] handle to a dynamic pointer array
254 * hdpa2 [I] handle to a dynamic pointer array
256 * pfnCompare [I] pointer to sort function
257 * pfnMerge [I] pointer to merge function
258 * lParam [I] application specific value
265 * No more information available yet!
267 BOOL WINAPI
DPA_Merge (HDPA hdpa1
, HDPA hdpa2
, DWORD dwFlags
,
268 PFNDPACOMPARE pfnCompare
, PFNDPAMERGE pfnMerge
,
272 LPVOID
*pWork1
, *pWork2
;
276 TRACE("%p %p %08x %p %p %08lx)\n",
277 hdpa1
, hdpa2
, dwFlags
, pfnCompare
, pfnMerge
, lParam
);
279 if (IsBadWritePtr (hdpa1
, sizeof(*hdpa1
)))
282 if (IsBadWritePtr (hdpa2
, sizeof(*hdpa2
)))
285 if (IsBadCodePtr ((FARPROC
)pfnCompare
))
288 if (IsBadCodePtr ((FARPROC
)pfnMerge
))
291 if (!(dwFlags
& DPAM_SORTED
)) {
292 TRACE("sorting dpa's!\n");
293 if (hdpa1
->nItemCount
> 0)
294 DPA_Sort (hdpa1
, pfnCompare
, lParam
);
295 TRACE ("dpa 1 sorted!\n");
296 if (hdpa2
->nItemCount
> 0)
297 DPA_Sort (hdpa2
, pfnCompare
, lParam
);
298 TRACE ("dpa 2 sorted!\n");
301 if (hdpa2
->nItemCount
< 1)
304 TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n",
305 hdpa1
->nItemCount
, hdpa2
->nItemCount
);
308 /* working but untrusted implementation */
310 pWork1
= &(hdpa1
->ptrs
[hdpa1
->nItemCount
- 1]);
311 pWork2
= &(hdpa2
->ptrs
[hdpa2
->nItemCount
- 1]);
313 nIndex
= hdpa1
->nItemCount
- 1;
314 nCount
= hdpa2
->nItemCount
- 1;
319 if ((nCount
>= 0) && (dwFlags
& DPAM_UNION
)) {
320 /* Now insert the remaining new items into DPA 1 */
321 TRACE("%d items to be inserted at start of DPA 1\n",
323 for (i
=nCount
; i
>=0; i
--) {
326 ptr
= (pfnMerge
)(DPAMM_INSERT
, *pWork2
, NULL
, lParam
);
329 DPA_InsertPtr (hdpa1
, 0, ptr
);
335 nResult
= (pfnCompare
)(*pWork1
, *pWork2
, lParam
);
336 TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n",
337 nResult
, nIndex
, nCount
);
343 ptr
= (pfnMerge
)(DPAMM_MERGE
, *pWork1
, *pWork2
, lParam
);
353 else if (nResult
> 0)
355 /* item in DPA 1 missing from DPA 2 */
356 if (dwFlags
& DPAM_INTERSECT
)
358 /* Now delete the extra item in DPA1 */
361 ptr
= DPA_DeletePtr (hdpa1
, nIndex
);
363 (pfnMerge
)(DPAMM_DELETE
, ptr
, NULL
, lParam
);
370 /* new item in DPA 2 */
371 if (dwFlags
& DPAM_UNION
)
373 /* Now insert the new item in DPA 1 */
376 ptr
= (pfnMerge
)(DPAMM_INSERT
, *pWork2
, NULL
, lParam
);
379 DPA_InsertPtr (hdpa1
, nIndex
+1, ptr
);
392 /**************************************************************************
393 * DPA_Destroy [COMCTL32.329]
395 * Destroys a dynamic pointer array
398 * hdpa [I] handle (pointer) to the pointer array
404 BOOL WINAPI
DPA_Destroy (const HDPA hdpa
)
406 TRACE("(%p)\n", hdpa
);
411 if (hdpa
->ptrs
&& (!HeapFree (hdpa
->hHeap
, 0, hdpa
->ptrs
)))
414 return HeapFree (hdpa
->hHeap
, 0, hdpa
);
418 /**************************************************************************
419 * DPA_Grow [COMCTL32.330]
421 * Sets the growth amount.
424 * hdpa [I] handle (pointer) to the existing (source) pointer array
425 * nGrow [I] number of items by which the array grows when it's too small
431 BOOL WINAPI
DPA_Grow (HDPA hdpa
, INT nGrow
)
434 TRACE("(%p %d)\n", hdpa
, nGrow
);
439 nGrow
= max( 8, nGrow
);
440 items
= nGrow
* (((hdpa
->nMaxCount
- 1) / nGrow
) + 1);
441 if (items
> hdpa
->nMaxCount
)
446 ptr
= HeapReAlloc( hdpa
->hHeap
, HEAP_ZERO_MEMORY
, hdpa
->ptrs
, items
* sizeof(LPVOID
) );
448 ptr
= HeapAlloc( hdpa
->hHeap
, HEAP_ZERO_MEMORY
, items
* sizeof(LPVOID
) );
449 if (!ptr
) return FALSE
;
450 hdpa
->nMaxCount
= items
;
459 /**************************************************************************
460 * DPA_Clone [COMCTL32.331]
462 * Copies a pointer array to an other one or creates a copy
465 * hdpa [I] handle (pointer) to the existing (source) pointer array
466 * hdpaNew [O] handle (pointer) to the destination pointer array
469 * Success: pointer to the destination pointer array.
473 * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
474 * array will be created and it's handle (pointer) is returned.
475 * - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
476 * this implementation just returns NULL.
478 HDPA WINAPI
DPA_Clone (const HDPA hdpa
, const HDPA hdpaNew
)
480 INT nNewItems
, nSize
;
486 TRACE("(%p %p)\n", hdpa
, hdpaNew
);
489 /* create a new DPA */
490 hdpaTemp
= HeapAlloc (hdpa
->hHeap
, HEAP_ZERO_MEMORY
,
492 hdpaTemp
->hHeap
= hdpa
->hHeap
;
493 hdpaTemp
->nGrow
= hdpa
->nGrow
;
498 if (hdpaTemp
->ptrs
) {
499 /* remove old pointer array */
500 HeapFree (hdpaTemp
->hHeap
, 0, hdpaTemp
->ptrs
);
501 hdpaTemp
->ptrs
= NULL
;
502 hdpaTemp
->nItemCount
= 0;
503 hdpaTemp
->nMaxCount
= 0;
506 /* create a new pointer array */
507 nNewItems
= hdpaTemp
->nGrow
*
508 (((hdpa
->nItemCount
- 1) / hdpaTemp
->nGrow
) + 1);
509 nSize
= nNewItems
* sizeof(LPVOID
);
510 hdpaTemp
->ptrs
= HeapAlloc (hdpaTemp
->hHeap
, HEAP_ZERO_MEMORY
, nSize
);
511 hdpaTemp
->nMaxCount
= nNewItems
;
513 /* clone the pointer array */
514 hdpaTemp
->nItemCount
= hdpa
->nItemCount
;
515 memmove (hdpaTemp
->ptrs
, hdpa
->ptrs
,
516 hdpaTemp
->nItemCount
* sizeof(LPVOID
));
522 /**************************************************************************
523 * DPA_GetPtr [COMCTL32.332]
525 * Retrieves a pointer from a dynamic pointer array
528 * hdpa [I] handle (pointer) to the pointer array
529 * nIndex [I] array index of the desired pointer
535 LPVOID WINAPI
DPA_GetPtr (const HDPA hdpa
, INT nIndex
)
537 TRACE("(%p %d)\n", hdpa
, nIndex
);
542 WARN("no pointer array.\n");
545 if ((nIndex
< 0) || (nIndex
>= hdpa
->nItemCount
)) {
546 WARN("not enough pointers in array (%d vs %d).\n",nIndex
,hdpa
->nItemCount
);
550 TRACE("-- %p\n", hdpa
->ptrs
[nIndex
]);
552 return hdpa
->ptrs
[nIndex
];
556 /**************************************************************************
557 * DPA_GetPtrIndex [COMCTL32.333]
559 * Retrieves the index of the specified pointer
562 * hdpa [I] handle (pointer) to the pointer array
566 * Success: index of the specified pointer
569 INT WINAPI
DPA_GetPtrIndex (HDPA hdpa
, LPCVOID p
)
573 if (!hdpa
|| !hdpa
->ptrs
)
576 for (i
= 0; i
< hdpa
->nItemCount
; i
++) {
577 if (hdpa
->ptrs
[i
] == p
)
585 /**************************************************************************
586 * DPA_InsertPtr [COMCTL32.334]
588 * Inserts a pointer into a dynamic pointer array
591 * hdpa [I] handle (pointer) to the array
593 * p [I] pointer to insert
596 * Success: index of the inserted pointer
599 INT WINAPI
DPA_InsertPtr (const HDPA hdpa
, INT i
, LPVOID p
)
601 TRACE("(%p %d %p)\n", hdpa
, i
, p
);
603 if (!hdpa
|| i
< 0) return -1;
605 /* append item if index is out of bounds */
606 i
= min(hdpa
->nItemCount
, i
);
608 /* create empty spot at the end */
609 if (!DPA_SetPtr(hdpa
, hdpa
->nItemCount
, 0)) return -1;
611 if (i
!= hdpa
->nItemCount
- 1)
612 memmove (hdpa
->ptrs
+ i
+ 1, hdpa
->ptrs
+ i
,
613 (hdpa
->nItemCount
- i
- 1) * sizeof(LPVOID
));
620 /**************************************************************************
621 * DPA_SetPtr [COMCTL32.335]
623 * Sets a pointer in the pointer array
626 * hdpa [I] handle (pointer) to the pointer array
627 * i [I] index of the pointer that will be set
628 * p [I] pointer to be set
634 BOOL WINAPI
DPA_SetPtr (const HDPA hdpa
, INT i
, LPVOID p
)
638 TRACE("(%p %d %p)\n", hdpa
, i
, p
);
643 if (hdpa
->nItemCount
<= i
) {
644 /* within the old array */
645 if (hdpa
->nMaxCount
<= i
) {
646 /* resize the block of memory */
648 hdpa
->nGrow
* ((((i
+1) - 1) / hdpa
->nGrow
) + 1);
649 INT nSize
= nNewItems
* sizeof(LPVOID
);
652 lpTemp
= HeapReAlloc (hdpa
->hHeap
, HEAP_ZERO_MEMORY
, hdpa
->ptrs
, nSize
);
654 lpTemp
= HeapAlloc (hdpa
->hHeap
, HEAP_ZERO_MEMORY
, nSize
);
659 hdpa
->nMaxCount
= nNewItems
;
662 hdpa
->nItemCount
= i
+1;
665 /* put the new entry in */
672 /**************************************************************************
673 * DPA_DeletePtr [COMCTL32.336]
675 * Removes a pointer from the pointer array.
678 * hdpa [I] handle (pointer) to the pointer array
679 * i [I] index of the pointer that will be deleted
682 * Success: deleted pointer
685 LPVOID WINAPI
DPA_DeletePtr (const HDPA hdpa
, INT i
)
687 LPVOID
*lpDest
, *lpSrc
, lpTemp
= NULL
;
690 TRACE("(%p %d)\n", hdpa
, i
);
692 if ((!hdpa
) || i
< 0 || i
>= hdpa
->nItemCount
)
695 lpTemp
= hdpa
->ptrs
[i
];
697 /* do we need to move ?*/
698 if (i
< hdpa
->nItemCount
- 1) {
699 lpDest
= hdpa
->ptrs
+ i
;
701 nSize
= (hdpa
->nItemCount
- i
- 1) * sizeof(LPVOID
);
702 TRACE("-- move dest=%p src=%p size=%x\n",
703 lpDest
, lpSrc
, nSize
);
704 memmove (lpDest
, lpSrc
, nSize
);
710 if ((hdpa
->nMaxCount
- hdpa
->nItemCount
) >= hdpa
->nGrow
) {
711 INT nNewItems
= max(hdpa
->nGrow
* 2, hdpa
->nItemCount
);
712 nSize
= nNewItems
* sizeof(LPVOID
);
713 lpDest
= HeapReAlloc (hdpa
->hHeap
, HEAP_ZERO_MEMORY
,
718 hdpa
->nMaxCount
= nNewItems
;
726 /**************************************************************************
727 * DPA_DeleteAllPtrs [COMCTL32.337]
729 * Removes all pointers and reinitializes the array.
732 * hdpa [I] handle (pointer) to the pointer array
738 BOOL WINAPI
DPA_DeleteAllPtrs (const HDPA hdpa
)
740 TRACE("(%p)\n", hdpa
);
745 if (hdpa
->ptrs
&& (!HeapFree (hdpa
->hHeap
, 0, hdpa
->ptrs
)))
748 hdpa
->nItemCount
= 0;
749 hdpa
->nMaxCount
= hdpa
->nGrow
* 2;
750 hdpa
->ptrs
= HeapAlloc (hdpa
->hHeap
, HEAP_ZERO_MEMORY
,
751 hdpa
->nMaxCount
* sizeof(LPVOID
));
757 /**************************************************************************
758 * DPA_QuickSort [Internal]
760 * Ordinary quicksort (used by DPA_Sort).
763 * lpPtrs [I] pointer to the pointer array
764 * l [I] index of the "left border" of the partition
765 * r [I] index of the "right border" of the partition
766 * pfnCompare [I] pointer to the compare function
767 * lParam [I] user defined value (3rd parameter in compare function)
772 static VOID
DPA_QuickSort (LPVOID
*lpPtrs
, INT l
, INT r
,
773 PFNDPACOMPARE pfnCompare
, LPARAM lParam
)
778 TRACE("l=%i r=%i\n", l
, r
);
780 if (l
==r
) /* one element is always sorted */
782 if (r
<l
) /* oops, got it in the wrong order */
784 DPA_QuickSort(lpPtrs
, r
, l
, pfnCompare
, lParam
);
787 m
= (l
+r
)/2; /* divide by two */
788 DPA_QuickSort(lpPtrs
, l
, m
, pfnCompare
, lParam
);
789 DPA_QuickSort(lpPtrs
, m
+1, r
, pfnCompare
, lParam
);
791 /* join the two sides */
792 while( (l
<=m
) && (m
<r
) )
794 if(pfnCompare(lpPtrs
[l
],lpPtrs
[m
+1],lParam
)>0)
797 memmove(&lpPtrs
[l
+1],&lpPtrs
[l
],(m
-l
+1)*sizeof(lpPtrs
[l
]));
807 /**************************************************************************
808 * DPA_Sort [COMCTL32.338]
810 * Sorts a pointer array using a user defined compare function
813 * hdpa [I] handle (pointer) to the pointer array
814 * pfnCompare [I] pointer to the compare function
815 * lParam [I] user defined value (3rd parameter of compare function)
821 BOOL WINAPI
DPA_Sort (const HDPA hdpa
, PFNDPACOMPARE pfnCompare
, LPARAM lParam
)
823 if (!hdpa
|| !pfnCompare
)
826 TRACE("(%p %p 0x%lx)\n", hdpa
, pfnCompare
, lParam
);
828 if ((hdpa
->nItemCount
> 1) && (hdpa
->ptrs
))
829 DPA_QuickSort (hdpa
->ptrs
, 0, hdpa
->nItemCount
- 1,
836 /**************************************************************************
837 * DPA_Search [COMCTL32.339]
839 * Searches a pointer array for a specified pointer
842 * hdpa [I] handle (pointer) to the pointer array
843 * pFind [I] pointer to search for
844 * nStart [I] start index
845 * pfnCompare [I] pointer to the compare function
846 * lParam [I] user defined value (3rd parameter of compare function)
847 * uOptions [I] search options
850 * Success: index of the pointer in the array.
853 INT WINAPI
DPA_Search (const HDPA hdpa
, LPVOID pFind
, INT nStart
,
854 PFNDPACOMPARE pfnCompare
, LPARAM lParam
, UINT uOptions
)
856 if (!hdpa
|| !pfnCompare
|| !pFind
)
859 TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n",
860 hdpa
, pFind
, nStart
, pfnCompare
, lParam
, uOptions
);
862 if (uOptions
& DPAS_SORTED
) {
863 /* array is sorted --> use binary search */
867 /* for binary search ignore start index */
869 r
= hdpa
->nItemCount
- 1;
873 n
= (pfnCompare
)(pFind
, lpPtr
[x
], lParam
);
881 if (uOptions
& (DPAS_INSERTBEFORE
|DPAS_INSERTAFTER
)) return l
;
884 /* array is not sorted --> use linear search */
888 nIndex
= (nStart
== -1)? 0 : nStart
;
890 for (; nIndex
< hdpa
->nItemCount
; nIndex
++) {
891 if ((pfnCompare
)(pFind
, lpPtr
[nIndex
], lParam
) == 0)
900 /**************************************************************************
901 * DPA_CreateEx [COMCTL32.340]
903 * Creates a dynamic pointer array using the specified size and heap.
906 * nGrow [I] number of items by which the array grows when it is filled
907 * hHeap [I] handle to the heap where the array is stored
910 * Success: handle (pointer) to the pointer array.
914 * The DPA_ functions can be used to create and manipulate arrays of
917 HDPA WINAPI
DPA_CreateEx (INT nGrow
, HANDLE hHeap
)
921 TRACE("(%d %p)\n", nGrow
, hHeap
);
924 hdpa
= HeapAlloc (hHeap
, HEAP_ZERO_MEMORY
, sizeof(*hdpa
));
926 hdpa
= Alloc (sizeof(*hdpa
));
929 hdpa
->nGrow
= max(8, nGrow
);
930 hdpa
->hHeap
= hHeap
? hHeap
: GetProcessHeap();
931 hdpa
->nMaxCount
= hdpa
->nGrow
* 2;
932 hdpa
->ptrs
= HeapAlloc (hdpa
->hHeap
, HEAP_ZERO_MEMORY
,
933 hdpa
->nMaxCount
* sizeof(LPVOID
));
936 TRACE("-- %p\n", hdpa
);
942 /**************************************************************************
943 * DPA_Create [COMCTL32.328]
945 * Creates a dynamic pointer array.
948 * nGrow [I] number of items by which the array grows when it is filled
951 * Success: handle (pointer) to the pointer array.
955 * The DPA_ functions can be used to create and manipulate arrays of
958 HDPA WINAPI
DPA_Create (INT nGrow
)
960 return DPA_CreateEx( nGrow
, 0 );
964 /**************************************************************************
965 * DPA_EnumCallback [COMCTL32.385]
967 * Enumerates all items in a dynamic pointer array.
970 * hdpa [I] handle to the dynamic pointer array
977 VOID WINAPI
DPA_EnumCallback (HDPA hdpa
, PFNDPAENUMCALLBACK enumProc
,
982 TRACE("(%p %p %p)\n", hdpa
, enumProc
, lParam
);
986 if (hdpa
->nItemCount
<= 0)
989 for (i
= 0; i
< hdpa
->nItemCount
; i
++) {
990 if ((enumProc
)(hdpa
->ptrs
[i
], lParam
) == 0)
998 /**************************************************************************
999 * DPA_DestroyCallback [COMCTL32.386]
1001 * Enumerates all items in a dynamic pointer array and destroys it.
1004 * hdpa [I] handle to the dynamic pointer array
1011 void WINAPI
DPA_DestroyCallback (HDPA hdpa
, PFNDPAENUMCALLBACK enumProc
,
1014 TRACE("(%p %p %p)\n", hdpa
, enumProc
, lParam
);
1016 DPA_EnumCallback (hdpa
, enumProc
, lParam
);
1020 /**************************************************************************
1021 * DPA_GetSize [COMCTL32.@]
1023 * Returns all array allocated memory size
1026 * hdpa [I] handle to the dynamic pointer array
1031 ULONGLONG WINAPI
DPA_GetSize(HDPA hdpa
)
1033 TRACE("(%p)\n", hdpa
);
1035 if (!hdpa
) return 0;
1037 return sizeof(DPA
) + hdpa
->nMaxCount
*sizeof(PVOID
);