2 * Undocumented functions from COMCTL32.DLL
4 * Copyright 1998 Eric Kohl <ekohl@abo.rhein-zeitung.de>
5 * 1998 Juergen Schmied <j.schmied@metronet.de>
7 * All of these functions are UNDOCUMENTED!! And I mean UNDOCUMENTED!!!!
8 * Do NOT rely on names or contents of undocumented structures and types!!!
9 * These functions are used by EXPLORER.EXE, IEXPLORE.EXE and
10 * COMCTL32.DLL (internally).
13 * - Add more functions.
14 * - Write some documentation.
18 #include <stdlib.h> /* atoi */
25 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(commctrl)
30 extern HANDLE COMCTL32_hHeap; /* handle to the private heap */
33 * We put some function prototypes here that don't seem to belong in
34 * any header file. When they find their place, we can remove them.
36 extern LPWSTR __cdecl CRTDLL_wcschr(LPCWSTR, WCHAR);
37 extern LPSTR WINAPI lstrrchr(LPCSTR, LPCSTR, WORD);
38 extern LPWSTR WINAPI lstrrchrw(LPCWSTR, LPCWSTR, WORD);
39 extern LPWSTR WINAPI strstrw(LPCWSTR, LPCWSTR);
42 typedef struct _STREAMDATA
47 } STREAMDATA, *PSTREAMDATA;
49 typedef struct _LOADDATA
53 } LOADDATA, *LPLOADDATA;
55 typedef HRESULT(CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM);
58 /**************************************************************************
59 * DPA_LoadStream [COMCTL32.9]
61 * Loads a dynamic pointer array from a stream
64 * phDpa [O] pointer to a handle to a dynamic pointer array
65 * loadProc [I] pointer to a callback function
66 * pStream [I] pointer to a stream
67 * lParam [I] application specific value
70 * No more information available yet!
74 DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
77 LARGE_INTEGER position;
78 ULARGE_INTEGER newPosition;
79 STREAMDATA streamData;
85 FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
86 phDpa, loadProc, pStream, lParam);
88 if (!phDpa || !loadProc || !pStream)
94 position.HighPart = 0;
96 errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition);
100 errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead);
104 FIXME ("dwSize=%lu dwData2=%lu dwItems=%lu\n",
105 streamData.dwSize, streamData.dwData2, streamData.dwItems);
107 if (lParam < sizeof(STREAMDATA) ||
108 streamData.dwSize < sizeof(STREAMDATA) ||
109 streamData.dwData2 < 1) {
114 hDpa = DPA_Create (streamData.dwItems);
116 return E_OUTOFMEMORY;
118 if (!DPA_Grow (hDpa, streamData.dwItems))
119 return E_OUTOFMEMORY;
121 /* load data from the stream into the dpa */
123 for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) {
124 errCode = (loadProc)(&loadData, pStream, lParam);
125 if (errCode != S_OK) {
134 /* set the number of items */
135 hDpa->nItemCount = loadData.nCount;
137 /* store the handle to the dpa */
139 FIXME ("new hDpa=%p\n", hDpa);
145 /**************************************************************************
146 * DPA_SaveStream [COMCTL32.10]
148 * Saves a dynamic pointer array to a stream
151 * hDpa [I] handle to a dynamic pointer array
152 * loadProc [I] pointer to a callback function
153 * pStream [I] pointer to a stream
154 * lParam [I] application specific value
157 * No more information available yet!
161 DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
164 FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
165 hDpa, loadProc, pStream, lParam);
171 /**************************************************************************
172 * DPA_Merge [COMCTL32.11]
175 * hdpa1 [I] handle to a dynamic pointer array
176 * hdpa2 [I] handle to a dynamic pointer array
178 * pfnSort [I] pointer to sort function
179 * pfnMerge [I] pointer to merge function
180 * lParam [I] application specific value
183 * No more information available yet!
187 DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
188 PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam)
190 LPVOID pWork1, pWork2;
195 TRACE("(%p %p %08lx %p %p %08lx): semi stub!\n",
196 hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam);
198 if (IsBadWritePtr (hdpa1, sizeof(DPA)))
201 if (IsBadWritePtr (hdpa2, sizeof(DPA)))
204 if (IsBadCodePtr ((FARPROC)pfnCompare))
207 if (IsBadCodePtr ((FARPROC)pfnMerge))
210 if (dwFlags & DPAM_SORT) {
211 TRACE("sorting dpa's!\n");
212 if (hdpa1->nItemCount > 0)
213 DPA_Sort (hdpa1, pfnCompare, lParam);
214 TRACE ("dpa 1 sorted!\n");
215 if (hdpa2->nItemCount > 0)
216 DPA_Sort (hdpa2, pfnCompare, lParam);
217 TRACE ("dpa 2 sorted!\n");
220 if (hdpa2->nItemCount < 1)
223 TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n",
224 hdpa1->nItemCount, hdpa2->nItemCount);
227 /* preliminary hack - simply append the pointer list hdpa2 to hdpa1*/
228 for (nCount = 0; nCount < hdpa2->nItemCount; nCount++)
229 DPA_InsertPtr (hdpa1, hdpa1->nItemCount + 1, hdpa2->ptrs[nCount]);
232 /* incomplete implementation */
234 pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]);
235 pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]);
237 nIndex = hdpa1->nItemCount - 1;
238 nCount = hdpa2->nItemCount - 1;
242 nResult = (pfnCompare)(pWork1, pWork2, lParam);
248 ptr = (pfnMerge)(1, pWork1, pWork2, lParam);
256 else if (nResult < 0)
262 ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1);
264 (pfnMerge)(2, ptr, NULL, lParam);
273 ptr = (pfnMerge)(3, pWork2, NULL, lParam);
276 DPA_InsertPtr (hdpa1, nIndex, ptr);
293 /**************************************************************************
294 * Alloc [COMCTL32.71]
296 * Allocates memory block from the dll's private heap
299 * dwSize [I] size of the allocated memory block
302 * Success: pointer to allocated memory block
307 COMCTL32_Alloc (DWORD dwSize)
311 TRACE("(0x%lx)\n", dwSize);
313 lpPtr = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
315 TRACE("-- ret=%p\n", lpPtr);
321 /**************************************************************************
322 * ReAlloc [COMCTL32.72]
324 * Changes the size of an allocated memory block or allocates a memory
325 * block using the dll's private heap.
328 * lpSrc [I] pointer to memory block which will be resized
329 * dwSize [I] new size of the memory block.
332 * Success: pointer to the resized memory block
336 * If lpSrc is a NULL-pointer, then COMCTL32_ReAlloc allocates a memory
337 * block like COMCTL32_Alloc.
341 COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
345 TRACE("(%p 0x%08lx)\n", lpSrc, dwSize);
348 lpDest = HeapReAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, lpSrc, dwSize);
350 lpDest = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
352 TRACE("-- ret=%p\n", lpDest);
358 /**************************************************************************
361 * Frees an allocated memory block from the dll's private heap.
364 * lpMem [I] pointer to memory block which will be freed
372 COMCTL32_Free (LPVOID lpMem)
374 TRACE("(%p)\n", lpMem);
376 return HeapFree (COMCTL32_hHeap, 0, lpMem);
380 /**************************************************************************
381 * GetSize [COMCTL32.74]
383 * Retrieves the size of the specified memory block from the dll's
387 * lpMem [I] pointer to an allocated memory block
390 * Success: size of the specified memory block
395 COMCTL32_GetSize (LPVOID lpMem)
397 TRACE("(%p)\n", lpMem);
399 return HeapSize (COMCTL32_hHeap, 0, lpMem);
403 /**************************************************************************
404 * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
410 typedef struct tagMRUINFO
418 } MRUINFO, *LPMRUINFO;
421 typedef struct tagMRU
423 DWORD dwParam1; /* some kind of flag */
432 CreateMRUListLazyA (LPMRUINFO lpmi, DWORD dwParam2,
433 DWORD dwParam3, DWORD dwParam4);
436 /**************************************************************************
437 * CreateMRUListA [COMCTL32.151]
446 CreateMRUListA (LPMRUINFO lpmi)
448 return CreateMRUListLazyA (lpmi, 0, 0, 0);
453 FreeMRUListA (HMRU hmru)
455 FIXME("(%p) empty stub!\n", hmru);
458 if (!(hmru->dwParam1 & 1001)) {
459 RegSetValueExA (hmru->hKeyMRU, "MRUList", 0, REG_SZ,
461 lstrlenA (hmru->lpszMRUString));
465 RegClosKey (hmru->hkeyMRU
466 COMCTL32_Free32 (hmru->lpszMRUString);
469 return COMCTL32_Free (hmru);
475 AddMRUData (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
478 FIXME("(%lx %lx %lx) empty stub!\n",
479 dwParam1, dwParam2, dwParam3);
486 FindMRUData (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
489 FIXME("(%lx %lx %lx %lx) empty stub!\n",
490 dwParam1, dwParam2, dwParam3, dwParam4);
497 CreateMRUListLazyA (LPMRUINFO lpmi, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
506 * DWORD dwDisposition; */
508 /* internal variables */
511 FIXME("(%p) empty stub!\n", lpmi);
514 FIXME("(%lx %lx %lx %lx \"%s\" %lx)\n",
515 lpmi->dwParam1, lpmi->dwParam2, lpmi->dwParam3,
516 (DWORD)lpmi->hkeyMain, lpmi->lpszSubKey, lpmi->dwParam6);
519 /* dummy pointer creation */
520 ptr = COMCTL32_Alloc (32);
522 FIXME("-- ret = %p\n", ptr);
530 /**************************************************************************
531 * Str_GetPtrA [COMCTL32.233]
542 Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
546 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
548 if (!lpDest && lpSrc)
549 return lstrlenA (lpSrc);
559 len = lstrlenA (lpSrc);
563 RtlMoveMemory (lpDest, lpSrc, len);
570 /**************************************************************************
571 * Str_SetPtrA [COMCTL32.234]
581 Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
583 TRACE("(%p %p)\n", lppDest, lpSrc);
586 LPSTR ptr = COMCTL32_ReAlloc (*lppDest, lstrlenA (lpSrc) + 1);
589 lstrcpyA (ptr, lpSrc);
594 COMCTL32_Free (*lppDest);
603 /**************************************************************************
604 * Str_GetPtrW [COMCTL32.235]
615 Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
619 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
621 if (!lpDest && lpSrc)
622 return lstrlenW (lpSrc);
632 len = lstrlenW (lpSrc);
636 RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
643 /**************************************************************************
644 * Str_SetPtrW [COMCTL32.236]
654 Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
656 TRACE("(%p %p)\n", lppDest, lpSrc);
659 INT len = lstrlenW (lpSrc) + 1;
660 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len * sizeof(WCHAR));
663 lstrcpyW (ptr, lpSrc);
668 COMCTL32_Free (*lppDest);
677 /**************************************************************************
678 * The DSA-API is a set of functions to create and manipulate arrays of
679 * fix sized memory blocks. These arrays can store any kind of data
680 * (strings, icons...).
683 /**************************************************************************
684 * DSA_Create [COMCTL32.320] Creates a dynamic storage array
687 * nSize [I] size of the array elements
688 * nGrow [I] number of elements by which the array grows when it is filled
691 * Success: pointer to a array control structure. use this like a handle.
696 DSA_Create (INT nSize, INT nGrow)
700 TRACE("(size=%d grow=%d)\n", nSize, nGrow);
702 hdsa = (HDSA)COMCTL32_Alloc (sizeof(DSA));
705 hdsa->nItemCount = 0;
708 hdsa->nItemSize = nSize;
709 hdsa->nGrow = MAX(1, nGrow);
716 /**************************************************************************
717 * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array
720 * hdsa [I] pointer to the array control structure
728 DSA_Destroy (const HDSA hdsa)
730 TRACE("(%p)\n", hdsa);
735 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
738 return COMCTL32_Free (hdsa);
742 /**************************************************************************
743 * DSA_GetItem [COMCTL32.322]
746 * hdsa [I] pointer to the array control structure
747 * nIndex [I] number of the Item to get
748 * pDest [O] destination buffer. Has to be >= dwElementSize.
756 DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
760 TRACE("(%p %d %p)\n", hdsa, nIndex, pDest);
764 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
767 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
768 memmove (pDest, pSrc, hdsa->nItemSize);
774 /**************************************************************************
775 * DSA_GetItemPtr [COMCTL32.323]
777 * Retrieves a pointer to the specified item.
780 * hdsa [I] pointer to the array control structure
781 * nIndex [I] index of the desired item
784 * Success: pointer to an item
789 DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
793 TRACE("(%p %d)\n", hdsa, nIndex);
797 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
800 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
802 TRACE("-- ret=%p\n", pSrc);
808 /**************************************************************************
809 * DSA_SetItem [COMCTL32.325]
811 * Sets the contents of an item in the array.
814 * hdsa [I] pointer to the array control structure
815 * nIndex [I] index for the item
816 * pSrc [I] pointer to the new item data
824 DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
826 INT nSize, nNewItems;
827 LPVOID pDest, lpTemp;
829 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
831 if ((!hdsa) || nIndex < 0)
834 if (hdsa->nItemCount <= nIndex) {
835 /* within the old array */
836 if (hdsa->nMaxCount > nIndex) {
837 /* within the allocated space, set a new boundary */
838 hdsa->nItemCount = nIndex + 1;
841 /* resize the block of memory */
843 hdsa->nGrow * ((INT)((nIndex - 1) / hdsa->nGrow) + 1);
844 nSize = hdsa->nItemSize * nNewItems;
846 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
850 hdsa->nMaxCount = nNewItems;
851 hdsa->nItemCount = nIndex + 1;
852 hdsa->pData = lpTemp;
856 /* put the new entry in */
857 pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
858 TRACE("-- move dest=%p src=%p size=%d\n",
859 pDest, pSrc, hdsa->nItemSize);
860 memmove (pDest, pSrc, hdsa->nItemSize);
866 /**************************************************************************
867 * DSA_InsertItem [COMCTL32.325]
870 * hdsa [I] pointer to the array control structure
871 * nIndex [I] index for the new item
872 * pSrc [I] pointer to the element
875 * Success: position of the new item
880 DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
882 INT nNewItems, nSize, i;
883 LPVOID lpTemp, lpDest;
886 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
888 if ((!hdsa) || nIndex < 0)
891 for (i = 0; i < hdsa->nItemSize; i += 4) {
892 p = *(DWORD**)((char *) pSrc + i);
893 if (IsBadStringPtrA ((char*)p, 256))
894 TRACE("-- %d=%p\n", i, (DWORD*)p);
896 TRACE("-- %d=%p [%s]\n", i, p, debugstr_a((char*)p));
899 /* when nIndex > nItemCount then append */
900 if (nIndex >= hdsa->nItemCount)
901 nIndex = hdsa->nItemCount;
903 /* do we need to resize ? */
904 if (hdsa->nItemCount >= hdsa->nMaxCount) {
905 nNewItems = hdsa->nMaxCount + hdsa->nGrow;
906 nSize = hdsa->nItemSize * nNewItems;
908 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
912 hdsa->nMaxCount = nNewItems;
913 hdsa->pData = lpTemp;
916 /* do we need to move elements ? */
917 if (nIndex < hdsa->nItemCount) {
918 lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
919 lpDest = (char *) lpTemp + hdsa->nItemSize;
920 nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
921 TRACE("-- move dest=%p src=%p size=%d\n",
922 lpDest, lpTemp, nSize);
923 memmove (lpDest, lpTemp, nSize);
926 /* ok, we can put the new Item in */
928 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
929 TRACE("-- move dest=%p src=%p size=%d\n",
930 lpDest, pSrc, hdsa->nItemSize);
931 memmove (lpDest, pSrc, hdsa->nItemSize);
933 return hdsa->nItemCount;
937 /**************************************************************************
938 * DSA_DeleteItem [COMCTL32.326]
941 * hdsa [I] pointer to the array control structure
942 * nIndex [I] index for the element to delete
945 * Success: number of the deleted element
950 DSA_DeleteItem (const HDSA hdsa, INT nIndex)
955 TRACE("(%p %d)\n", hdsa, nIndex);
959 if (nIndex < 0 || nIndex >= hdsa->nItemCount)
962 /* do we need to move ? */
963 if (nIndex < hdsa->nItemCount - 1) {
964 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
965 lpSrc = (char *) lpDest + hdsa->nItemSize;
966 nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
967 TRACE("-- move dest=%p src=%p size=%d\n",
968 lpDest, lpSrc, nSize);
969 memmove (lpDest, lpSrc, nSize);
975 if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
976 nSize = hdsa->nItemSize * hdsa->nItemCount;
978 lpDest = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
982 hdsa->nMaxCount = hdsa->nItemCount;
983 hdsa->pData = lpDest;
990 /**************************************************************************
991 * DSA_DeleteAllItems [COMCTL32.326]
993 * Removes all items and reinitializes the array.
996 * hdsa [I] pointer to the array control structure
1004 DSA_DeleteAllItems (const HDSA hdsa)
1006 TRACE("(%p)\n", hdsa);
1010 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1013 hdsa->nItemCount = 0;
1015 hdsa->nMaxCount = 0;
1021 /**************************************************************************
1022 * The DPA-API is a set of functions to create and manipulate arrays of
1026 /**************************************************************************
1027 * DPA_Create [COMCTL32.328] Creates a dynamic pointer array
1030 * nGrow [I] number of items by which the array grows when it is filled
1033 * Success: handle (pointer) to the pointer array.
1038 DPA_Create (INT nGrow)
1042 TRACE("(%d)\n", nGrow);
1044 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1046 hdpa->nGrow = MAX(8, nGrow);
1047 hdpa->hHeap = COMCTL32_hHeap;
1048 hdpa->nMaxCount = hdpa->nGrow * 2;
1050 (LPVOID*)COMCTL32_Alloc (hdpa->nMaxCount * sizeof(LPVOID));
1053 TRACE("-- %p\n", hdpa);
1059 /**************************************************************************
1060 * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array
1063 * hdpa [I] handle (pointer) to the pointer array
1071 DPA_Destroy (const HDPA hdpa)
1073 TRACE("(%p)\n", hdpa);
1078 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1081 return HeapFree (hdpa->hHeap, 0, hdpa);
1085 /**************************************************************************
1086 * DPA_Grow [COMCTL32.330]
1088 * Sets the growth amount.
1091 * hdpa [I] handle (pointer) to the existing (source) pointer array
1092 * nGrow [I] number of items, the array grows, when it's too small
1100 DPA_Grow (const HDPA hdpa, INT nGrow)
1102 TRACE("(%p %d)\n", hdpa, nGrow);
1107 hdpa->nGrow = MAX(8, nGrow);
1113 /**************************************************************************
1114 * DPA_Clone [COMCTL32.331]
1116 * Copies a pointer array to an other one or creates a copy
1119 * hdpa [I] handle (pointer) to the existing (source) pointer array
1120 * hdpaNew [O] handle (pointer) to the destination pointer array
1123 * Success: pointer to the destination pointer array.
1127 * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
1128 * array will be created and it's handle (pointer) is returned.
1129 * - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
1130 * this implementation just returns NULL.
1134 DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
1136 INT nNewItems, nSize;
1142 TRACE("(%p %p)\n", hdpa, hdpaNew);
1145 /* create a new DPA */
1146 hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1148 hdpaTemp->hHeap = hdpa->hHeap;
1149 hdpaTemp->nGrow = hdpa->nGrow;
1154 if (hdpaTemp->ptrs) {
1155 /* remove old pointer array */
1156 HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
1157 hdpaTemp->ptrs = NULL;
1158 hdpaTemp->nItemCount = 0;
1159 hdpaTemp->nMaxCount = 0;
1162 /* create a new pointer array */
1163 nNewItems = hdpaTemp->nGrow *
1164 ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
1165 nSize = nNewItems * sizeof(LPVOID);
1167 (LPVOID*)HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
1168 hdpaTemp->nMaxCount = nNewItems;
1170 /* clone the pointer array */
1171 hdpaTemp->nItemCount = hdpa->nItemCount;
1172 memmove (hdpaTemp->ptrs, hdpa->ptrs,
1173 hdpaTemp->nItemCount * sizeof(LPVOID));
1179 /**************************************************************************
1180 * DPA_GetPtr [COMCTL32.332]
1182 * Retrieves a pointer from a dynamic pointer array
1185 * hdpa [I] handle (pointer) to the pointer array
1186 * nIndex [I] array index of the desired pointer
1194 DPA_GetPtr (const HDPA hdpa, INT i)
1196 TRACE("(%p %d)\n", hdpa, i);
1202 if ((i < 0) || (i >= hdpa->nItemCount))
1205 TRACE("-- %p\n", hdpa->ptrs[i]);
1207 return hdpa->ptrs[i];
1211 /**************************************************************************
1212 * DPA_GetPtrIndex [COMCTL32.333]
1214 * Retrieves the index of the specified pointer
1217 * hdpa [I] handle (pointer) to the pointer array
1221 * Success: index of the specified pointer
1226 DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
1233 for (i = 0; i < hdpa->nItemCount; i++) {
1234 if (hdpa->ptrs[i] == p)
1242 /**************************************************************************
1243 * DPA_InsertPtr [COMCTL32.334]
1245 * Inserts a pointer into a dynamic pointer array
1248 * hdpa [I] handle (pointer) to the array
1250 * p [I] pointer to insert
1253 * Success: index of the inserted pointer
1258 DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p)
1260 INT nNewItems, nSize, nIndex = 0;
1261 LPVOID *lpTemp, *lpDest;
1263 TRACE("(%p %d %p)\n", hdpa, i, p);
1265 if ((!hdpa) || (i < 0))
1270 (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1271 2 * hdpa->nGrow * sizeof(LPVOID));
1274 hdpa->nMaxCount = hdpa->nGrow * 2;
1278 if (hdpa->nItemCount >= hdpa->nMaxCount) {
1279 TRACE("-- resizing\n");
1280 nNewItems = hdpa->nMaxCount + hdpa->nGrow;
1281 nSize = nNewItems * sizeof(LPVOID);
1283 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1287 hdpa->nMaxCount = nNewItems;
1288 hdpa->ptrs = lpTemp;
1291 if (i >= hdpa->nItemCount) {
1292 nIndex = hdpa->nItemCount;
1293 TRACE("-- appending at %d\n", nIndex);
1296 TRACE("-- inserting at %d\n", i);
1297 lpTemp = hdpa->ptrs + i;
1298 lpDest = lpTemp + 1;
1299 nSize = (hdpa->nItemCount - i) * sizeof(LPVOID);
1300 TRACE("-- move dest=%p src=%p size=%x\n",
1301 lpDest, lpTemp, nSize);
1302 memmove (lpDest, lpTemp, nSize);
1309 hdpa->ptrs[nIndex] = p;
1315 /**************************************************************************
1316 * DPA_SetPtr [COMCTL32.335]
1318 * Sets a pointer in the pointer array
1321 * hdpa [I] handle (pointer) to the pointer array
1322 * i [I] index of the pointer that will be set
1323 * p [I] pointer to be set
1331 DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
1335 TRACE("(%p %d %p)\n", hdpa, i, p);
1337 if ((!hdpa) || i < 0)
1340 if (hdpa->nItemCount <= i) {
1341 /* within the old array */
1342 if (hdpa->nMaxCount > i) {
1343 /* within the allocated space, set a new boundary */
1344 hdpa->nItemCount = i;
1347 /* resize the block of memory */
1349 hdpa->nGrow * ((INT)((i - 1) / hdpa->nGrow) + 1);
1350 INT nSize = nNewItems * sizeof(LPVOID);
1352 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1357 hdpa->nItemCount = nNewItems;
1358 hdpa->ptrs = lpTemp;
1362 /* put the new entry in */
1369 /**************************************************************************
1370 * DPA_DeletePtr [COMCTL32.336]
1372 * Removes a pointer from the pointer array.
1375 * hdpa [I] handle (pointer) to the pointer array
1376 * i [I] index of the pointer that will be deleted
1379 * Success: deleted pointer
1384 DPA_DeletePtr (const HDPA hdpa, INT i)
1386 LPVOID *lpDest, *lpSrc, lpTemp = NULL;
1389 TRACE("(%p %d)\n", hdpa, i);
1391 if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
1394 lpTemp = hdpa->ptrs[i];
1396 /* do we need to move ?*/
1397 if (i < hdpa->nItemCount - 1) {
1398 lpDest = hdpa->ptrs + i;
1400 nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
1401 TRACE("-- move dest=%p src=%p size=%x\n",
1402 lpDest, lpSrc, nSize);
1403 memmove (lpDest, lpSrc, nSize);
1406 hdpa->nItemCount --;
1409 if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
1410 INT nNewItems = MIN(hdpa->nGrow * 2, hdpa->nItemCount);
1411 nSize = nNewItems * sizeof(LPVOID);
1412 lpDest = (LPVOID)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1417 hdpa->nMaxCount = nNewItems;
1418 hdpa->ptrs = (LPVOID*)lpDest;
1425 /**************************************************************************
1426 * DPA_DeleteAllPtrs [COMCTL32.337]
1428 * Removes all pointers and reinitializes the array.
1431 * hdpa [I] handle (pointer) to the pointer array
1439 DPA_DeleteAllPtrs (const HDPA hdpa)
1441 TRACE("(%p)\n", hdpa);
1446 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1449 hdpa->nItemCount = 0;
1450 hdpa->nMaxCount = hdpa->nGrow * 2;
1451 hdpa->ptrs = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1452 hdpa->nMaxCount * sizeof(LPVOID));
1458 /**************************************************************************
1459 * DPA_QuickSort [Internal]
1461 * Ordinary quicksort (used by DPA_Sort).
1464 * lpPtrs [I] pointer to the pointer array
1465 * l [I] index of the "left border" of the partition
1466 * r [I] index of the "right border" of the partition
1467 * pfnCompare [I] pointer to the compare function
1468 * lParam [I] user defined value (3rd parameter in compare function)
1475 DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
1476 PFNDPACOMPARE pfnCompare, LPARAM lParam)
1481 TRACE("l=%i r=%i\n", l, r);
1485 v = lpPtrs[(int)(l+r)/2];
1487 while ((pfnCompare)(lpPtrs[i], v, lParam) > 0) i++;
1488 while ((pfnCompare)(lpPtrs[j], v, lParam) < 0) j--;
1492 lpPtrs[i++] = lpPtrs[j];
1496 if (l < j) DPA_QuickSort (lpPtrs, l, j, pfnCompare, lParam);
1497 if (i < r) DPA_QuickSort (lpPtrs, i, r, pfnCompare, lParam);
1501 /**************************************************************************
1502 * DPA_Sort [COMCTL32.338]
1504 * Sorts a pointer array using a user defined compare function
1507 * hdpa [I] handle (pointer) to the pointer array
1508 * pfnCompare [I] pointer to the compare function
1509 * lParam [I] user defined value (3rd parameter of compare function)
1517 DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
1519 if (!hdpa || !pfnCompare)
1522 TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
1524 if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
1525 DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
1526 pfnCompare, lParam);
1532 /**************************************************************************
1533 * DPA_Search [COMCTL32.339]
1535 * Searches a pointer array for a specified pointer
1538 * hdpa [I] handle (pointer) to the pointer array
1539 * pFind [I] pointer to search for
1540 * nStart [I] start index
1541 * pfnCompare [I] pointer to the compare function
1542 * lParam [I] user defined value (3rd parameter of compare function)
1543 * uOptions [I] search options
1546 * Success: index of the pointer in the array.
1550 * Binary search taken from R.Sedgewick "Algorithms in C"!
1551 * Function is NOT tested!
1552 * If something goes wrong, blame HIM not ME! (Eric Kohl)
1556 DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
1557 PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
1559 if (!hdpa || !pfnCompare || !pFind)
1562 TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n",
1563 hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
1565 if (uOptions & DPAS_SORTED) {
1566 /* array is sorted --> use binary search */
1570 TRACE("binary search\n");
1572 l = (nStart == -1) ? 0 : nStart;
1573 r = hdpa->nItemCount - 1;
1577 n = (pfnCompare)(pFind, lpPtr[x], lParam);
1583 TRACE("-- ret=%d\n", n);
1588 if (uOptions & DPAS_INSERTBEFORE) {
1589 TRACE("-- ret=%d\n", r);
1593 if (uOptions & DPAS_INSERTAFTER) {
1594 TRACE("-- ret=%d\n", l);
1599 /* array is not sorted --> use linear search */
1603 TRACE("linear search\n");
1605 nIndex = (nStart == -1)? 0 : nStart;
1607 for (; nIndex < hdpa->nItemCount; nIndex++) {
1608 if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
1609 TRACE("-- ret=%d\n", nIndex);
1615 TRACE("-- not found: ret=-1\n");
1620 /**************************************************************************
1621 * DPA_CreateEx [COMCTL32.340]
1623 * Creates a dynamic pointer array using the specified size and heap.
1626 * nGrow [I] number of items by which the array grows when it is filled
1627 * hHeap [I] handle to the heap where the array is stored
1630 * Success: handle (pointer) to the pointer array.
1635 DPA_CreateEx (INT nGrow, HANDLE hHeap)
1639 TRACE("(%d 0x%x)\n", nGrow, hHeap);
1642 hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(DPA));
1644 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1647 hdpa->nGrow = MIN(8, nGrow);
1648 hdpa->hHeap = hHeap ? hHeap : COMCTL32_hHeap;
1649 hdpa->nMaxCount = hdpa->nGrow * 2;
1651 (LPVOID*)HeapAlloc (hHeap, HEAP_ZERO_MEMORY,
1652 hdpa->nMaxCount * sizeof(LPVOID));
1655 TRACE("-- %p\n", hdpa);
1661 /**************************************************************************
1662 * Notification functions
1665 typedef struct tagNOTIFYDATA
1673 } NOTIFYDATA, *LPNOTIFYDATA;
1676 /**************************************************************************
1677 * DoNotify [Internal]
1681 DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
1684 LPNMHDR lpNmh = NULL;
1687 TRACE("(0x%04x 0x%04x %d %p 0x%08lx)\n",
1688 lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr,
1689 lpNotify->dwParam5);
1691 if (!lpNotify->hwndTo)
1694 if (lpNotify->hwndFrom == -1) {
1696 idFrom = lpHdr->idFrom;
1699 if (lpNotify->hwndFrom) {
1700 HWND hwndParent = GetParent (lpNotify->hwndFrom);
1702 hwndParent = GetWindow (lpNotify->hwndFrom, GW_OWNER);
1704 idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
1708 lpNmh = (lpHdr) ? lpHdr : &nmhdr;
1710 lpNmh->hwndFrom = lpNotify->hwndFrom;
1711 lpNmh->idFrom = idFrom;
1712 lpNmh->code = uCode;
1715 return SendMessageA (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
1719 /**************************************************************************
1720 * SendNotify [COMCTL32.341]
1729 * Success: return value from notification
1734 COMCTL32_SendNotify (HWND hwndFrom, HWND hwndTo,
1735 UINT uCode, LPNMHDR lpHdr)
1739 TRACE("(0x%04x 0x%04x %d %p)\n",
1740 hwndFrom, hwndTo, uCode, lpHdr);
1742 notify.hwndFrom = hwndFrom;
1743 notify.hwndTo = hwndTo;
1744 notify.dwParam5 = 0;
1745 notify.dwParam6 = 0;
1747 return DoNotify (¬ify, uCode, lpHdr);
1751 /**************************************************************************
1752 * SendNotifyEx [COMCTL32.342]
1762 * Success: return value from notification
1767 COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
1768 LPNMHDR lpHdr, DWORD dwParam5)
1773 TRACE("(0x%04x 0x%04x %d %p 0x%08lx)\n",
1774 hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
1776 hwndNotify = hwndTo;
1778 if (IsWindow (hwndFrom)) {
1779 hwndNotify = GetParent (hwndFrom);
1785 notify.hwndFrom = hwndFrom;
1786 notify.hwndTo = hwndNotify;
1787 notify.dwParam5 = dwParam5;
1788 notify.dwParam6 = 0;
1790 return DoNotify (¬ify, uCode, lpHdr);
1794 /**************************************************************************
1795 * StrChrA [COMCTL32.350]
1800 COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
1802 return strchr (lpString, cChar);
1806 /**************************************************************************
1807 * StrStrIA [COMCTL32.355]
1811 COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
1817 return ((LPSTR)lpStr1);
1819 while (lpStr1[len1] != 0) ++len1;
1821 while (lpStr2[len2] != 0) ++len2;
1823 return ((LPSTR)(lpStr1 + len1));
1824 first = tolower (*lpStr2);
1825 while (len1 >= len2) {
1826 if (tolower(*lpStr1) == first) {
1827 for (i = 1; i < len2; ++i)
1828 if (tolower (lpStr1[i]) != tolower(lpStr2[i]))
1831 return ((LPSTR)lpStr1);
1839 /**************************************************************************
1840 * StrToIntA [COMCTL32.357] Converts a string to a signed integer.
1844 COMCTL32_StrToIntA (LPSTR lpString)
1846 return atoi(lpString);
1850 /**************************************************************************
1851 * DPA_EnumCallback [COMCTL32.385]
1853 * Enumerates all items in a dynamic pointer array.
1856 * hdpa [I] handle to the dynamic pointer array
1865 DPA_EnumCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
1869 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
1873 if (hdpa->nItemCount <= 0)
1876 for (i = 0; i < hdpa->nItemCount; i++) {
1877 if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
1885 /**************************************************************************
1886 * DPA_DestroyCallback [COMCTL32.386]
1888 * Enumerates all items in a dynamic pointer array and destroys it.
1891 * hdpa [I] handle to the dynamic pointer array
1901 DPA_DestroyCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
1903 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
1905 DPA_EnumCallback (hdpa, enumProc, lParam);
1907 return DPA_Destroy (hdpa);
1911 /**************************************************************************
1912 * DSA_EnumCallback [COMCTL32.387]
1914 * Enumerates all items in a dynamic storage array.
1917 * hdsa [I] handle to the dynamic storage array
1926 DSA_EnumCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
1930 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
1934 if (hdsa->nItemCount <= 0)
1937 for (i = 0; i < hdsa->nItemCount; i++) {
1938 LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
1939 if ((enumProc)(lpItem, lParam) == 0)
1947 /**************************************************************************
1948 * DSA_DestroyCallback [COMCTL32.388]
1950 * Enumerates all items in a dynamic storage array and destroys it.
1953 * hdsa [I] handle to the dynamic storage array
1963 DSA_DestroyCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
1965 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
1967 DSA_EnumCallback (hdsa, enumProc, lParam);
1969 return DSA_Destroy (hdsa);
1972 /**************************************************************************
1973 * StrCSpnA [COMCTL32.356]
1976 INT WINAPI COMCTL32_StrCSpnA( LPCSTR lpStr, LPCSTR lpSet) {
1977 return strcspn(lpStr, lpSet);
1980 /**************************************************************************
1981 * StrChrW [COMCTL32.358]
1984 LPWSTR WINAPI COMCTL32_StrChrW( LPCWSTR lpStart, WORD wMatch) {
1985 return CRTDLL_wcschr(lpStart, wMatch);
1988 /**************************************************************************
1989 * StrCmpNA [COMCTL32.352]
1992 INT WINAPI COMCTL32_StrCmpNA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
1993 return lstrncmpA(lpStr1, lpStr2, nChar);
1996 /**************************************************************************
1997 * StrCmpNW [COMCTL32.360]
2000 INT WINAPI COMCTL32_StrCmpNW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
2001 return lstrncmpW(lpStr1, lpStr2, nChar);
2004 /**************************************************************************
2005 * StrRChrA [COMCTL32.351]
2008 LPSTR WINAPI COMCTL32_StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch) {
2009 return lstrrchr(lpStart, lpEnd, wMatch);
2012 /**************************************************************************
2013 * StrRChrW [COMCTL32.359]
2016 LPWSTR WINAPI COMCTL32_StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch) {
2017 return lstrrchrw(lpStart, lpEnd, wMatch);
2020 /**************************************************************************
2021 * StrStrA [COMCTL32.354]
2024 LPSTR WINAPI COMCTL32_StrStrA( LPCSTR lpFirst, LPCSTR lpSrch) {
2025 return strstr(lpFirst, lpSrch);
2028 /**************************************************************************
2029 * StrStrW [COMCTL32.362]
2032 LPWSTR WINAPI COMCTL32_StrStrW( LPCWSTR lpFirst, LPCWSTR lpSrch) {
2033 return strstrw(lpFirst, lpSrch);
2036 /**************************************************************************
2037 * StrSpnW [COMCTL32.364]
2040 INT WINAPI COMCTL32_StrSpnW( LPWSTR lpStr, LPWSTR lpSet) {
2041 LPWSTR lpLoop = lpStr;
2044 if ((lpStr == 0) || (lpSet == 0)) return 0;
2046 /* while(*lpLoop) { if lpLoop++; } */
2048 for(; (*lpLoop != 0); lpLoop++)
2049 if( CRTDLL_wcschr(lpSet, *(WORD*)lpLoop))
2050 return (INT)(lpLoop-lpStr);
2052 return (INT)(lpLoop-lpStr);