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.324]
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.327]
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
);