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 DEFAULT_DEBUG_CHANNEL(commctrl)
28 extern HANDLE COMCTL32_hHeap; /* handle to the private heap */
31 * We put some function prototypes here that don't seem to belong in
32 * any header file. When they find their place, we can remove them.
34 extern LPWSTR __cdecl CRTDLL_wcschr(LPCWSTR, WCHAR);
35 extern LPSTR WINAPI lstrrchr(LPCSTR, LPCSTR, WORD);
36 extern LPWSTR WINAPI lstrrchrw(LPCWSTR, LPCWSTR, WORD);
37 extern LPWSTR WINAPI strstrw(LPCWSTR, LPCWSTR);
40 /**************************************************************************
41 * DPA_Merge [COMCTL32.11]
44 * hdpa1 [I] handle to a dynamic pointer array
45 * hdpa2 [I] handle to a dynamic pointer array
47 * pfnSort [I] pointer to sort function
49 * lParam [I] application specific value
52 * No more information available yet!
56 DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
57 PFNDPACOMPARE pfnCompare, LPVOID pfnParam5, LPARAM lParam)
59 /* LPVOID *pWork1, *pWork2; */
62 TRACE (commctrl, "(%p %p %08lx %p %p %08lx): stub!\n",
63 hdpa1, hdpa2, dwFlags, pfnCompare, pfnParam5, lParam);
65 if (IsBadWritePtr (hdpa1, sizeof(DPA)))
68 if (IsBadWritePtr (hdpa2, sizeof(DPA)))
71 if (IsBadCodePtr ((FARPROC)pfnCompare))
74 if (IsBadCodePtr ((FARPROC)pfnParam5))
77 if (dwFlags & DPAM_SORT) {
78 TRACE (commctrl, "sorting dpa's!\n");
79 DPA_Sort (hdpa1, pfnCompare, lParam);
80 DPA_Sort (hdpa2, pfnCompare, lParam);
83 if (hdpa2->nItemCount <= 0)
86 nCount1 = hdpa1->nItemCount - 1;
88 nCount2 = hdpa2->nItemCount - 1;
90 FIXME (commctrl, "nCount1=%d nCount2=%d\n", nCount1, nCount2);
91 FIXME (commctrl, "semi stub!\n");
100 else if (nResult > 0) {
108 while (nCount2 >= 0);
117 /**************************************************************************
118 * Alloc [COMCTL32.71]
120 * Allocates memory block from the dll's private heap
123 * dwSize [I] size of the allocated memory block
126 * Success: pointer to allocated memory block
131 COMCTL32_Alloc (DWORD dwSize)
135 TRACE (commctrl, "(0x%lx)\n", dwSize);
137 lpPtr = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
139 TRACE (commctrl, "-- ret=%p\n", lpPtr);
145 /**************************************************************************
146 * ReAlloc [COMCTL32.72]
148 * Changes the size of an allocated memory block or allocates a memory
149 * block using the dll's private heap.
152 * lpSrc [I] pointer to memory block which will be resized
153 * dwSize [I] new size of the memory block.
156 * Success: pointer to the resized memory block
160 * If lpSrc is a NULL-pointer, then COMCTL32_ReAlloc allocates a memory
161 * block like COMCTL32_Alloc.
165 COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
169 TRACE (commctrl, "(%p 0x%08lx)\n", lpSrc, dwSize);
172 lpDest = HeapReAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, lpSrc, dwSize);
174 lpDest = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
176 TRACE (commctrl, "-- ret=%p\n", lpDest);
182 /**************************************************************************
185 * Frees an allocated memory block from the dll's private heap.
188 * lpMem [I] pointer to memory block which will be freed
196 COMCTL32_Free (LPVOID lpMem)
198 TRACE (commctrl, "(%p)\n", lpMem);
200 return HeapFree (COMCTL32_hHeap, 0, lpMem);
204 /**************************************************************************
205 * GetSize [COMCTL32.74]
207 * Retrieves the size of the specified memory block from the dll's
211 * lpMem [I] pointer to an allocated memory block
214 * Success: size of the specified memory block
219 COMCTL32_GetSize (LPVOID lpMem)
221 TRACE (commctrl, "(%p)\n", lpMem);
223 return HeapSize (COMCTL32_hHeap, 0, lpMem);
227 /**************************************************************************
228 * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
234 typedef struct tagMRUINFO
242 } MRUINFO, *LPMRUINFO;
245 typedef struct tagMRU
247 DWORD dwParam1; /* some kind of flag */
256 CreateMRUListLazyA (LPMRUINFO lpmi, DWORD dwParam2,
257 DWORD dwParam3, DWORD dwParam4);
260 /**************************************************************************
261 * CreateMRUListA [COMCTL32.151]
270 CreateMRUListA (LPMRUINFO lpmi)
272 return CreateMRUListLazyA (lpmi, 0, 0, 0);
277 FreeMRUListA (HMRU hmru)
279 FIXME (commctrl, "(%p) empty stub!\n", hmru);
282 if (!(hmru->dwParam1 & 1001)) {
283 RegSetValueExA (hmru->hKeyMRU, "MRUList", 0, REG_SZ,
285 lstrlenA (hmru->lpszMRUString));
289 RegClosKey (hmru->hkeyMRU
290 COMCTL32_Free32 (hmru->lpszMRUString);
293 return COMCTL32_Free (hmru);
299 AddMRUData (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3)
302 FIXME (commctrl, "(%lx %lx %lx) empty stub!\n",
303 dwParam1, dwParam2, dwParam3);
310 FindMRUData (DWORD dwParam1, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
313 FIXME (commctrl, "(%lx %lx %lx %lx) empty stub!\n",
314 dwParam1, dwParam2, dwParam3, dwParam4);
321 CreateMRUListLazyA (LPMRUINFO lpmi, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
330 * DWORD dwDisposition; */
332 /* internal variables */
335 FIXME (commctrl, "(%p) empty stub!\n", lpmi);
338 FIXME (commctrl, "(%lx %lx %lx %lx \"%s\" %lx)\n",
339 lpmi->dwParam1, lpmi->dwParam2, lpmi->dwParam3,
340 (DWORD)lpmi->hkeyMain, lpmi->lpszSubKey, lpmi->dwParam6);
343 /* dummy pointer creation */
344 ptr = COMCTL32_Alloc (32);
346 FIXME (commctrl, "-- ret = %p\n", ptr);
354 /**************************************************************************
355 * Str_GetPtrA [COMCTL32.233]
366 Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
370 TRACE (commctrl, "(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
372 if (!lpDest && lpSrc)
373 return lstrlenA (lpSrc);
383 len = lstrlenA (lpSrc);
387 RtlMoveMemory (lpDest, lpSrc, len);
394 /**************************************************************************
395 * Str_SetPtrA [COMCTL32.234]
405 Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
407 TRACE (commctrl, "(%p %p)\n", lppDest, lpSrc);
410 LPSTR ptr = COMCTL32_ReAlloc (*lppDest, lstrlenA (lpSrc) + 1);
413 lstrcpyA (ptr, lpSrc);
418 COMCTL32_Free (*lppDest);
427 /**************************************************************************
428 * Str_GetPtrW [COMCTL32.235]
439 Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
443 TRACE (commctrl, "(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
445 if (!lpDest && lpSrc)
446 return lstrlenW (lpSrc);
456 len = lstrlenW (lpSrc);
460 RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
467 /**************************************************************************
468 * Str_SetPtrW [COMCTL32.236]
478 Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
480 TRACE (commctrl, "(%p %p)\n", lppDest, lpSrc);
483 INT len = lstrlenW (lpSrc) + 1;
484 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len * sizeof(WCHAR));
487 lstrcpyW (ptr, lpSrc);
492 COMCTL32_Free (*lppDest);
501 /**************************************************************************
502 * The DSA-API is a set of functions to create and manipulate arrays of
503 * fix sized memory blocks. These arrays can store any kind of data
504 * (strings, icons...).
507 /**************************************************************************
508 * DSA_Create [COMCTL32.320] Creates a dynamic storage array
511 * nSize [I] size of the array elements
512 * nGrow [I] number of elements by which the array grows when it is filled
515 * Success: pointer to a array control structure. use this like a handle.
520 DSA_Create (INT nSize, INT nGrow)
524 TRACE (commctrl, "(size=%d grow=%d)\n", nSize, nGrow);
526 hdsa = (HDSA)COMCTL32_Alloc (sizeof(DSA));
529 hdsa->nItemCount = 0;
532 hdsa->nItemSize = nSize;
533 hdsa->nGrow = MAX(1, nGrow);
540 /**************************************************************************
541 * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array
544 * hdsa [I] pointer to the array control structure
552 DSA_Destroy (const HDSA hdsa)
554 TRACE (commctrl, "(%p)\n", hdsa);
559 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
562 return COMCTL32_Free (hdsa);
566 /**************************************************************************
567 * DSA_GetItem [COMCTL32.322]
570 * hdsa [I] pointer to the array control structure
571 * nIndex [I] number of the Item to get
572 * pDest [O] destination buffer. Has to be >= dwElementSize.
580 DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
584 TRACE (commctrl, "(%p %d %p)\n", hdsa, nIndex, pDest);
588 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
591 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
592 memmove (pDest, pSrc, hdsa->nItemSize);
598 /**************************************************************************
599 * DSA_GetItemPtr [COMCTL32.323]
601 * Retrieves a pointer to the specified item.
604 * hdsa [I] pointer to the array control structure
605 * nIndex [I] index of the desired item
608 * Success: pointer to an item
613 DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
617 TRACE (commctrl, "(%p %d)\n", hdsa, nIndex);
621 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
624 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
626 TRACE (commctrl, "-- ret=%p\n", pSrc);
632 /**************************************************************************
633 * DSA_SetItem [COMCTL32.325]
635 * Sets the contents of an item in the array.
638 * hdsa [I] pointer to the array control structure
639 * nIndex [I] index for the item
640 * pSrc [I] pointer to the new item data
648 DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
650 INT nSize, nNewItems;
651 LPVOID pDest, lpTemp;
653 TRACE (commctrl, "(%p %d %p)\n", hdsa, nIndex, pSrc);
655 if ((!hdsa) || nIndex < 0)
658 if (hdsa->nItemCount <= nIndex) {
659 /* within the old array */
660 if (hdsa->nMaxCount > nIndex) {
661 /* within the allocated space, set a new boundary */
662 hdsa->nItemCount = nIndex;
665 /* resize the block of memory */
667 hdsa->nGrow * ((INT)((nIndex - 1) / hdsa->nGrow) + 1);
668 nSize = hdsa->nItemSize * nNewItems;
670 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
674 hdsa->nMaxCount = nNewItems;
675 hdsa->pData = lpTemp;
679 /* put the new entry in */
680 pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
681 TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
682 pDest, pSrc, hdsa->nItemSize);
683 memmove (pDest, pSrc, hdsa->nItemSize);
689 /**************************************************************************
690 * DSA_InsertItem [COMCTL32.325]
693 * hdsa [I] pointer to the array control structure
694 * nIndex [I] index for the new item
695 * pSrc [I] pointer to the element
698 * Success: position of the new item
703 DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
705 INT nNewItems, nSize, i;
706 LPVOID lpTemp, lpDest;
709 TRACE(commctrl, "(%p %d %p)\n", hdsa, nIndex, pSrc);
711 if ((!hdsa) || nIndex < 0)
714 for (i = 0; i < hdsa->nItemSize; i += 4) {
715 p = *(DWORD**)((char *) pSrc + i);
716 if (IsBadStringPtrA ((char*)p, 256))
717 TRACE (commctrl, "-- %d=%p\n", i, (DWORD*)p);
719 TRACE (commctrl, "-- %d=%p [%s]\n", i, p, debugstr_a((char*)p));
722 /* when nIndex > nItemCount then append */
723 if (nIndex >= hdsa->nItemCount)
724 nIndex = hdsa->nItemCount;
726 /* do we need to resize ? */
727 if (hdsa->nItemCount >= hdsa->nMaxCount) {
728 nNewItems = hdsa->nMaxCount + hdsa->nGrow;
729 nSize = hdsa->nItemSize * nNewItems;
731 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
735 hdsa->nMaxCount = nNewItems;
736 hdsa->pData = lpTemp;
739 /* do we need to move elements ? */
740 if (nIndex < hdsa->nItemCount) {
741 lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
742 lpDest = (char *) lpTemp + hdsa->nItemSize;
743 nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
744 TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
745 lpDest, lpTemp, nSize);
746 memmove (lpDest, lpTemp, nSize);
749 /* ok, we can put the new Item in */
751 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
752 TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
753 lpDest, pSrc, hdsa->nItemSize);
754 memmove (lpDest, pSrc, hdsa->nItemSize);
756 return hdsa->nItemCount;
760 /**************************************************************************
761 * DSA_DeleteItem [COMCTL32.326]
764 * hdsa [I] pointer to the array control structure
765 * nIndex [I] index for the element to delete
768 * Success: number of the deleted element
773 DSA_DeleteItem (const HDSA hdsa, INT nIndex)
778 TRACE (commctrl, "(%p %d)\n", hdsa, nIndex);
782 if (nIndex < 0 || nIndex >= hdsa->nItemCount)
785 /* do we need to move ? */
786 if (nIndex < hdsa->nItemCount - 1) {
787 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
788 lpSrc = (char *) lpDest + hdsa->nItemSize;
789 nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
790 TRACE (commctrl, "-- move dest=%p src=%p size=%d\n",
791 lpDest, lpSrc, nSize);
792 memmove (lpDest, lpSrc, nSize);
798 if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
799 nSize = hdsa->nItemSize * hdsa->nItemCount;
801 lpDest = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
805 hdsa->nMaxCount = hdsa->nItemCount;
806 hdsa->pData = lpDest;
813 /**************************************************************************
814 * DSA_DeleteAllItems [COMCTL32.326]
816 * Removes all items and reinitializes the array.
819 * hdsa [I] pointer to the array control structure
827 DSA_DeleteAllItems (const HDSA hdsa)
829 TRACE (commctrl, "(%p)\n", hdsa);
833 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
836 hdsa->nItemCount = 0;
844 /**************************************************************************
845 * The DPA-API is a set of functions to create and manipulate arrays of
849 /**************************************************************************
850 * DPA_Create [COMCTL32.328] Creates a dynamic pointer array
853 * nGrow [I] number of items by which the array grows when it is filled
856 * Success: handle (pointer) to the pointer array.
861 DPA_Create (INT nGrow)
865 TRACE (commctrl, "(%d)\n", nGrow);
867 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
869 hdpa->nGrow = MAX(8, nGrow);
870 hdpa->hHeap = COMCTL32_hHeap;
871 hdpa->nMaxCount = hdpa->nGrow * 2;
873 (LPVOID*)COMCTL32_Alloc (hdpa->nMaxCount * sizeof(LPVOID));
876 TRACE (commctrl, "-- %p\n", hdpa);
882 /**************************************************************************
883 * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array
886 * hdpa [I] handle (pointer) to the pointer array
894 DPA_Destroy (const HDPA hdpa)
896 TRACE (commctrl, "(%p)\n", hdpa);
901 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
904 return HeapFree (hdpa->hHeap, 0, hdpa);
908 /**************************************************************************
909 * DPA_Grow [COMCTL32.330]
911 * Sets the growth amount.
914 * hdpa [I] handle (pointer) to the existing (source) pointer array
915 * nGrow [I] number of items, the array grows, when it's too small
923 DPA_Grow (const HDPA hdpa, INT nGrow)
925 TRACE (commctrl, "(%p %d)\n", hdpa, nGrow);
930 hdpa->nGrow = MAX(8, nGrow);
936 /**************************************************************************
937 * DPA_Clone [COMCTL32.331]
939 * Copies a pointer array to an other one or creates a copy
942 * hdpa [I] handle (pointer) to the existing (source) pointer array
943 * hdpaNew [O] handle (pointer) to the destination pointer array
946 * Success: pointer to the destination pointer array.
950 * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
951 * array will be created and it's handle (pointer) is returned.
952 * - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
953 * this implementation just returns NULL.
957 DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
959 INT nNewItems, nSize;
965 TRACE (commctrl, "(%p %p)\n", hdpa, hdpaNew);
968 /* create a new DPA */
969 hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
971 hdpaTemp->hHeap = hdpa->hHeap;
972 hdpaTemp->nGrow = hdpa->nGrow;
977 if (hdpaTemp->ptrs) {
978 /* remove old pointer array */
979 HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
980 hdpaTemp->ptrs = NULL;
981 hdpaTemp->nItemCount = 0;
982 hdpaTemp->nMaxCount = 0;
985 /* create a new pointer array */
986 nNewItems = hdpaTemp->nGrow *
987 ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
988 nSize = nNewItems * sizeof(LPVOID);
990 (LPVOID*)HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
991 hdpaTemp->nMaxCount = nNewItems;
993 /* clone the pointer array */
994 hdpaTemp->nItemCount = hdpa->nItemCount;
995 memmove (hdpaTemp->ptrs, hdpa->ptrs,
996 hdpaTemp->nItemCount * sizeof(LPVOID));
1002 /**************************************************************************
1003 * DPA_GetPtr [COMCTL32.332]
1005 * Retrieves a pointer from a dynamic pointer array
1008 * hdpa [I] handle (pointer) to the pointer array
1009 * nIndex [I] array index of the desired pointer
1017 DPA_GetPtr (const HDPA hdpa, INT i)
1019 TRACE (commctrl, "(%p %d)\n", hdpa, i);
1025 if ((i < 0) || (i >= hdpa->nItemCount))
1028 TRACE (commctrl, "-- %p\n", hdpa->ptrs[i]);
1030 return hdpa->ptrs[i];
1034 /**************************************************************************
1035 * DPA_GetPtrIndex [COMCTL32.333]
1037 * Retrieves the index of the specified pointer
1040 * hdpa [I] handle (pointer) to the pointer array
1044 * Success: index of the specified pointer
1049 DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
1056 for (i = 0; i < hdpa->nItemCount; i++) {
1057 if (hdpa->ptrs[i] == p)
1065 /**************************************************************************
1066 * DPA_InsertPtr [COMCTL32.334]
1068 * Inserts a pointer into a dynamic pointer array
1071 * hdpa [I] handle (pointer) to the array
1073 * p [I] pointer to insert
1076 * Success: index of the inserted pointer
1081 DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p)
1083 INT nNewItems, nSize, nIndex = 0;
1084 LPVOID *lpTemp, *lpDest;
1086 TRACE (commctrl, "(%p %d %p)\n", hdpa, i, p);
1088 if ((!hdpa) || (i < 0))
1093 (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1094 2 * hdpa->nGrow * sizeof(LPVOID));
1097 hdpa->nMaxCount = hdpa->nGrow * 2;
1101 if (hdpa->nItemCount >= hdpa->nMaxCount) {
1102 TRACE (commctrl, "-- resizing\n");
1103 nNewItems = hdpa->nMaxCount + hdpa->nGrow;
1104 nSize = nNewItems * sizeof(LPVOID);
1106 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1110 hdpa->nMaxCount = nNewItems;
1111 hdpa->ptrs = lpTemp;
1114 if (i >= hdpa->nItemCount) {
1115 nIndex = hdpa->nItemCount;
1116 TRACE (commctrl, "-- appending at %d\n", nIndex);
1119 TRACE (commctrl, "-- inserting at %d\n", i);
1120 lpTemp = hdpa->ptrs + i;
1121 lpDest = lpTemp + 1;
1122 nSize = (hdpa->nItemCount - i) * sizeof(LPVOID);
1123 TRACE (commctrl, "-- move dest=%p src=%p size=%x\n",
1124 lpDest, lpTemp, nSize);
1125 memmove (lpDest, lpTemp, nSize);
1132 hdpa->ptrs[nIndex] = p;
1138 /**************************************************************************
1139 * DPA_SetPtr [COMCTL32.335]
1141 * Sets a pointer in the pointer array
1144 * hdpa [I] handle (pointer) to the pointer array
1145 * i [I] index of the pointer that will be set
1146 * p [I] pointer to be set
1154 DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
1158 TRACE (commctrl, "(%p %d %p)\n", hdpa, i, p);
1160 if ((!hdpa) || i < 0)
1163 if (hdpa->nItemCount <= i) {
1164 /* within the old array */
1165 if (hdpa->nMaxCount > i) {
1166 /* within the allocated space, set a new boundary */
1167 hdpa->nItemCount = i;
1170 /* resize the block of memory */
1172 hdpa->nGrow * ((INT)((i - 1) / hdpa->nGrow) + 1);
1173 INT nSize = nNewItems * sizeof(LPVOID);
1175 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1180 hdpa->nItemCount = nNewItems;
1181 hdpa->ptrs = lpTemp;
1185 /* put the new entry in */
1192 /**************************************************************************
1193 * DPA_DeletePtr [COMCTL32.336]
1195 * Removes a pointer from the pointer array.
1198 * hdpa [I] handle (pointer) to the pointer array
1199 * i [I] index of the pointer that will be deleted
1202 * Success: deleted pointer
1207 DPA_DeletePtr (const HDPA hdpa, INT i)
1209 LPVOID *lpDest, *lpSrc, lpTemp = NULL;
1212 TRACE (commctrl, "(%p %d)\n", hdpa, i);
1214 if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
1217 lpTemp = hdpa->ptrs[i];
1219 /* do we need to move ?*/
1220 if (i < hdpa->nItemCount - 1) {
1221 lpDest = hdpa->ptrs + i;
1223 nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
1224 TRACE (commctrl,"-- move dest=%p src=%p size=%x\n",
1225 lpDest, lpSrc, nSize);
1226 memmove (lpDest, lpSrc, nSize);
1229 hdpa->nItemCount --;
1232 if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
1233 INT nNewItems = MIN(hdpa->nGrow * 2, hdpa->nItemCount);
1234 nSize = nNewItems * sizeof(LPVOID);
1235 lpDest = (LPVOID)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1240 hdpa->nMaxCount = nNewItems;
1241 hdpa->ptrs = (LPVOID*)lpDest;
1248 /**************************************************************************
1249 * DPA_DeleteAllPtrs [COMCTL32.337]
1251 * Removes all pointers and reinitializes the array.
1254 * hdpa [I] handle (pointer) to the pointer array
1262 DPA_DeleteAllPtrs (const HDPA hdpa)
1264 TRACE (commctrl, "(%p)\n", hdpa);
1269 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1272 hdpa->nItemCount = 0;
1273 hdpa->nMaxCount = hdpa->nGrow * 2;
1274 hdpa->ptrs = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1275 hdpa->nMaxCount * sizeof(LPVOID));
1281 /**************************************************************************
1282 * DPA_QuickSort [Internal]
1284 * Ordinary quicksort (used by DPA_Sort).
1287 * lpPtrs [I] pointer to the pointer array
1288 * l [I] index of the "left border" of the partition
1289 * r [I] index of the "right border" of the partition
1290 * pfnCompare [I] pointer to the compare function
1291 * lParam [I] user defined value (3rd parameter in compare function)
1298 DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
1299 PFNDPACOMPARE pfnCompare, LPARAM lParam)
1304 TRACE (commctrl, "l=%i r=%i\n", l, r);
1308 v = lpPtrs[(int)(l+r)/2];
1310 while ((pfnCompare)(lpPtrs[i], v, lParam) > 0) i++;
1311 while ((pfnCompare)(lpPtrs[j], v, lParam) < 0) j--;
1315 lpPtrs[i++] = lpPtrs[j];
1319 if (l < j) DPA_QuickSort (lpPtrs, l, j, pfnCompare, lParam);
1320 if (i < r) DPA_QuickSort (lpPtrs, i, r, pfnCompare, lParam);
1324 /**************************************************************************
1325 * DPA_Sort [COMCTL32.338]
1327 * Sorts a pointer array using a user defined compare function
1330 * hdpa [I] handle (pointer) to the pointer array
1331 * pfnCompare [I] pointer to the compare function
1332 * lParam [I] user defined value (3rd parameter of compare function)
1340 DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
1342 if (!hdpa || !pfnCompare)
1345 TRACE (commctrl, "(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
1347 if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
1348 DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
1349 pfnCompare, lParam);
1355 /**************************************************************************
1356 * DPA_Search [COMCTL32.339]
1358 * Searches a pointer array for a specified pointer
1361 * hdpa [I] handle (pointer) to the pointer array
1362 * pFind [I] pointer to search for
1363 * nStart [I] start index
1364 * pfnCompare [I] pointer to the compare function
1365 * lParam [I] user defined value (3rd parameter of compare function)
1366 * uOptions [I] search options
1369 * Success: index of the pointer in the array.
1373 * Binary search taken from R.Sedgewick "Algorithms in C"!
1374 * Function is NOT tested!
1375 * If something goes wrong, blame HIM not ME! (Eric Kohl)
1379 DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
1380 PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
1382 if (!hdpa || !pfnCompare || !pFind)
1385 TRACE (commctrl, "(%p %p %d %p 0x%08lx 0x%08x)\n",
1386 hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
1388 if (uOptions & DPAS_SORTED) {
1389 /* array is sorted --> use binary search */
1393 TRACE (commctrl, "binary search\n");
1395 l = (nStart == -1) ? 0 : nStart;
1396 r = hdpa->nItemCount - 1;
1400 n = (pfnCompare)(pFind, lpPtr[x], lParam);
1406 TRACE (commctrl, "-- ret=%d\n", n);
1411 if (uOptions & DPAS_INSERTBEFORE) {
1412 TRACE (commctrl, "-- ret=%d\n", r);
1416 if (uOptions & DPAS_INSERTAFTER) {
1417 TRACE (commctrl, "-- ret=%d\n", l);
1422 /* array is not sorted --> use linear search */
1426 TRACE (commctrl, "linear search\n");
1428 nIndex = (nStart == -1)? 0 : nStart;
1430 for (; nIndex < hdpa->nItemCount; nIndex++) {
1431 if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
1432 TRACE (commctrl, "-- ret=%d\n", nIndex);
1438 TRACE (commctrl, "-- not found: ret=-1\n");
1443 /**************************************************************************
1444 * DPA_CreateEx [COMCTL32.340]
1446 * Creates a dynamic pointer array using the specified size and heap.
1449 * nGrow [I] number of items by which the array grows when it is filled
1450 * hHeap [I] handle to the heap where the array is stored
1453 * Success: handle (pointer) to the pointer array.
1458 DPA_CreateEx (INT nGrow, HANDLE hHeap)
1462 TRACE (commctrl, "(%d 0x%x)\n", nGrow, hHeap);
1465 hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(DPA));
1467 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1470 hdpa->nGrow = MIN(8, nGrow);
1471 hdpa->hHeap = hHeap ? hHeap : COMCTL32_hHeap;
1472 hdpa->nMaxCount = hdpa->nGrow * 2;
1474 (LPVOID*)HeapAlloc (hHeap, HEAP_ZERO_MEMORY,
1475 hdpa->nMaxCount * sizeof(LPVOID));
1478 TRACE (commctrl, "-- %p\n", hdpa);
1484 /**************************************************************************
1485 * Notification functions
1488 typedef struct tagNOTIFYDATA
1496 } NOTIFYDATA, *LPNOTIFYDATA;
1499 /**************************************************************************
1500 * DoNotify [Internal]
1504 DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
1507 LPNMHDR lpNmh = NULL;
1510 TRACE (commctrl, "(0x%04x 0x%04x %d %p 0x%08lx)\n",
1511 lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr,
1512 lpNotify->dwParam5);
1514 if (!lpNotify->hwndTo)
1517 if (lpNotify->hwndFrom == -1) {
1519 idFrom = lpHdr->idFrom;
1522 if (lpNotify->hwndFrom) {
1523 HWND hwndParent = GetParent (lpNotify->hwndFrom);
1525 hwndParent = GetWindow (lpNotify->hwndFrom, GW_OWNER);
1527 idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
1531 lpNmh = (lpHdr) ? lpHdr : &nmhdr;
1533 lpNmh->hwndFrom = lpNotify->hwndFrom;
1534 lpNmh->idFrom = idFrom;
1535 lpNmh->code = uCode;
1538 return SendMessageA (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
1542 /**************************************************************************
1543 * SendNotify [COMCTL32.341]
1552 * Success: return value from notification
1557 COMCTL32_SendNotify (HWND hwndFrom, HWND hwndTo,
1558 UINT uCode, LPNMHDR lpHdr)
1562 TRACE (commctrl, "(0x%04x 0x%04x %d %p)\n",
1563 hwndFrom, hwndTo, uCode, lpHdr);
1565 notify.hwndFrom = hwndFrom;
1566 notify.hwndTo = hwndTo;
1567 notify.dwParam5 = 0;
1568 notify.dwParam6 = 0;
1570 return DoNotify (¬ify, uCode, lpHdr);
1574 /**************************************************************************
1575 * SendNotifyEx [COMCTL32.342]
1585 * Success: return value from notification
1590 COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
1591 LPNMHDR lpHdr, DWORD dwParam5)
1596 TRACE (commctrl, "(0x%04x 0x%04x %d %p 0x%08lx)\n",
1597 hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
1599 hwndNotify = hwndTo;
1601 if (IsWindow (hwndFrom)) {
1602 hwndNotify = GetParent (hwndFrom);
1608 notify.hwndFrom = hwndFrom;
1609 notify.hwndTo = hwndNotify;
1610 notify.dwParam5 = dwParam5;
1611 notify.dwParam6 = 0;
1613 return DoNotify (¬ify, uCode, lpHdr);
1617 /**************************************************************************
1618 * StrChrA [COMCTL32.350]
1623 COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
1625 return strchr (lpString, cChar);
1629 /**************************************************************************
1630 * StrStrIA [COMCTL32.355]
1634 COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
1640 return ((LPSTR)lpStr1);
1642 while (lpStr1[len1] != 0) ++len1;
1644 while (lpStr2[len2] != 0) ++len2;
1646 return ((LPSTR)(lpStr1 + len1));
1647 first = tolower (*lpStr2);
1648 while (len1 >= len2) {
1649 if (tolower(*lpStr1) == first) {
1650 for (i = 1; i < len2; ++i)
1651 if (tolower (lpStr1[i]) != tolower(lpStr2[i]))
1654 return ((LPSTR)lpStr1);
1662 /**************************************************************************
1663 * StrToIntA [COMCTL32.357] Converts a string to a signed integer.
1667 COMCTL32_StrToIntA (LPSTR lpString)
1669 return atoi(lpString);
1673 /**************************************************************************
1674 * DPA_EnumCallback [COMCTL32.385]
1676 * Enumerates all items in a dynamic pointer array.
1679 * hdpa [I] handle to the dynamic pointer array
1688 DPA_EnumCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
1692 TRACE (commctrl, "(%p %p %08lx)\n", hdpa, enumProc, lParam);
1696 if (hdpa->nItemCount <= 0)
1699 for (i = 0; i < hdpa->nItemCount; i++) {
1700 if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
1708 /**************************************************************************
1709 * DPA_DestroyCallback [COMCTL32.386]
1711 * Enumerates all items in a dynamic pointer array and destroys it.
1714 * hdpa [I] handle to the dynamic pointer array
1724 DPA_DestroyCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
1726 TRACE (commctrl, "(%p %p %08lx)\n", hdpa, enumProc, lParam);
1728 DPA_EnumCallback (hdpa, enumProc, lParam);
1730 return DPA_Destroy (hdpa);
1734 /**************************************************************************
1735 * DSA_EnumCallback [COMCTL32.387]
1737 * Enumerates all items in a dynamic storage array.
1740 * hdsa [I] handle to the dynamic storage array
1749 DSA_EnumCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
1753 TRACE (commctrl, "(%p %p %08lx)\n", hdsa, enumProc, lParam);
1757 if (hdsa->nItemCount <= 0)
1760 for (i = 0; i < hdsa->nItemCount; i++) {
1761 LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
1762 if ((enumProc)(lpItem, lParam) == 0)
1770 /**************************************************************************
1771 * DSA_DestroyCallback [COMCTL32.388]
1773 * Enumerates all items in a dynamic storage array and destroys it.
1776 * hdsa [I] handle to the dynamic storage array
1786 DSA_DestroyCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
1788 TRACE (commctrl, "(%p %p %08lx)\n", hdsa, enumProc, lParam);
1790 DSA_EnumCallback (hdsa, enumProc, lParam);
1792 return DSA_Destroy (hdsa);
1795 /**************************************************************************
1796 * StrCSpnA [COMCTL32.356]
1799 INT WINAPI COMCTL32_StrCSpnA( LPCSTR lpStr, LPCSTR lpSet) {
1800 return strcspn(lpStr, lpSet);
1803 /**************************************************************************
1804 * StrChrW [COMCTL32.358]
1807 LPWSTR WINAPI COMCTL32_StrChrW( LPCWSTR lpStart, WORD wMatch) {
1808 return CRTDLL_wcschr(lpStart, wMatch);
1811 /**************************************************************************
1812 * StrCmpNA [COMCTL32.352]
1815 INT WINAPI COMCTL32_StrCmpNA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
1816 return lstrncmpA(lpStr1, lpStr2, nChar);
1819 /**************************************************************************
1820 * StrCmpNW [COMCTL32.360]
1823 INT WINAPI COMCTL32_StrCmpNW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
1824 return lstrncmpW(lpStr1, lpStr2, nChar);
1827 /**************************************************************************
1828 * StrRChrA [COMCTL32.351]
1831 LPSTR WINAPI COMCTL32_StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch) {
1832 return lstrrchr(lpStart, lpEnd, wMatch);
1835 /**************************************************************************
1836 * StrRChrW [COMCTL32.359]
1839 LPWSTR WINAPI COMCTL32_StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch) {
1840 return lstrrchrw(lpStart, lpEnd, wMatch);
1843 /**************************************************************************
1844 * StrStrA [COMCTL32.354]
1847 LPSTR WINAPI COMCTL32_StrStrA( LPCSTR lpFirst, LPCSTR lpSrch) {
1848 return strstr(lpFirst, lpSrch);
1851 /**************************************************************************
1852 * StrStrW [COMCTL32.362]
1855 LPWSTR WINAPI COMCTL32_StrStrW( LPCWSTR lpFirst, LPCWSTR lpSrch) {
1856 return strstrw(lpFirst, lpSrch);
1859 /**************************************************************************
1860 * StrSpnW [COMCTL32.364]
1863 INT WINAPI COMCTL32_StrSpnW( LPWSTR lpStr, LPWSTR lpSet) {
1864 LPWSTR lpLoop = lpStr;
1867 if ((lpStr == 0) || (lpSet == 0)) return 0;
1869 /* while(*lpLoop) { if lpLoop++; } */
1871 for(; (*lpLoop != 0); lpLoop++)
1872 if( CRTDLL_wcschr(lpSet, *(WORD*)lpLoop))
1873 return (INT)(lpLoop-lpStr);
1875 return (INT)(lpLoop-lpStr);