2 * Undocumented functions from COMCTL32.DLL
4 * Copyright 1998 Eric Kohl
5 * 1998 Juergen Schmied <j.schmied@metronet.de>
6 * 2000 Eric Kohl for CodeWeavers
9 * All of these functions are UNDOCUMENTED!! And I mean UNDOCUMENTED!!!!
10 * Do NOT rely on names or contents of undocumented structures and types!!!
11 * These functions are used by EXPLORER.EXE, IEXPLORE.EXE and
12 * COMCTL32.DLL (internally).
15 * - Add more functions.
16 * - Write some documentation.
20 #include <stdlib.h> /* atoi */
25 #include "wine/unicode.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(commctrl);
33 extern HANDLE COMCTL32_hHeap; /* handle to the private heap */
36 typedef struct _STREAMDATA
41 } STREAMDATA, *PSTREAMDATA;
43 typedef struct _LOADDATA
47 } LOADDATA, *LPLOADDATA;
49 typedef HRESULT CALLBACK (*DPALOADPROC)(LPLOADDATA,IStream*,LPARAM);
51 INT __cdecl _wtoi(LPWSTR string);
53 /**************************************************************************
54 * DPA_LoadStream [COMCTL32.9]
56 * Loads a dynamic pointer array from a stream
59 * phDpa [O] pointer to a handle to a dynamic pointer array
60 * loadProc [I] pointer to a callback function
61 * pStream [I] pointer to a stream
62 * lParam [I] application specific value
65 * No more information available yet!
69 DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
72 LARGE_INTEGER position;
73 ULARGE_INTEGER newPosition;
74 STREAMDATA streamData;
80 FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
81 phDpa, loadProc, pStream, lParam);
83 if (!phDpa || !loadProc || !pStream)
88 position.s.LowPart = 0;
89 position.s.HighPart = 0;
91 errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition);
95 errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead);
99 FIXME ("dwSize=%lu dwData2=%lu dwItems=%lu\n",
100 streamData.dwSize, streamData.dwData2, streamData.dwItems);
102 if (lParam < sizeof(STREAMDATA) ||
103 streamData.dwSize < sizeof(STREAMDATA) ||
104 streamData.dwData2 < 1) {
109 hDpa = DPA_Create (streamData.dwItems);
111 return E_OUTOFMEMORY;
113 if (!DPA_Grow (hDpa, streamData.dwItems))
114 return E_OUTOFMEMORY;
116 /* load data from the stream into the dpa */
118 for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) {
119 errCode = (loadProc)(&loadData, pStream, lParam);
120 if (errCode != S_OK) {
129 /* set the number of items */
130 hDpa->nItemCount = loadData.nCount;
132 /* store the handle to the dpa */
134 FIXME ("new hDpa=%p\n", hDpa);
140 /**************************************************************************
141 * DPA_SaveStream [COMCTL32.10]
143 * Saves a dynamic pointer array to a stream
146 * hDpa [I] handle to a dynamic pointer array
147 * loadProc [I] pointer to a callback function
148 * pStream [I] pointer to a stream
149 * lParam [I] application specific value
152 * No more information available yet!
156 DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
159 FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
160 hDpa, loadProc, pStream, lParam);
166 /**************************************************************************
167 * DPA_Merge [COMCTL32.11]
170 * hdpa1 [I] handle to a dynamic pointer array
171 * hdpa2 [I] handle to a dynamic pointer array
173 * pfnCompare [I] pointer to sort function
174 * pfnMerge [I] pointer to merge function
175 * lParam [I] application specific value
178 * No more information available yet!
182 DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
183 PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam)
186 LPVOID *pWork1, *pWork2;
190 TRACE("%p %p %08lx %p %p %08lx)\n",
191 hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam);
193 if (IsBadWritePtr (hdpa1, sizeof(DPA)))
196 if (IsBadWritePtr (hdpa2, sizeof(DPA)))
199 if (IsBadCodePtr ((FARPROC)pfnCompare))
202 if (IsBadCodePtr ((FARPROC)pfnMerge))
205 if (dwFlags & DPAM_SORT) {
206 TRACE("sorting dpa's!\n");
207 if (hdpa1->nItemCount > 0)
208 DPA_Sort (hdpa1, pfnCompare, lParam);
209 TRACE ("dpa 1 sorted!\n");
210 if (hdpa2->nItemCount > 0)
211 DPA_Sort (hdpa2, pfnCompare, lParam);
212 TRACE ("dpa 2 sorted!\n");
215 if (hdpa2->nItemCount < 1)
218 TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n",
219 hdpa1->nItemCount, hdpa2->nItemCount);
222 /* working but untrusted implementation */
224 pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]);
225 pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]);
227 nIndex = hdpa1->nItemCount - 1;
228 nCount = hdpa2->nItemCount - 1;
232 if (nIndex < 0) break;
233 nResult = (pfnCompare)(*pWork1, *pWork2, lParam);
234 TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n",
235 nResult, nIndex, nCount);
241 ptr = (pfnMerge)(1, *pWork1, *pWork2, lParam);
251 else if (nResult < 0)
257 ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1);
259 (pfnMerge)(2, ptr, NULL, lParam);
270 ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
273 DPA_InsertPtr (hdpa1, nIndex, ptr);
286 /**************************************************************************
287 * Alloc [COMCTL32.71]
289 * Allocates memory block from the dll's private heap
292 * dwSize [I] size of the allocated memory block
295 * Success: pointer to allocated memory block
300 COMCTL32_Alloc (DWORD dwSize)
304 TRACE("(0x%lx)\n", dwSize);
306 lpPtr = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
308 TRACE("-- ret=%p\n", lpPtr);
314 /**************************************************************************
315 * ReAlloc [COMCTL32.72]
317 * Changes the size of an allocated memory block or allocates a memory
318 * block using the dll's private heap.
321 * lpSrc [I] pointer to memory block which will be resized
322 * dwSize [I] new size of the memory block.
325 * Success: pointer to the resized memory block
329 * If lpSrc is a NULL-pointer, then COMCTL32_ReAlloc allocates a memory
330 * block like COMCTL32_Alloc.
334 COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
338 TRACE("(%p 0x%08lx)\n", lpSrc, dwSize);
341 lpDest = HeapReAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, lpSrc, dwSize);
343 lpDest = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
345 TRACE("-- ret=%p\n", lpDest);
351 /**************************************************************************
354 * Frees an allocated memory block from the dll's private heap.
357 * lpMem [I] pointer to memory block which will be freed
365 COMCTL32_Free (LPVOID lpMem)
367 TRACE("(%p)\n", lpMem);
369 return HeapFree (COMCTL32_hHeap, 0, lpMem);
373 /**************************************************************************
374 * GetSize [COMCTL32.74]
376 * Retrieves the size of the specified memory block from the dll's
380 * lpMem [I] pointer to an allocated memory block
383 * Success: size of the specified memory block
388 COMCTL32_GetSize (LPVOID lpMem)
390 TRACE("(%p)\n", lpMem);
392 return HeapSize (COMCTL32_hHeap, 0, lpMem);
396 /**************************************************************************
397 * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
400 * Stored in the reg. as a set of values under a single key. Each item in the
401 * list has a value name that is a single char. 'a' - 'z', '{', '|' or '}'.
402 * The order of the list is stored with value name 'MRUList' which is a string
403 * containing the value names (i.e. 'a', 'b', etc.) in the relevant order.
406 typedef struct tagCREATEMRULIST
408 DWORD cbSize; /* size of struct */
409 DWORD nMaxItems; /* max no. of items in list */
410 DWORD dwFlags; /* see below */
411 HKEY hKey; /* root reg. key under which list is saved */
412 LPCSTR lpszSubKey; /* reg. subkey */
413 PROC lpfnCompare; /* item compare proc */
414 } CREATEMRULIST, *LPCREATEMRULIST;
417 #define MRUF_STRING_LIST 0 /* list will contain strings */
418 #define MRUF_BINARY_LIST 1 /* list will contain binary data */
419 #define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */
421 /* If list is a string list lpfnCompare has the following prototype
422 * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
423 * for binary lists the prototype is
424 * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
425 * where cbData is the no. of bytes to compare.
426 * Need to check what return value means identical - 0?
429 typedef struct tagMRU
431 DWORD dwParam1; /* some kind of flag */
440 CreateMRUListLazyA (LPCREATEMRULIST lpcml, DWORD dwParam2,
441 DWORD dwParam3, DWORD dwParam4);
444 /**************************************************************************
445 * CreateMRUListA [COMCTL32.151]
448 * lpcml [I] ptr to CREATEMRULIST structure.
451 * Handle to MRU list.
454 CreateMRUListA (LPCREATEMRULIST lpcml)
456 return CreateMRUListLazyA (lpcml, 0, 0, 0);
459 /**************************************************************************
460 * FreeMRUListA [COMCTL32.152]
463 * hMRUList [I] Handle to list.
467 FreeMRUListA (HANDLE hMRUList)
469 FIXME("(%08x) empty stub!\n", hMRUList);
472 if (!(hmru->dwParam1 & 1001)) {
473 RegSetValueExA (hmru->hKeyMRU, "MRUList", 0, REG_SZ,
475 strlen (hmru->lpszMRUString));
479 RegClosKey (hmru->hkeyMRU
480 COMCTL32_Free32 (hmru->lpszMRUString);
483 return COMCTL32_Free ((LPVOID)hMRUList);
487 /**************************************************************************
488 * AddMRUData [COMCTL32.167]
490 * Add item to MRU binary list. If item already exists in list them it is
491 * simply moved up to the top of the list and not added again. If list is
492 * full then the least recently used item is removed to make room.
495 * hList [I] Handle to list.
496 * lpData [I] ptr to data to add.
497 * cbData [I] no. of bytes of data.
500 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
504 AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
506 FIXME("(%08x, %p, %ld) empty stub!\n", hList, lpData, cbData);
511 /**************************************************************************
512 * AddMRUStringA [COMCTL32.153]
514 * Add item to MRU string list. If item already exists in list them it is
515 * simply moved up to the top of the list and not added again. If list is
516 * full then the least recently used item is removed to make room.
519 * hList [I] Handle to list.
520 * lpszString [I] ptr to string to add.
523 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
527 AddMRUStringA(HANDLE hList, LPCSTR lpszString)
529 FIXME("(%08x, %s) empty stub!\n", hList, debugstr_a(lpszString));
534 /**************************************************************************
535 * DelMRUString [COMCTL32.156]
537 * Removes item from either string or binary list (despite its name)
540 * hList [I] list handle
541 * nItemPos [I] item position to remove 0 -> MRU
544 * TRUE is successful, FALSE if nItemPos is out of range.
547 DelMRUString(HANDLE hList, INT nItemPos)
549 FIXME("(%08x, %d): stub\n", hList, nItemPos);
553 /**************************************************************************
554 * FindMRUData [COMCTL32.169]
556 * Searches binary list for item that matches lpData of length cbData.
557 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
558 * corresponding to item's reg. name will be stored in it ('a' -> 0).
561 * hList [I] list handle
562 * lpData [I] data to find
563 * cbData [I] length of data
564 * lpRegNum [O] position in registry (maybe NULL)
567 * Position in list 0 -> MRU. -1 if item not found.
570 FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
572 FIXME("(%08x, %p, %ld, %p) empty stub!\n",
573 hList, lpData, cbData, lpRegNum);
578 /**************************************************************************
579 * FindMRUStringA [COMCTL32.155]
581 * Searches string list for item that matches lpszString.
582 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
583 * corresponding to item's reg. name will be stored in it ('a' -> 0).
586 * hList [I] list handle
587 * lpszString [I] string to find
588 * lpRegNum [O] position in registry (maybe NULL)
591 * Position in list 0 -> MRU. -1 if item not found.
594 FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
596 FIXME("(%08x, %s, %p) empty stub!\n", hList, debugstr_a(lpszString),
602 /**************************************************************************
603 * CreateMRUListLazyA [COMCTL32.157]
606 CreateMRUListLazyA (LPCREATEMRULIST lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
615 * DWORD dwDisposition; */
617 /* internal variables */
620 FIXME("(%p) empty stub!\n", lpcml);
625 if (lpcml->cbSize < sizeof(CREATEMRULIST))
628 FIXME("(%lu %lu %lx %lx \"%s\" %p)\n",
629 lpcml->cbSize, lpcml->nMaxItems, lpcml->dwFlags,
630 (DWORD)lpcml->hKey, lpcml->lpszSubKey, lpcml->lpfnCompare);
632 /* dummy pointer creation */
633 ptr = COMCTL32_Alloc (32);
635 FIXME("-- ret = %p\n", ptr);
640 /**************************************************************************
641 * EnumMRUListA [COMCTL32.154]
643 * Enumerate item in a list
646 * hList [I] list handle
647 * nItemPos [I] item position to enumerate
648 * lpBuffer [O] buffer to receive item
649 * nBufferSize [I] size of buffer
652 * For binary lists specifies how many bytes were copied to buffer, for
653 * string lists specifies full length of string. Enumerating past the end
654 * of list returns -1.
655 * If lpBuffer == NULL or nItemPos is -ve return value is no. of items in
658 INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
661 FIXME("(%08x, %d, %p, %ld): stub\n", hList, nItemPos, lpBuffer,
666 /**************************************************************************
667 * Str_GetPtrA [COMCTL32.233]
678 Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
682 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
684 if (!lpDest && lpSrc)
685 return strlen (lpSrc);
695 len = strlen (lpSrc);
699 RtlMoveMemory (lpDest, lpSrc, len);
706 /**************************************************************************
707 * Str_SetPtrA [COMCTL32.234]
717 Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
719 TRACE("(%p %p)\n", lppDest, lpSrc);
722 LPSTR ptr = COMCTL32_ReAlloc (*lppDest, strlen (lpSrc) + 1);
730 COMCTL32_Free (*lppDest);
739 /**************************************************************************
740 * Str_GetPtrW [COMCTL32.235]
751 Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
755 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
757 if (!lpDest && lpSrc)
758 return strlenW (lpSrc);
768 len = strlenW (lpSrc);
772 RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
779 /**************************************************************************
780 * Str_SetPtrW [COMCTL32.236]
790 Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
792 TRACE("(%p %p)\n", lppDest, lpSrc);
795 INT len = strlenW (lpSrc) + 1;
796 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len * sizeof(WCHAR));
799 strcpyW (ptr, lpSrc);
804 COMCTL32_Free (*lppDest);
813 /**************************************************************************
814 * Str_GetPtrWtoA [internal]
816 * Converts a unicode string into a multi byte string
819 * lpSrc [I] Pointer to the unicode source string
820 * lpDest [O] Pointer to caller supplied storage for the multi byte string
821 * nMaxLen [I] Size, in bytes, of the destination buffer
824 * Length, in bytes, of the converted string.
828 Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen)
832 TRACE("(%s %p %d)\n", debugstr_w(lpSrc), lpDest, nMaxLen);
834 if (!lpDest && lpSrc)
835 return WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
845 len = WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
849 WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, lpDest, len, NULL, NULL);
856 /**************************************************************************
857 * Str_SetPtrAtoW [internal]
859 * Converts a multi byte string to a unicode string.
860 * If the pointer to the destination buffer is NULL a buffer is allocated.
861 * If the destination buffer is too small to keep the converted multi byte
862 * string the destination buffer is reallocated. If the source pointer is
863 * NULL, the destination buffer is freed.
866 * lppDest [I/O] pointer to a pointer to the destination buffer
867 * lpSrc [I] pointer to a multi byte string
870 * TRUE: conversion successful
875 Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc)
877 TRACE("(%p %s)\n", lppDest, lpSrc);
880 INT len = MultiByteToWideChar(CP_ACP,0,lpSrc,-1,NULL,0);
881 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len*sizeof(WCHAR));
885 MultiByteToWideChar(CP_ACP,0,lpSrc,-1,ptr,len);
890 COMCTL32_Free (*lppDest);
899 /**************************************************************************
900 * The DSA-API is a set of functions to create and manipulate arrays of
901 * fixed-size memory blocks. These arrays can store any kind of data
902 * (strings, icons...).
905 /**************************************************************************
906 * DSA_Create [COMCTL32.320] Creates a dynamic storage array
909 * nSize [I] size of the array elements
910 * nGrow [I] number of elements by which the array grows when it is filled
913 * Success: pointer to an array control structure. Use this like a handle.
918 DSA_Create (INT nSize, INT nGrow)
922 TRACE("(size=%d grow=%d)\n", nSize, nGrow);
924 hdsa = (HDSA)COMCTL32_Alloc (sizeof(DSA));
927 hdsa->nItemCount = 0;
930 hdsa->nItemSize = nSize;
931 hdsa->nGrow = max(1, nGrow);
938 /**************************************************************************
939 * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array
942 * hdsa [I] pointer to the array control structure
950 DSA_Destroy (const HDSA hdsa)
952 TRACE("(%p)\n", hdsa);
957 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
960 return COMCTL32_Free (hdsa);
964 /**************************************************************************
965 * DSA_GetItem [COMCTL32.322]
968 * hdsa [I] pointer to the array control structure
969 * nIndex [I] number of the Item to get
970 * pDest [O] destination buffer. Has to be >= dwElementSize.
978 DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
982 TRACE("(%p %d %p)\n", hdsa, nIndex, pDest);
986 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
989 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
990 memmove (pDest, pSrc, hdsa->nItemSize);
996 /**************************************************************************
997 * DSA_GetItemPtr [COMCTL32.323]
999 * Retrieves a pointer to the specified item.
1002 * hdsa [I] pointer to the array control structure
1003 * nIndex [I] index of the desired item
1006 * Success: pointer to an item
1011 DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
1015 TRACE("(%p %d)\n", hdsa, nIndex);
1019 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
1022 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1024 TRACE("-- ret=%p\n", pSrc);
1030 /**************************************************************************
1031 * DSA_SetItem [COMCTL32.325]
1033 * Sets the contents of an item in the array.
1036 * hdsa [I] pointer to the array control structure
1037 * nIndex [I] index for the item
1038 * pSrc [I] pointer to the new item data
1046 DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
1048 INT nSize, nNewItems;
1049 LPVOID pDest, lpTemp;
1051 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
1053 if ((!hdsa) || nIndex < 0)
1056 if (hdsa->nItemCount <= nIndex) {
1057 /* within the old array */
1058 if (hdsa->nMaxCount > nIndex) {
1059 /* within the allocated space, set a new boundary */
1060 hdsa->nItemCount = nIndex + 1;
1063 /* resize the block of memory */
1065 hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1);
1066 nSize = hdsa->nItemSize * nNewItems;
1068 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1072 hdsa->nMaxCount = nNewItems;
1073 hdsa->nItemCount = nIndex + 1;
1074 hdsa->pData = lpTemp;
1078 /* put the new entry in */
1079 pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1080 TRACE("-- move dest=%p src=%p size=%d\n",
1081 pDest, pSrc, hdsa->nItemSize);
1082 memmove (pDest, pSrc, hdsa->nItemSize);
1088 /**************************************************************************
1089 * DSA_InsertItem [COMCTL32.325]
1092 * hdsa [I] pointer to the array control structure
1093 * nIndex [I] index for the new item
1094 * pSrc [I] pointer to the element
1097 * Success: position of the new item
1102 DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
1104 INT nNewItems, nSize, i;
1105 LPVOID lpTemp, lpDest;
1108 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
1110 if ((!hdsa) || nIndex < 0)
1113 for (i = 0; i < hdsa->nItemSize; i += 4) {
1114 p = *(DWORD**)((char *) pSrc + i);
1115 if (IsBadStringPtrA ((char*)p, 256))
1116 TRACE("-- %d=%p\n", i, (DWORD*)p);
1118 TRACE("-- %d=%p [%s]\n", i, p, debugstr_a((char*)p));
1121 /* when nIndex >= nItemCount then append */
1122 if (nIndex >= hdsa->nItemCount)
1123 nIndex = hdsa->nItemCount;
1125 /* do we need to resize ? */
1126 if (hdsa->nItemCount >= hdsa->nMaxCount) {
1127 nNewItems = hdsa->nMaxCount + hdsa->nGrow;
1128 nSize = hdsa->nItemSize * nNewItems;
1130 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1134 hdsa->nMaxCount = nNewItems;
1135 hdsa->pData = lpTemp;
1138 /* do we need to move elements ? */
1139 if (nIndex < hdsa->nItemCount) {
1140 lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1141 lpDest = (char *) lpTemp + hdsa->nItemSize;
1142 nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
1143 TRACE("-- move dest=%p src=%p size=%d\n",
1144 lpDest, lpTemp, nSize);
1145 memmove (lpDest, lpTemp, nSize);
1148 /* ok, we can put the new Item in */
1150 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1151 TRACE("-- move dest=%p src=%p size=%d\n",
1152 lpDest, pSrc, hdsa->nItemSize);
1153 memmove (lpDest, pSrc, hdsa->nItemSize);
1159 /**************************************************************************
1160 * DSA_DeleteItem [COMCTL32.326]
1163 * hdsa [I] pointer to the array control structure
1164 * nIndex [I] index for the element to delete
1167 * Success: number of the deleted element
1172 DSA_DeleteItem (const HDSA hdsa, INT nIndex)
1174 LPVOID lpDest,lpSrc;
1177 TRACE("(%p %d)\n", hdsa, nIndex);
1181 if (nIndex < 0 || nIndex >= hdsa->nItemCount)
1184 /* do we need to move ? */
1185 if (nIndex < hdsa->nItemCount - 1) {
1186 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1187 lpSrc = (char *) lpDest + hdsa->nItemSize;
1188 nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
1189 TRACE("-- move dest=%p src=%p size=%d\n",
1190 lpDest, lpSrc, nSize);
1191 memmove (lpDest, lpSrc, nSize);
1197 if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
1198 nSize = hdsa->nItemSize * hdsa->nItemCount;
1200 lpDest = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1204 hdsa->nMaxCount = hdsa->nItemCount;
1205 hdsa->pData = lpDest;
1212 /**************************************************************************
1213 * DSA_DeleteAllItems [COMCTL32.326]
1215 * Removes all items and reinitializes the array.
1218 * hdsa [I] pointer to the array control structure
1226 DSA_DeleteAllItems (const HDSA hdsa)
1228 TRACE("(%p)\n", hdsa);
1232 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1235 hdsa->nItemCount = 0;
1237 hdsa->nMaxCount = 0;
1243 /**************************************************************************
1244 * The DPA-API is a set of functions to create and manipulate arrays of
1248 /**************************************************************************
1249 * DPA_Create [COMCTL32.328] Creates a dynamic pointer array
1252 * nGrow [I] number of items by which the array grows when it is filled
1255 * Success: handle (pointer) to the pointer array.
1260 DPA_Create (INT nGrow)
1264 TRACE("(%d)\n", nGrow);
1266 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1268 hdpa->nGrow = max(8, nGrow);
1269 hdpa->hHeap = COMCTL32_hHeap;
1270 hdpa->nMaxCount = hdpa->nGrow * 2;
1272 (LPVOID*)COMCTL32_Alloc (hdpa->nMaxCount * sizeof(LPVOID));
1275 TRACE("-- %p\n", hdpa);
1281 /**************************************************************************
1282 * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array
1285 * hdpa [I] handle (pointer) to the pointer array
1293 DPA_Destroy (const HDPA hdpa)
1295 TRACE("(%p)\n", hdpa);
1300 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1303 return HeapFree (hdpa->hHeap, 0, hdpa);
1307 /**************************************************************************
1308 * DPA_Grow [COMCTL32.330]
1310 * Sets the growth amount.
1313 * hdpa [I] handle (pointer) to the existing (source) pointer array
1314 * nGrow [I] number of items, the array grows, when it's too small
1322 DPA_Grow (const HDPA hdpa, INT nGrow)
1324 TRACE("(%p %d)\n", hdpa, nGrow);
1329 hdpa->nGrow = max(8, nGrow);
1335 /**************************************************************************
1336 * DPA_Clone [COMCTL32.331]
1338 * Copies a pointer array to an other one or creates a copy
1341 * hdpa [I] handle (pointer) to the existing (source) pointer array
1342 * hdpaNew [O] handle (pointer) to the destination pointer array
1345 * Success: pointer to the destination pointer array.
1349 * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
1350 * array will be created and it's handle (pointer) is returned.
1351 * - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
1352 * this implementation just returns NULL.
1356 DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
1358 INT nNewItems, nSize;
1364 TRACE("(%p %p)\n", hdpa, hdpaNew);
1367 /* create a new DPA */
1368 hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1370 hdpaTemp->hHeap = hdpa->hHeap;
1371 hdpaTemp->nGrow = hdpa->nGrow;
1376 if (hdpaTemp->ptrs) {
1377 /* remove old pointer array */
1378 HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
1379 hdpaTemp->ptrs = NULL;
1380 hdpaTemp->nItemCount = 0;
1381 hdpaTemp->nMaxCount = 0;
1384 /* create a new pointer array */
1385 nNewItems = hdpaTemp->nGrow *
1386 ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
1387 nSize = nNewItems * sizeof(LPVOID);
1389 (LPVOID*)HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
1390 hdpaTemp->nMaxCount = nNewItems;
1392 /* clone the pointer array */
1393 hdpaTemp->nItemCount = hdpa->nItemCount;
1394 memmove (hdpaTemp->ptrs, hdpa->ptrs,
1395 hdpaTemp->nItemCount * sizeof(LPVOID));
1401 /**************************************************************************
1402 * DPA_GetPtr [COMCTL32.332]
1404 * Retrieves a pointer from a dynamic pointer array
1407 * hdpa [I] handle (pointer) to the pointer array
1408 * nIndex [I] array index of the desired pointer
1416 DPA_GetPtr (const HDPA hdpa, INT i)
1418 TRACE("(%p %d)\n", hdpa, i);
1423 WARN("no pointer array.\n");
1426 if ((i < 0) || (i >= hdpa->nItemCount)) {
1427 WARN("not enough pointers in array (%d vs %d).\n",i,hdpa->nItemCount);
1431 TRACE("-- %p\n", hdpa->ptrs[i]);
1433 return hdpa->ptrs[i];
1437 /**************************************************************************
1438 * DPA_GetPtrIndex [COMCTL32.333]
1440 * Retrieves the index of the specified pointer
1443 * hdpa [I] handle (pointer) to the pointer array
1447 * Success: index of the specified pointer
1452 DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
1459 for (i = 0; i < hdpa->nItemCount; i++) {
1460 if (hdpa->ptrs[i] == p)
1468 /**************************************************************************
1469 * DPA_InsertPtr [COMCTL32.334]
1471 * Inserts a pointer into a dynamic pointer array
1474 * hdpa [I] handle (pointer) to the array
1476 * p [I] pointer to insert
1479 * Success: index of the inserted pointer
1484 DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p)
1486 INT nNewItems, nSize, nIndex = 0;
1487 LPVOID *lpTemp, *lpDest;
1489 TRACE("(%p %d %p)\n", hdpa, i, p);
1491 if ((!hdpa) || (i < 0))
1496 (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1497 2 * hdpa->nGrow * sizeof(LPVOID));
1500 hdpa->nMaxCount = hdpa->nGrow * 2;
1504 if (hdpa->nItemCount >= hdpa->nMaxCount) {
1505 TRACE("-- resizing\n");
1506 nNewItems = hdpa->nMaxCount + hdpa->nGrow;
1507 nSize = nNewItems * sizeof(LPVOID);
1509 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1513 hdpa->nMaxCount = nNewItems;
1514 hdpa->ptrs = lpTemp;
1517 if (i >= hdpa->nItemCount) {
1518 nIndex = hdpa->nItemCount;
1519 TRACE("-- appending at %d\n", nIndex);
1522 TRACE("-- inserting at %d\n", i);
1523 lpTemp = hdpa->ptrs + i;
1524 lpDest = lpTemp + 1;
1525 nSize = (hdpa->nItemCount - i) * sizeof(LPVOID);
1526 TRACE("-- move dest=%p src=%p size=%x\n",
1527 lpDest, lpTemp, nSize);
1528 memmove (lpDest, lpTemp, nSize);
1535 hdpa->ptrs[nIndex] = p;
1541 /**************************************************************************
1542 * DPA_SetPtr [COMCTL32.335]
1544 * Sets a pointer in the pointer array
1547 * hdpa [I] handle (pointer) to the pointer array
1548 * i [I] index of the pointer that will be set
1549 * p [I] pointer to be set
1557 DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
1561 TRACE("(%p %d %p)\n", hdpa, i, p);
1563 if ((!hdpa) || i < 0)
1566 if (hdpa->nItemCount <= i) {
1567 /* within the old array */
1568 if (hdpa->nMaxCount > i) {
1569 /* within the allocated space, set a new boundary */
1570 hdpa->nItemCount = i+1;
1573 /* resize the block of memory */
1575 hdpa->nGrow * ((INT)(((i+1) - 1) / hdpa->nGrow) + 1);
1576 INT nSize = nNewItems * sizeof(LPVOID);
1578 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1583 hdpa->nItemCount = nNewItems;
1584 hdpa->ptrs = lpTemp;
1588 /* put the new entry in */
1595 /**************************************************************************
1596 * DPA_DeletePtr [COMCTL32.336]
1598 * Removes a pointer from the pointer array.
1601 * hdpa [I] handle (pointer) to the pointer array
1602 * i [I] index of the pointer that will be deleted
1605 * Success: deleted pointer
1610 DPA_DeletePtr (const HDPA hdpa, INT i)
1612 LPVOID *lpDest, *lpSrc, lpTemp = NULL;
1615 TRACE("(%p %d)\n", hdpa, i);
1617 if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
1620 lpTemp = hdpa->ptrs[i];
1622 /* do we need to move ?*/
1623 if (i < hdpa->nItemCount - 1) {
1624 lpDest = hdpa->ptrs + i;
1626 nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
1627 TRACE("-- move dest=%p src=%p size=%x\n",
1628 lpDest, lpSrc, nSize);
1629 memmove (lpDest, lpSrc, nSize);
1632 hdpa->nItemCount --;
1635 if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
1636 INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount);
1637 nSize = nNewItems * sizeof(LPVOID);
1638 lpDest = (LPVOID)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1643 hdpa->nMaxCount = nNewItems;
1644 hdpa->ptrs = (LPVOID*)lpDest;
1651 /**************************************************************************
1652 * DPA_DeleteAllPtrs [COMCTL32.337]
1654 * Removes all pointers and reinitializes the array.
1657 * hdpa [I] handle (pointer) to the pointer array
1665 DPA_DeleteAllPtrs (const HDPA hdpa)
1667 TRACE("(%p)\n", hdpa);
1672 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1675 hdpa->nItemCount = 0;
1676 hdpa->nMaxCount = hdpa->nGrow * 2;
1677 hdpa->ptrs = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1678 hdpa->nMaxCount * sizeof(LPVOID));
1684 /**************************************************************************
1685 * DPA_QuickSort [Internal]
1687 * Ordinary quicksort (used by DPA_Sort).
1690 * lpPtrs [I] pointer to the pointer array
1691 * l [I] index of the "left border" of the partition
1692 * r [I] index of the "right border" of the partition
1693 * pfnCompare [I] pointer to the compare function
1694 * lParam [I] user defined value (3rd parameter in compare function)
1701 DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
1702 PFNDPACOMPARE pfnCompare, LPARAM lParam)
1707 TRACE("l=%i r=%i\n", l, r);
1709 if (l==r) /* one element is always sorted */
1711 if (r<l) /* oops, got it in the wrong order */
1713 DPA_QuickSort(lpPtrs, r, l, pfnCompare, lParam);
1716 m = (l+r)/2; /* divide by two */
1717 DPA_QuickSort(lpPtrs, l, m, pfnCompare, lParam);
1718 DPA_QuickSort(lpPtrs, m+1, r, pfnCompare, lParam);
1720 /* join the two sides */
1721 while( (l<=m) && (m<r) )
1723 if(pfnCompare(lpPtrs[l],lpPtrs[m+1],lParam)>0)
1726 memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof lpPtrs[l]);
1736 /**************************************************************************
1737 * DPA_Sort [COMCTL32.338]
1739 * Sorts a pointer array using a user defined compare function
1742 * hdpa [I] handle (pointer) to the pointer array
1743 * pfnCompare [I] pointer to the compare function
1744 * lParam [I] user defined value (3rd parameter of compare function)
1752 DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
1754 if (!hdpa || !pfnCompare)
1757 TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
1759 if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
1760 DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
1761 pfnCompare, lParam);
1767 /**************************************************************************
1768 * DPA_Search [COMCTL32.339]
1770 * Searches a pointer array for a specified pointer
1773 * hdpa [I] handle (pointer) to the pointer array
1774 * pFind [I] pointer to search for
1775 * nStart [I] start index
1776 * pfnCompare [I] pointer to the compare function
1777 * lParam [I] user defined value (3rd parameter of compare function)
1778 * uOptions [I] search options
1781 * Success: index of the pointer in the array.
1785 * Binary search taken from R.Sedgewick "Algorithms in C"!
1786 * Function is NOT tested!
1787 * If something goes wrong, blame HIM not ME! (Eric Kohl)
1791 DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
1792 PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
1794 if (!hdpa || !pfnCompare || !pFind)
1797 TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n",
1798 hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
1800 if (uOptions & DPAS_SORTED) {
1801 /* array is sorted --> use binary search */
1805 TRACE("binary search\n");
1807 l = (nStart == -1) ? 0 : nStart;
1808 r = hdpa->nItemCount - 1;
1812 n = (pfnCompare)(pFind, lpPtr[x], lParam);
1818 TRACE("-- ret=%d\n", n);
1823 if (uOptions & DPAS_INSERTBEFORE) {
1824 TRACE("-- ret=%d\n", r);
1828 if (uOptions & DPAS_INSERTAFTER) {
1829 TRACE("-- ret=%d\n", l);
1834 /* array is not sorted --> use linear search */
1838 TRACE("linear search\n");
1840 nIndex = (nStart == -1)? 0 : nStart;
1842 for (; nIndex < hdpa->nItemCount; nIndex++) {
1843 if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
1844 TRACE("-- ret=%d\n", nIndex);
1850 TRACE("-- not found: ret=-1\n");
1855 /**************************************************************************
1856 * DPA_CreateEx [COMCTL32.340]
1858 * Creates a dynamic pointer array using the specified size and heap.
1861 * nGrow [I] number of items by which the array grows when it is filled
1862 * hHeap [I] handle to the heap where the array is stored
1865 * Success: handle (pointer) to the pointer array.
1870 DPA_CreateEx (INT nGrow, HANDLE hHeap)
1874 TRACE("(%d 0x%x)\n", nGrow, hHeap);
1877 hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(DPA));
1879 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1882 hdpa->nGrow = min(8, nGrow);
1883 hdpa->hHeap = hHeap ? hHeap : COMCTL32_hHeap;
1884 hdpa->nMaxCount = hdpa->nGrow * 2;
1886 (LPVOID*)HeapAlloc (hHeap, HEAP_ZERO_MEMORY,
1887 hdpa->nMaxCount * sizeof(LPVOID));
1890 TRACE("-- %p\n", hdpa);
1896 /**************************************************************************
1897 * Notification functions
1900 typedef struct tagNOTIFYDATA
1908 } NOTIFYDATA, *LPNOTIFYDATA;
1911 /**************************************************************************
1912 * DoNotify [Internal]
1916 DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
1919 LPNMHDR lpNmh = NULL;
1922 TRACE("(0x%04x 0x%04x %d %p 0x%08lx)\n",
1923 lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr,
1924 lpNotify->dwParam5);
1926 if (!lpNotify->hwndTo)
1929 if (lpNotify->hwndFrom == -1) {
1931 idFrom = lpHdr->idFrom;
1934 if (lpNotify->hwndFrom) {
1935 HWND hwndParent = GetParent (lpNotify->hwndFrom);
1937 hwndParent = GetWindow (lpNotify->hwndFrom, GW_OWNER);
1939 idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
1943 lpNmh = (lpHdr) ? lpHdr : &nmhdr;
1945 lpNmh->hwndFrom = lpNotify->hwndFrom;
1946 lpNmh->idFrom = idFrom;
1947 lpNmh->code = uCode;
1950 return SendMessageA (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
1954 /**************************************************************************
1955 * SendNotify [COMCTL32.341]
1964 * Success: return value from notification
1969 COMCTL32_SendNotify (HWND hwndFrom, HWND hwndTo,
1970 UINT uCode, LPNMHDR lpHdr)
1974 TRACE("(0x%04x 0x%04x %d %p)\n",
1975 hwndFrom, hwndTo, uCode, lpHdr);
1977 notify.hwndFrom = hwndFrom;
1978 notify.hwndTo = hwndTo;
1979 notify.dwParam5 = 0;
1980 notify.dwParam6 = 0;
1982 return DoNotify (¬ify, uCode, lpHdr);
1986 /**************************************************************************
1987 * SendNotifyEx [COMCTL32.342]
1997 * Success: return value from notification
2002 COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
2003 LPNMHDR lpHdr, DWORD dwParam5)
2008 TRACE("(0x%04x 0x%04x %d %p 0x%08lx)\n",
2009 hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
2011 hwndNotify = hwndTo;
2013 if (IsWindow (hwndFrom)) {
2014 hwndNotify = GetParent (hwndFrom);
2020 notify.hwndFrom = hwndFrom;
2021 notify.hwndTo = hwndNotify;
2022 notify.dwParam5 = dwParam5;
2023 notify.dwParam6 = 0;
2025 return DoNotify (¬ify, uCode, lpHdr);
2029 /**************************************************************************
2030 * StrChrA [COMCTL32.350]
2035 COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
2037 return strchr (lpString, cChar);
2041 /**************************************************************************
2042 * StrStrIA [COMCTL32.355]
2046 COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
2052 return ((LPSTR)lpStr1);
2054 while (lpStr1[len1] != 0) ++len1;
2056 while (lpStr2[len2] != 0) ++len2;
2058 return ((LPSTR)(lpStr1 + len1));
2059 first = tolower (*lpStr2);
2060 while (len1 >= len2) {
2061 if (tolower(*lpStr1) == first) {
2062 for (i = 1; i < len2; ++i)
2063 if (tolower (lpStr1[i]) != tolower(lpStr2[i]))
2066 return ((LPSTR)lpStr1);
2074 /**************************************************************************
2075 * StrToIntA [COMCTL32.357] Converts a string to a signed integer.
2079 COMCTL32_StrToIntA (LPSTR lpString)
2081 return atoi(lpString);
2084 /**************************************************************************
2085 * StrToIntW [COMCTL32.365] Converts a wide char string to a signed integer.
2089 COMCTL32_StrToIntW (LPWSTR lpString)
2091 return _wtoi(lpString);
2095 /**************************************************************************
2096 * DPA_EnumCallback [COMCTL32.385]
2098 * Enumerates all items in a dynamic pointer array.
2101 * hdpa [I] handle to the dynamic pointer array
2110 DPA_EnumCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
2114 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
2118 if (hdpa->nItemCount <= 0)
2121 for (i = 0; i < hdpa->nItemCount; i++) {
2122 if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
2130 /**************************************************************************
2131 * DPA_DestroyCallback [COMCTL32.386]
2133 * Enumerates all items in a dynamic pointer array and destroys it.
2136 * hdpa [I] handle to the dynamic pointer array
2146 DPA_DestroyCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
2148 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
2150 DPA_EnumCallback (hdpa, enumProc, lParam);
2152 return DPA_Destroy (hdpa);
2156 /**************************************************************************
2157 * DSA_EnumCallback [COMCTL32.387]
2159 * Enumerates all items in a dynamic storage array.
2162 * hdsa [I] handle to the dynamic storage array
2171 DSA_EnumCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
2175 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
2179 if (hdsa->nItemCount <= 0)
2182 for (i = 0; i < hdsa->nItemCount; i++) {
2183 LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
2184 if ((enumProc)(lpItem, lParam) == 0)
2192 /**************************************************************************
2193 * DSA_DestroyCallback [COMCTL32.388]
2195 * Enumerates all items in a dynamic storage array and destroys it.
2198 * hdsa [I] handle to the dynamic storage array
2208 DSA_DestroyCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
2210 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
2212 DSA_EnumCallback (hdsa, enumProc, lParam);
2214 return DSA_Destroy (hdsa);
2217 /**************************************************************************
2218 * StrCSpnA [COMCTL32.356]
2221 INT WINAPI COMCTL32_StrCSpnA( LPCSTR lpStr, LPCSTR lpSet) {
2222 return strcspn(lpStr, lpSet);
2225 /**************************************************************************
2226 * StrChrW [COMCTL32.358]
2229 LPWSTR WINAPI COMCTL32_StrChrW( LPCWSTR lpStart, WORD wMatch) {
2230 return strchrW(lpStart, wMatch);
2233 /**************************************************************************
2234 * StrCmpNA [COMCTL32.352]
2237 INT WINAPI COMCTL32_StrCmpNA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
2238 return strncmp(lpStr1, lpStr2, nChar);
2241 /**************************************************************************
2242 * StrCmpNIA [COMCTL32.353]
2245 INT WINAPI COMCTL32_StrCmpNIA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
2246 return strncasecmp(lpStr1, lpStr2, nChar);
2249 /**************************************************************************
2250 * StrCmpNW [COMCTL32.360]
2253 INT WINAPI COMCTL32_StrCmpNW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
2254 return strncmpW(lpStr1, lpStr2, nChar);
2257 /**************************************************************************
2258 * StrCmpNIW [COMCTL32.361]
2261 INT WINAPI COMCTL32_StrCmpNIW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
2262 FIXME("(%s, %s, %i): stub\n", debugstr_w(lpStr1), debugstr_w(lpStr2), nChar);
2266 /**************************************************************************
2267 * StrRChrA [COMCTL32.351]
2270 LPSTR WINAPI COMCTL32_StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
2272 LPCSTR lpGotIt = NULL;
2273 BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) );
2275 TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
2277 if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
2279 for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
2281 if (*lpStart != LOBYTE(wMatch)) continue;
2282 if (dbcs && lpStart[1] != HIBYTE(wMatch)) continue;
2285 return (LPSTR)lpGotIt;
2289 /**************************************************************************
2290 * StrRChrW [COMCTL32.359]
2293 LPWSTR WINAPI COMCTL32_StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
2295 LPCWSTR lpGotIt = NULL;
2297 TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
2298 if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
2300 for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
2301 if (*lpStart == wMatch) lpGotIt = lpStart;
2303 return (LPWSTR)lpGotIt;
2307 /**************************************************************************
2308 * StrStrA [COMCTL32.354]
2311 LPSTR WINAPI COMCTL32_StrStrA( LPCSTR lpFirst, LPCSTR lpSrch) {
2312 return strstr(lpFirst, lpSrch);
2315 /**************************************************************************
2316 * StrStrW [COMCTL32.362]
2319 LPWSTR WINAPI COMCTL32_StrStrW( LPCWSTR lpFirst, LPCWSTR lpSrch) {
2320 return strstrW(lpFirst, lpSrch);
2323 /**************************************************************************
2324 * StrSpnW [COMCTL32.364]
2327 INT WINAPI COMCTL32_StrSpnW( LPWSTR lpStr, LPWSTR lpSet) {
2328 LPWSTR lpLoop = lpStr;
2331 if ((lpStr == 0) || (lpSet == 0)) return 0;
2333 /* while(*lpLoop) { if lpLoop++; } */
2335 for(; (*lpLoop != 0); lpLoop++)
2336 if( strchrW(lpSet, *(WORD*)lpLoop))
2337 return (INT)(lpLoop-lpStr);
2339 return (INT)(lpLoop-lpStr);
2342 /**************************************************************************
2343 * COMCTL32_410 [COMCTL32.410]
2345 * FIXME: What's this supposed to do?
2346 * Parameter 1 is an HWND, you're on your own for the rest.
2349 BOOL WINAPI COMCTL32_410( HWND hw, DWORD b, DWORD c, DWORD d) {
2351 FIXME("(%x, %lx, %lx, %lx): stub!\n", hw, b, c, d);
2356 /**************************************************************************
2357 * COMCTL32_411 [COMCTL32.411]
2359 * FIXME: What's this supposed to do?
2360 * Parameter 1 is an HWND, you're on your own for the rest.
2363 BOOL WINAPI COMCTL32_411( HWND hw, DWORD b, DWORD c) {
2365 FIXME("(%x, %lx, %lx): stub!\n", hw, b, c);
2370 /**************************************************************************
2371 * COMCTL32_412 [COMCTL32.412]
2373 * FIXME: What's this supposed to do?
2374 * Parameter 1 is an HWND, you're on your own for the rest.
2377 BOOL WINAPI COMCTL32_412( HWND hwnd, DWORD b, DWORD c)
2379 FIXME("(%x, %lx, %lx): stub!\n", hwnd, b, c);
2381 if (IsWindow (hwnd) == FALSE)
2391 /**************************************************************************
2392 * COMCTL32_413 [COMCTL32.413]
2394 * FIXME: What's this supposed to do?
2395 * Parameter 1 is an HWND, you're on your own for the rest.
2398 BOOL WINAPI COMCTL32_413( HWND hw, DWORD b, DWORD c, DWORD d) {
2400 FIXME("(%x, %lx, %lx, %lx): stub!\n", hw, b, c, d);
2406 /**************************************************************************
2407 * COMCTL32_415 [COMCTL32.415]
2409 * FIXME: What's this supposed to do?
2410 * Parameter 1 is an HWND, you're on your own for the rest.
2413 BOOL WINAPI COMCTL32_415( HWND hwnd, DWORD b, DWORD c, DWORD d, DWORD e)
2416 FIXME("(%x, %lx, %lx, %lx, %lx): stub!\n", hwnd, b, c, d, e);