Documentation ordinal fixes.
[wine/wine-kai.git] / dlls / comctl32 / comctl32undoc.c
blobcc7f2c1cb1f7d2524febe2075e81b13e86885f53
1 /*
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
8 * NOTES
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).
14 * TODO
15 * - Add more functions.
16 * - Write some documentation.
19 #include <string.h>
20 #include <stdlib.h> /* atoi */
21 #include <ctype.h>
23 #include "winbase.h"
24 #include "winerror.h"
25 #include "wine/unicode.h"
26 #include "objbase.h"
27 #include "commctrl.h"
28 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(commctrl);
33 extern HANDLE COMCTL32_hHeap; /* handle to the private heap */
36 typedef struct _STREAMDATA
38 DWORD dwSize;
39 DWORD dwData2;
40 DWORD dwItems;
41 } STREAMDATA, *PSTREAMDATA;
43 typedef struct _LOADDATA
45 INT nCount;
46 PVOID ptr;
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
58 * PARAMS
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
64 * NOTES
65 * No more information available yet!
68 HRESULT WINAPI
69 DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
71 HRESULT errCode;
72 LARGE_INTEGER position;
73 ULARGE_INTEGER newPosition;
74 STREAMDATA streamData;
75 LOADDATA loadData;
76 ULONG ulRead;
77 HDPA hDpa;
78 PVOID *ptr;
80 FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
81 phDpa, loadProc, pStream, lParam);
83 if (!phDpa || !loadProc || !pStream)
84 return E_INVALIDARG;
86 *phDpa = (HDPA)NULL;
88 position.s.LowPart = 0;
89 position.s.HighPart = 0;
91 errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition);
92 if (errCode != S_OK)
93 return errCode;
95 errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead);
96 if (errCode != S_OK)
97 return errCode;
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) {
105 errCode = E_FAIL;
108 /* create the dpa */
109 hDpa = DPA_Create (streamData.dwItems);
110 if (!hDpa)
111 return E_OUTOFMEMORY;
113 if (!DPA_Grow (hDpa, streamData.dwItems))
114 return E_OUTOFMEMORY;
116 /* load data from the stream into the dpa */
117 ptr = hDpa->ptrs;
118 for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) {
119 errCode = (loadProc)(&loadData, pStream, lParam);
120 if (errCode != S_OK) {
121 errCode = S_FALSE;
122 break;
125 *ptr = loadData.ptr;
126 ptr++;
129 /* set the number of items */
130 hDpa->nItemCount = loadData.nCount;
132 /* store the handle to the dpa */
133 *phDpa = hDpa;
134 FIXME ("new hDpa=%p\n", hDpa);
136 return errCode;
140 /**************************************************************************
141 * DPA_SaveStream [COMCTL32.10]
143 * Saves a dynamic pointer array to a stream
145 * PARAMS
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
151 * NOTES
152 * No more information available yet!
155 HRESULT WINAPI
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);
162 return E_FAIL;
166 /**************************************************************************
167 * DPA_Merge [COMCTL32.11]
169 * PARAMS
170 * hdpa1 [I] handle to a dynamic pointer array
171 * hdpa2 [I] handle to a dynamic pointer array
172 * dwFlags [I] flags
173 * pfnCompare [I] pointer to sort function
174 * pfnMerge [I] pointer to merge function
175 * lParam [I] application specific value
177 * NOTES
178 * No more information available yet!
181 BOOL WINAPI
182 DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
183 PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam)
185 INT nCount;
186 LPVOID *pWork1, *pWork2;
187 INT nResult;
188 INT nIndex;
190 TRACE("%p %p %08lx %p %p %08lx)\n",
191 hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam);
193 if (IsBadWritePtr (hdpa1, sizeof(DPA)))
194 return FALSE;
196 if (IsBadWritePtr (hdpa2, sizeof(DPA)))
197 return FALSE;
199 if (IsBadCodePtr ((FARPROC)pfnCompare))
200 return FALSE;
202 if (IsBadCodePtr ((FARPROC)pfnMerge))
203 return FALSE;
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)
216 return TRUE;
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);
237 if (nResult == 0)
239 PVOID ptr;
241 ptr = (pfnMerge)(1, *pWork1, *pWork2, lParam);
242 if (!ptr)
243 return FALSE;
245 nCount--;
246 pWork2--;
247 *pWork1 = ptr;
248 nIndex--;
249 pWork1--;
251 else if (nResult < 0)
253 if (!dwFlags & 8)
255 PVOID ptr;
257 ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1);
259 (pfnMerge)(2, ptr, NULL, lParam);
261 nIndex--;
262 pWork1--;
264 else
266 if (!dwFlags & 4)
268 PVOID ptr;
270 ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
271 if (!ptr)
272 return FALSE;
273 DPA_InsertPtr (hdpa1, nIndex, ptr);
275 nCount--;
276 pWork2--;
280 while (nCount >= 0);
282 return TRUE;
286 /**************************************************************************
287 * Alloc [COMCTL32.71]
289 * Allocates memory block from the dll's private heap
291 * PARAMS
292 * dwSize [I] size of the allocated memory block
294 * RETURNS
295 * Success: pointer to allocated memory block
296 * Failure: NULL
299 LPVOID WINAPI
300 COMCTL32_Alloc (DWORD dwSize)
302 LPVOID lpPtr;
304 TRACE("(0x%lx)\n", dwSize);
306 lpPtr = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
308 TRACE("-- ret=%p\n", lpPtr);
310 return 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.
320 * PARAMS
321 * lpSrc [I] pointer to memory block which will be resized
322 * dwSize [I] new size of the memory block.
324 * RETURNS
325 * Success: pointer to the resized memory block
326 * Failure: NULL
328 * NOTES
329 * If lpSrc is a NULL-pointer, then COMCTL32_ReAlloc allocates a memory
330 * block like COMCTL32_Alloc.
333 LPVOID WINAPI
334 COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
336 LPVOID lpDest;
338 TRACE("(%p 0x%08lx)\n", lpSrc, dwSize);
340 if (lpSrc)
341 lpDest = HeapReAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, lpSrc, dwSize);
342 else
343 lpDest = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
345 TRACE("-- ret=%p\n", lpDest);
347 return lpDest;
351 /**************************************************************************
352 * Free [COMCTL32.73]
354 * Frees an allocated memory block from the dll's private heap.
356 * PARAMS
357 * lpMem [I] pointer to memory block which will be freed
359 * RETURNS
360 * Success: TRUE
361 * Failure: FALSE
364 BOOL WINAPI
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
377 * private heap.
379 * PARAMS
380 * lpMem [I] pointer to an allocated memory block
382 * RETURNS
383 * Success: size of the specified memory block
384 * Failure: 0
387 DWORD WINAPI
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)
398 * lists.
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;
416 /* dwFlags */
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 */
432 DWORD dwParam2;
433 DWORD dwParam3;
434 HKEY hkeyMRU;
435 LPCSTR lpszSubKey;
436 DWORD dwParam6;
437 } MRU, *HMRU;
439 HANDLE WINAPI
440 CreateMRUListLazyA (LPCREATEMRULIST lpcml, DWORD dwParam2,
441 DWORD dwParam3, DWORD dwParam4);
444 /**************************************************************************
445 * CreateMRUListA [COMCTL32.151]
447 * PARAMS
448 * lpcml [I] ptr to CREATEMRULIST structure.
450 * RETURNS
451 * Handle to MRU list.
453 HANDLE WINAPI
454 CreateMRUListA (LPCREATEMRULIST lpcml)
456 return CreateMRUListLazyA (lpcml, 0, 0, 0);
459 /**************************************************************************
460 * FreeMRUListA [COMCTL32.152]
462 * PARAMS
463 * hMRUList [I] Handle to list.
466 DWORD WINAPI
467 FreeMRUListA (HANDLE hMRUList)
469 FIXME("(%08x) empty stub!\n", hMRUList);
471 #if 0
472 if (!(hmru->dwParam1 & 1001)) {
473 RegSetValueExA (hmru->hKeyMRU, "MRUList", 0, REG_SZ,
474 hmru->lpszMRUString,
475 strlen (hmru->lpszMRUString));
479 RegClosKey (hmru->hkeyMRU
480 COMCTL32_Free32 (hmru->lpszMRUString);
481 #endif
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.
494 * PARAMS
495 * hList [I] Handle to list.
496 * lpData [I] ptr to data to add.
497 * cbData [I] no. of bytes of data.
499 * RETURNS
500 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
501 * -1 on error.
503 INT WINAPI
504 AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
506 FIXME("(%08x, %p, %ld) empty stub!\n", hList, lpData, cbData);
508 return 0;
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.
518 * PARAMS
519 * hList [I] Handle to list.
520 * lpszString [I] ptr to string to add.
522 * RETURNS
523 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
524 * -1 on error.
526 INT WINAPI
527 AddMRUStringA(HANDLE hList, LPCSTR lpszString)
529 FIXME("(%08x, %s) empty stub!\n", hList, debugstr_a(lpszString));
531 return 0;
534 /**************************************************************************
535 * DelMRUString [COMCTL32.156]
537 * Removes item from either string or binary list (despite its name)
539 * PARAMS
540 * hList [I] list handle
541 * nItemPos [I] item position to remove 0 -> MRU
543 * RETURNS
544 * TRUE is successful, FALSE if nItemPos is out of range.
546 BOOL WINAPI
547 DelMRUString(HANDLE hList, INT nItemPos)
549 FIXME("(%08x, %d): stub\n", hList, nItemPos);
550 return TRUE;
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).
560 * PARAMS
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)
566 * RETURNS
567 * Position in list 0 -> MRU. -1 if item not found.
569 INT WINAPI
570 FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
572 FIXME("(%08x, %p, %ld, %p) empty stub!\n",
573 hList, lpData, cbData, lpRegNum);
575 return 0;
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).
585 * PARAMS
586 * hList [I] list handle
587 * lpszString [I] string to find
588 * lpRegNum [O] position in registry (maybe NULL)
590 * RETURNS
591 * Position in list 0 -> MRU. -1 if item not found.
593 INT WINAPI
594 FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
596 FIXME("(%08x, %s, %p) empty stub!\n", hList, debugstr_a(lpszString),
597 lpRegNum);
599 return 0;
602 /**************************************************************************
603 * CreateMRUListLazyA [COMCTL32.157]
605 HANDLE WINAPI
606 CreateMRUListLazyA (LPCREATEMRULIST lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
608 /* DWORD dwLocal1; *
609 * HKEY hkeyResult; *
610 * DWORD dwLocal3; *
611 * LPVOID lMRU; *
612 * DWORD dwLocal5; *
613 * DWORD dwLocal6; *
614 * DWORD dwLocal7; *
615 * DWORD dwDisposition; */
617 /* internal variables */
618 LPVOID ptr;
620 FIXME("(%p) empty stub!\n", lpcml);
622 if (lpcml == NULL)
623 return 0;
625 if (lpcml->cbSize < sizeof(CREATEMRULIST))
626 return 0;
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);
637 return (HANDLE)ptr;
640 /**************************************************************************
641 * EnumMRUListA [COMCTL32.154]
643 * Enumerate item in a list
645 * PARAMS
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
651 * RETURNS
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
656 * the list.
658 INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
659 DWORD nBufferSize)
661 FIXME("(%08x, %d, %p, %ld): stub\n", hList, nItemPos, lpBuffer,
662 nBufferSize);
663 return 0;
666 /**************************************************************************
667 * Str_GetPtrA [COMCTL32.233]
669 * PARAMS
670 * lpSrc [I]
671 * lpDest [O]
672 * nMaxLen [I]
674 * RETURNS
677 INT WINAPI
678 Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
680 INT len;
682 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
684 if (!lpDest && lpSrc)
685 return strlen (lpSrc);
687 if (nMaxLen == 0)
688 return 0;
690 if (lpSrc == NULL) {
691 lpDest[0] = '\0';
692 return 0;
695 len = strlen (lpSrc);
696 if (len >= nMaxLen)
697 len = nMaxLen - 1;
699 RtlMoveMemory (lpDest, lpSrc, len);
700 lpDest[len] = '\0';
702 return len;
706 /**************************************************************************
707 * Str_SetPtrA [COMCTL32.234]
709 * PARAMS
710 * lppDest [O]
711 * lpSrc [I]
713 * RETURNS
716 BOOL WINAPI
717 Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
719 TRACE("(%p %p)\n", lppDest, lpSrc);
721 if (lpSrc) {
722 LPSTR ptr = COMCTL32_ReAlloc (*lppDest, strlen (lpSrc) + 1);
723 if (!ptr)
724 return FALSE;
725 strcpy (ptr, lpSrc);
726 *lppDest = ptr;
728 else {
729 if (*lppDest) {
730 COMCTL32_Free (*lppDest);
731 *lppDest = NULL;
735 return TRUE;
739 /**************************************************************************
740 * Str_GetPtrW [COMCTL32.235]
742 * PARAMS
743 * lpSrc [I]
744 * lpDest [O]
745 * nMaxLen [I]
747 * RETURNS
750 INT WINAPI
751 Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
753 INT len;
755 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
757 if (!lpDest && lpSrc)
758 return strlenW (lpSrc);
760 if (nMaxLen == 0)
761 return 0;
763 if (lpSrc == NULL) {
764 lpDest[0] = L'\0';
765 return 0;
768 len = strlenW (lpSrc);
769 if (len >= nMaxLen)
770 len = nMaxLen - 1;
772 RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
773 lpDest[len] = L'\0';
775 return len;
779 /**************************************************************************
780 * Str_SetPtrW [COMCTL32.236]
782 * PARAMS
783 * lpDest [O]
784 * lpSrc [I]
786 * RETURNS
789 BOOL WINAPI
790 Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
792 TRACE("(%p %p)\n", lppDest, lpSrc);
794 if (lpSrc) {
795 INT len = strlenW (lpSrc) + 1;
796 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len * sizeof(WCHAR));
797 if (!ptr)
798 return FALSE;
799 strcpyW (ptr, lpSrc);
800 *lppDest = ptr;
802 else {
803 if (*lppDest) {
804 COMCTL32_Free (*lppDest);
805 *lppDest = NULL;
809 return TRUE;
813 /**************************************************************************
814 * Str_GetPtrWtoA [internal]
816 * Converts a unicode string into a multi byte string
818 * PARAMS
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
823 * RETURNS
824 * Length, in bytes, of the converted string.
828 Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen)
830 INT len;
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);
837 if (nMaxLen == 0)
838 return 0;
840 if (lpSrc == NULL) {
841 lpDest[0] = '\0';
842 return 0;
845 len = WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
846 if (len >= nMaxLen)
847 len = nMaxLen - 1;
849 WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, lpDest, len, NULL, NULL);
850 lpDest[len] = '\0';
852 return len;
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.
865 * PARAMS
866 * lppDest [I/O] pointer to a pointer to the destination buffer
867 * lpSrc [I] pointer to a multi byte string
869 * RETURNS
870 * TRUE: conversion successful
871 * FALSE: error
874 BOOL
875 Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc)
877 TRACE("(%p %s)\n", lppDest, lpSrc);
879 if (lpSrc) {
880 INT len = MultiByteToWideChar(CP_ACP,0,lpSrc,-1,NULL,0);
881 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len*sizeof(WCHAR));
883 if (!ptr)
884 return FALSE;
885 MultiByteToWideChar(CP_ACP,0,lpSrc,-1,ptr,len);
886 *lppDest = ptr;
888 else {
889 if (*lppDest) {
890 COMCTL32_Free (*lppDest);
891 *lppDest = NULL;
895 return TRUE;
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
908 * PARAMS
909 * nSize [I] size of the array elements
910 * nGrow [I] number of elements by which the array grows when it is filled
912 * RETURNS
913 * Success: pointer to an array control structure. Use this like a handle.
914 * Failure: NULL
917 HDSA WINAPI
918 DSA_Create (INT nSize, INT nGrow)
920 HDSA hdsa;
922 TRACE("(size=%d grow=%d)\n", nSize, nGrow);
924 hdsa = (HDSA)COMCTL32_Alloc (sizeof(DSA));
925 if (hdsa)
927 hdsa->nItemCount = 0;
928 hdsa->pData = NULL;
929 hdsa->nMaxCount = 0;
930 hdsa->nItemSize = nSize;
931 hdsa->nGrow = max(1, nGrow);
934 return hdsa;
938 /**************************************************************************
939 * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array
941 * PARAMS
942 * hdsa [I] pointer to the array control structure
944 * RETURNS
945 * Success: TRUE
946 * Failure: FALSE
949 BOOL WINAPI
950 DSA_Destroy (const HDSA hdsa)
952 TRACE("(%p)\n", hdsa);
954 if (!hdsa)
955 return FALSE;
957 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
958 return FALSE;
960 return COMCTL32_Free (hdsa);
964 /**************************************************************************
965 * DSA_GetItem [COMCTL32.322]
967 * PARAMS
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.
972 * RETURNS
973 * Success: TRUE
974 * Failure: FALSE
977 BOOL WINAPI
978 DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
980 LPVOID pSrc;
982 TRACE("(%p %d %p)\n", hdsa, nIndex, pDest);
984 if (!hdsa)
985 return FALSE;
986 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
987 return FALSE;
989 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
990 memmove (pDest, pSrc, hdsa->nItemSize);
992 return TRUE;
996 /**************************************************************************
997 * DSA_GetItemPtr [COMCTL32.323]
999 * Retrieves a pointer to the specified item.
1001 * PARAMS
1002 * hdsa [I] pointer to the array control structure
1003 * nIndex [I] index of the desired item
1005 * RETURNS
1006 * Success: pointer to an item
1007 * Failure: NULL
1010 LPVOID WINAPI
1011 DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
1013 LPVOID pSrc;
1015 TRACE("(%p %d)\n", hdsa, nIndex);
1017 if (!hdsa)
1018 return NULL;
1019 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
1020 return NULL;
1022 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1024 TRACE("-- ret=%p\n", pSrc);
1026 return pSrc;
1030 /**************************************************************************
1031 * DSA_SetItem [COMCTL32.325]
1033 * Sets the contents of an item in the array.
1035 * PARAMS
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
1040 * RETURNS
1041 * Success: TRUE
1042 * Failure: FALSE
1045 BOOL WINAPI
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)
1054 return FALSE;
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;
1062 else {
1063 /* resize the block of memory */
1064 nNewItems =
1065 hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1);
1066 nSize = hdsa->nItemSize * nNewItems;
1068 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1069 if (!lpTemp)
1070 return FALSE;
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);
1084 return TRUE;
1088 /**************************************************************************
1089 * DSA_InsertItem [COMCTL32.324]
1091 * PARAMS
1092 * hdsa [I] pointer to the array control structure
1093 * nIndex [I] index for the new item
1094 * pSrc [I] pointer to the element
1096 * RETURNS
1097 * Success: position of the new item
1098 * Failure: -1
1101 INT WINAPI
1102 DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
1104 INT nNewItems, nSize, i;
1105 LPVOID lpTemp, lpDest;
1106 LPDWORD p;
1108 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
1110 if ((!hdsa) || nIndex < 0)
1111 return -1;
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);
1117 else
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);
1131 if (!lpTemp)
1132 return -1;
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 */
1149 hdsa->nItemCount++;
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);
1155 return nIndex;
1159 /**************************************************************************
1160 * DSA_DeleteItem [COMCTL32.326]
1162 * PARAMS
1163 * hdsa [I] pointer to the array control structure
1164 * nIndex [I] index for the element to delete
1166 * RETURNS
1167 * Success: number of the deleted element
1168 * Failure: -1
1171 INT WINAPI
1172 DSA_DeleteItem (const HDSA hdsa, INT nIndex)
1174 LPVOID lpDest,lpSrc;
1175 INT nSize;
1177 TRACE("(%p %d)\n", hdsa, nIndex);
1179 if (!hdsa)
1180 return -1;
1181 if (nIndex < 0 || nIndex >= hdsa->nItemCount)
1182 return -1;
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);
1194 hdsa->nItemCount--;
1196 /* free memory ? */
1197 if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
1198 nSize = hdsa->nItemSize * hdsa->nItemCount;
1200 lpDest = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1201 if (!lpDest)
1202 return -1;
1204 hdsa->nMaxCount = hdsa->nItemCount;
1205 hdsa->pData = lpDest;
1208 return nIndex;
1212 /**************************************************************************
1213 * DSA_DeleteAllItems [COMCTL32.327]
1215 * Removes all items and reinitializes the array.
1217 * PARAMS
1218 * hdsa [I] pointer to the array control structure
1220 * RETURNS
1221 * Success: TRUE
1222 * Failure: FALSE
1225 BOOL WINAPI
1226 DSA_DeleteAllItems (const HDSA hdsa)
1228 TRACE("(%p)\n", hdsa);
1230 if (!hdsa)
1231 return FALSE;
1232 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1233 return FALSE;
1235 hdsa->nItemCount = 0;
1236 hdsa->pData = NULL;
1237 hdsa->nMaxCount = 0;
1239 return TRUE;
1243 /**************************************************************************
1244 * The DPA-API is a set of functions to create and manipulate arrays of
1245 * pointers.
1248 /**************************************************************************
1249 * DPA_Create [COMCTL32.328] Creates a dynamic pointer array
1251 * PARAMS
1252 * nGrow [I] number of items by which the array grows when it is filled
1254 * RETURNS
1255 * Success: handle (pointer) to the pointer array.
1256 * Failure: NULL
1259 HDPA WINAPI
1260 DPA_Create (INT nGrow)
1262 HDPA hdpa;
1264 TRACE("(%d)\n", nGrow);
1266 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1267 if (hdpa) {
1268 hdpa->nGrow = max(8, nGrow);
1269 hdpa->hHeap = COMCTL32_hHeap;
1270 hdpa->nMaxCount = hdpa->nGrow * 2;
1271 hdpa->ptrs =
1272 (LPVOID*)COMCTL32_Alloc (hdpa->nMaxCount * sizeof(LPVOID));
1275 TRACE("-- %p\n", hdpa);
1277 return hdpa;
1281 /**************************************************************************
1282 * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array
1284 * PARAMS
1285 * hdpa [I] handle (pointer) to the pointer array
1287 * RETURNS
1288 * Success: TRUE
1289 * Failure: FALSE
1292 BOOL WINAPI
1293 DPA_Destroy (const HDPA hdpa)
1295 TRACE("(%p)\n", hdpa);
1297 if (!hdpa)
1298 return FALSE;
1300 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1301 return FALSE;
1303 return HeapFree (hdpa->hHeap, 0, hdpa);
1307 /**************************************************************************
1308 * DPA_Grow [COMCTL32.330]
1310 * Sets the growth amount.
1312 * PARAMS
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
1316 * RETURNS
1317 * Success: TRUE
1318 * Failure: FALSE
1321 BOOL WINAPI
1322 DPA_Grow (const HDPA hdpa, INT nGrow)
1324 TRACE("(%p %d)\n", hdpa, nGrow);
1326 if (!hdpa)
1327 return FALSE;
1329 hdpa->nGrow = max(8, nGrow);
1331 return TRUE;
1335 /**************************************************************************
1336 * DPA_Clone [COMCTL32.331]
1338 * Copies a pointer array to an other one or creates a copy
1340 * PARAMS
1341 * hdpa [I] handle (pointer) to the existing (source) pointer array
1342 * hdpaNew [O] handle (pointer) to the destination pointer array
1344 * RETURNS
1345 * Success: pointer to the destination pointer array.
1346 * Failure: NULL
1348 * NOTES
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.
1355 HDPA WINAPI
1356 DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
1358 INT nNewItems, nSize;
1359 HDPA hdpaTemp;
1361 if (!hdpa)
1362 return NULL;
1364 TRACE("(%p %p)\n", hdpa, hdpaNew);
1366 if (!hdpaNew) {
1367 /* create a new DPA */
1368 hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1369 sizeof(DPA));
1370 hdpaTemp->hHeap = hdpa->hHeap;
1371 hdpaTemp->nGrow = hdpa->nGrow;
1373 else
1374 hdpaTemp = hdpaNew;
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);
1388 hdpaTemp->ptrs =
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));
1397 return hdpaTemp;
1401 /**************************************************************************
1402 * DPA_GetPtr [COMCTL32.332]
1404 * Retrieves a pointer from a dynamic pointer array
1406 * PARAMS
1407 * hdpa [I] handle (pointer) to the pointer array
1408 * nIndex [I] array index of the desired pointer
1410 * RETURNS
1411 * Success: pointer
1412 * Failure: NULL
1415 LPVOID WINAPI
1416 DPA_GetPtr (const HDPA hdpa, INT i)
1418 TRACE("(%p %d)\n", hdpa, i);
1420 if (!hdpa)
1421 return NULL;
1422 if (!hdpa->ptrs) {
1423 WARN("no pointer array.\n");
1424 return NULL;
1426 if ((i < 0) || (i >= hdpa->nItemCount)) {
1427 WARN("not enough pointers in array (%d vs %d).\n",i,hdpa->nItemCount);
1428 return NULL;
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
1442 * PARAMS
1443 * hdpa [I] handle (pointer) to the pointer array
1444 * p [I] pointer
1446 * RETURNS
1447 * Success: index of the specified pointer
1448 * Failure: -1
1451 INT WINAPI
1452 DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
1454 INT i;
1456 if (!hdpa->ptrs)
1457 return -1;
1459 for (i = 0; i < hdpa->nItemCount; i++) {
1460 if (hdpa->ptrs[i] == p)
1461 return i;
1464 return -1;
1468 /**************************************************************************
1469 * DPA_InsertPtr [COMCTL32.334]
1471 * Inserts a pointer into a dynamic pointer array
1473 * PARAMS
1474 * hdpa [I] handle (pointer) to the array
1475 * i [I] array index
1476 * p [I] pointer to insert
1478 * RETURNS
1479 * Success: index of the inserted pointer
1480 * Failure: -1
1483 INT WINAPI
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))
1492 return -1;
1494 if (!hdpa->ptrs) {
1495 hdpa->ptrs =
1496 (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1497 2 * hdpa->nGrow * sizeof(LPVOID));
1498 if (!hdpa->ptrs)
1499 return -1;
1500 hdpa->nMaxCount = hdpa->nGrow * 2;
1501 nIndex = 0;
1503 else {
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,
1510 hdpa->ptrs, nSize);
1511 if (!lpTemp)
1512 return -1;
1513 hdpa->nMaxCount = nNewItems;
1514 hdpa->ptrs = lpTemp;
1517 if (i >= hdpa->nItemCount) {
1518 nIndex = hdpa->nItemCount;
1519 TRACE("-- appending at %d\n", nIndex);
1521 else {
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);
1529 nIndex = i;
1533 /* insert item */
1534 hdpa->nItemCount++;
1535 hdpa->ptrs[nIndex] = p;
1537 return nIndex;
1541 /**************************************************************************
1542 * DPA_SetPtr [COMCTL32.335]
1544 * Sets a pointer in the pointer array
1546 * PARAMS
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
1551 * RETURNS
1552 * Success: TRUE
1553 * Failure: FALSE
1556 BOOL WINAPI
1557 DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
1559 LPVOID *lpTemp;
1561 TRACE("(%p %d %p)\n", hdpa, i, p);
1563 if ((!hdpa) || i < 0)
1564 return FALSE;
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;
1572 else {
1573 /* resize the block of memory */
1574 INT nNewItems =
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,
1579 hdpa->ptrs, nSize);
1580 if (!lpTemp)
1581 return FALSE;
1583 hdpa->nItemCount = nNewItems;
1584 hdpa->ptrs = lpTemp;
1588 /* put the new entry in */
1589 hdpa->ptrs[i] = p;
1591 return TRUE;
1595 /**************************************************************************
1596 * DPA_DeletePtr [COMCTL32.336]
1598 * Removes a pointer from the pointer array.
1600 * PARAMS
1601 * hdpa [I] handle (pointer) to the pointer array
1602 * i [I] index of the pointer that will be deleted
1604 * RETURNS
1605 * Success: deleted pointer
1606 * Failure: NULL
1609 LPVOID WINAPI
1610 DPA_DeletePtr (const HDPA hdpa, INT i)
1612 LPVOID *lpDest, *lpSrc, lpTemp = NULL;
1613 INT nSize;
1615 TRACE("(%p %d)\n", hdpa, i);
1617 if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
1618 return NULL;
1620 lpTemp = hdpa->ptrs[i];
1622 /* do we need to move ?*/
1623 if (i < hdpa->nItemCount - 1) {
1624 lpDest = hdpa->ptrs + i;
1625 lpSrc = lpDest + 1;
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 --;
1634 /* free memory ?*/
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,
1639 hdpa->ptrs, nSize);
1640 if (!lpDest)
1641 return NULL;
1643 hdpa->nMaxCount = nNewItems;
1644 hdpa->ptrs = (LPVOID*)lpDest;
1647 return lpTemp;
1651 /**************************************************************************
1652 * DPA_DeleteAllPtrs [COMCTL32.337]
1654 * Removes all pointers and reinitializes the array.
1656 * PARAMS
1657 * hdpa [I] handle (pointer) to the pointer array
1659 * RETURNS
1660 * Success: TRUE
1661 * Failure: FALSE
1664 BOOL WINAPI
1665 DPA_DeleteAllPtrs (const HDPA hdpa)
1667 TRACE("(%p)\n", hdpa);
1669 if (!hdpa)
1670 return FALSE;
1672 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1673 return FALSE;
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));
1680 return TRUE;
1684 /**************************************************************************
1685 * DPA_QuickSort [Internal]
1687 * Ordinary quicksort (used by DPA_Sort).
1689 * PARAMS
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)
1696 * RETURNS
1697 * NONE
1700 static VOID
1701 DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
1702 PFNDPACOMPARE pfnCompare, LPARAM lParam)
1704 INT m;
1705 LPVOID t;
1707 TRACE("l=%i r=%i\n", l, r);
1709 if (l==r) /* one element is always sorted */
1710 return;
1711 if (r<l) /* oops, got it in the wrong order */
1713 DPA_QuickSort(lpPtrs, r, l, pfnCompare, lParam);
1714 return;
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)
1725 t = lpPtrs[m+1];
1726 memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof lpPtrs[l]);
1727 lpPtrs[l] = t;
1729 m++;
1731 l++;
1736 /**************************************************************************
1737 * DPA_Sort [COMCTL32.338]
1739 * Sorts a pointer array using a user defined compare function
1741 * PARAMS
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)
1746 * RETURNS
1747 * Success: TRUE
1748 * Failure: FALSE
1751 BOOL WINAPI
1752 DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
1754 if (!hdpa || !pfnCompare)
1755 return FALSE;
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);
1763 return TRUE;
1767 /**************************************************************************
1768 * DPA_Search [COMCTL32.339]
1770 * Searches a pointer array for a specified pointer
1772 * PARAMS
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
1780 * RETURNS
1781 * Success: index of the pointer in the array.
1782 * Failure: -1
1784 * NOTES
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)
1790 INT WINAPI
1791 DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
1792 PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
1794 if (!hdpa || !pfnCompare || !pFind)
1795 return -1;
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 */
1802 INT l, r, x, n;
1803 LPVOID *lpPtr;
1805 TRACE("binary search\n");
1807 l = (nStart == -1) ? 0 : nStart;
1808 r = hdpa->nItemCount - 1;
1809 lpPtr = hdpa->ptrs;
1810 while (r >= l) {
1811 x = (l + r) / 2;
1812 n = (pfnCompare)(pFind, lpPtr[x], lParam);
1813 if (n < 0)
1814 r = x - 1;
1815 else
1816 l = x + 1;
1817 if (n == 0) {
1818 TRACE("-- ret=%d\n", n);
1819 return n;
1823 if (uOptions & DPAS_INSERTBEFORE) {
1824 TRACE("-- ret=%d\n", r);
1825 return r;
1828 if (uOptions & DPAS_INSERTAFTER) {
1829 TRACE("-- ret=%d\n", l);
1830 return l;
1833 else {
1834 /* array is not sorted --> use linear search */
1835 LPVOID *lpPtr;
1836 INT nIndex;
1838 TRACE("linear search\n");
1840 nIndex = (nStart == -1)? 0 : nStart;
1841 lpPtr = hdpa->ptrs;
1842 for (; nIndex < hdpa->nItemCount; nIndex++) {
1843 if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
1844 TRACE("-- ret=%d\n", nIndex);
1845 return nIndex;
1850 TRACE("-- not found: ret=-1\n");
1851 return -1;
1855 /**************************************************************************
1856 * DPA_CreateEx [COMCTL32.340]
1858 * Creates a dynamic pointer array using the specified size and heap.
1860 * PARAMS
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
1864 * RETURNS
1865 * Success: handle (pointer) to the pointer array.
1866 * Failure: NULL
1869 HDPA WINAPI
1870 DPA_CreateEx (INT nGrow, HANDLE hHeap)
1872 HDPA hdpa;
1874 TRACE("(%d 0x%x)\n", nGrow, hHeap);
1876 if (hHeap)
1877 hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(DPA));
1878 else
1879 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1881 if (hdpa) {
1882 hdpa->nGrow = min(8, nGrow);
1883 hdpa->hHeap = hHeap ? hHeap : COMCTL32_hHeap;
1884 hdpa->nMaxCount = hdpa->nGrow * 2;
1885 hdpa->ptrs =
1886 (LPVOID*)HeapAlloc (hHeap, HEAP_ZERO_MEMORY,
1887 hdpa->nMaxCount * sizeof(LPVOID));
1890 TRACE("-- %p\n", hdpa);
1892 return hdpa;
1896 /**************************************************************************
1897 * Notification functions
1900 typedef struct tagNOTIFYDATA
1902 HWND hwndFrom;
1903 HWND hwndTo;
1904 DWORD dwParam3;
1905 DWORD dwParam4;
1906 DWORD dwParam5;
1907 DWORD dwParam6;
1908 } NOTIFYDATA, *LPNOTIFYDATA;
1911 /**************************************************************************
1912 * DoNotify [Internal]
1915 static LRESULT
1916 DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
1918 NMHDR nmhdr;
1919 LPNMHDR lpNmh = NULL;
1920 UINT idFrom = 0;
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)
1927 return 0;
1929 if (lpNotify->hwndFrom == -1) {
1930 lpNmh = lpHdr;
1931 idFrom = lpHdr->idFrom;
1933 else {
1934 if (lpNotify->hwndFrom) {
1935 HWND hwndParent = GetParent (lpNotify->hwndFrom);
1936 if (hwndParent) {
1937 hwndParent = GetWindow (lpNotify->hwndFrom, GW_OWNER);
1938 if (hwndParent)
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]
1957 * PARAMS
1958 * hwndFrom [I]
1959 * hwndTo [I]
1960 * uCode [I]
1961 * lpHdr [I]
1963 * RETURNS
1964 * Success: return value from notification
1965 * Failure: 0
1968 LRESULT WINAPI
1969 COMCTL32_SendNotify (HWND hwndFrom, HWND hwndTo,
1970 UINT uCode, LPNMHDR lpHdr)
1972 NOTIFYDATA notify;
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 (&notify, uCode, lpHdr);
1986 /**************************************************************************
1987 * SendNotifyEx [COMCTL32.342]
1989 * PARAMS
1990 * hwndFrom [I]
1991 * hwndTo [I]
1992 * uCode [I]
1993 * lpHdr [I]
1994 * dwParam5 [I]
1996 * RETURNS
1997 * Success: return value from notification
1998 * Failure: 0
2001 LRESULT WINAPI
2002 COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
2003 LPNMHDR lpHdr, DWORD dwParam5)
2005 NOTIFYDATA notify;
2006 HWND hwndNotify;
2008 TRACE("(0x%04x 0x%04x %d %p 0x%08lx)\n",
2009 hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
2011 hwndNotify = hwndTo;
2012 if (!hwndTo) {
2013 if (IsWindow (hwndFrom)) {
2014 hwndNotify = GetParent (hwndFrom);
2015 if (!hwndNotify)
2016 return 0;
2020 notify.hwndFrom = hwndFrom;
2021 notify.hwndTo = hwndNotify;
2022 notify.dwParam5 = dwParam5;
2023 notify.dwParam6 = 0;
2025 return DoNotify (&notify, uCode, lpHdr);
2029 /**************************************************************************
2030 * StrChrA [COMCTL32.350]
2034 LPSTR WINAPI
2035 COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
2037 return strchr (lpString, cChar);
2041 /**************************************************************************
2042 * StrStrIA [COMCTL32.355]
2045 LPSTR WINAPI
2046 COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
2048 INT len1, len2, i;
2049 CHAR first;
2051 if (*lpStr2 == 0)
2052 return ((LPSTR)lpStr1);
2053 len1 = 0;
2054 while (lpStr1[len1] != 0) ++len1;
2055 len2 = 0;
2056 while (lpStr2[len2] != 0) ++len2;
2057 if (len2 == 0)
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]))
2064 break;
2065 if (i >= len2)
2066 return ((LPSTR)lpStr1);
2068 ++lpStr1; --len1;
2070 return (NULL);
2074 /**************************************************************************
2075 * StrToIntA [COMCTL32.357] Converts a string to a signed integer.
2078 INT WINAPI
2079 COMCTL32_StrToIntA (LPSTR lpString)
2081 return atoi(lpString);
2084 /**************************************************************************
2085 * StrToIntW [COMCTL32.365] Converts a wide char string to a signed integer.
2088 INT WINAPI
2089 COMCTL32_StrToIntW (LPWSTR lpString)
2091 return _wtoi(lpString);
2095 /**************************************************************************
2096 * DPA_EnumCallback [COMCTL32.385]
2098 * Enumerates all items in a dynamic pointer array.
2100 * PARAMS
2101 * hdpa [I] handle to the dynamic pointer array
2102 * enumProc [I]
2103 * lParam [I]
2105 * RETURNS
2106 * none
2109 VOID WINAPI
2110 DPA_EnumCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
2112 INT i;
2114 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
2116 if (!hdpa)
2117 return;
2118 if (hdpa->nItemCount <= 0)
2119 return;
2121 for (i = 0; i < hdpa->nItemCount; i++) {
2122 if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
2123 return;
2126 return;
2130 /**************************************************************************
2131 * DPA_DestroyCallback [COMCTL32.386]
2133 * Enumerates all items in a dynamic pointer array and destroys it.
2135 * PARAMS
2136 * hdpa [I] handle to the dynamic pointer array
2137 * enumProc [I]
2138 * lParam [I]
2140 * RETURNS
2141 * Success: TRUE
2142 * Failure: FALSE
2145 BOOL WINAPI
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.
2161 * PARAMS
2162 * hdsa [I] handle to the dynamic storage array
2163 * enumProc [I]
2164 * lParam [I]
2166 * RETURNS
2167 * none
2170 VOID WINAPI
2171 DSA_EnumCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
2173 INT i;
2175 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
2177 if (!hdsa)
2178 return;
2179 if (hdsa->nItemCount <= 0)
2180 return;
2182 for (i = 0; i < hdsa->nItemCount; i++) {
2183 LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
2184 if ((enumProc)(lpItem, lParam) == 0)
2185 return;
2188 return;
2192 /**************************************************************************
2193 * DSA_DestroyCallback [COMCTL32.388]
2195 * Enumerates all items in a dynamic storage array and destroys it.
2197 * PARAMS
2198 * hdsa [I] handle to the dynamic storage array
2199 * enumProc [I]
2200 * lParam [I]
2202 * RETURNS
2203 * Success: TRUE
2204 * Failure: FALSE
2207 BOOL WINAPI
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);
2263 return 0;
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;
2283 lpGotIt = lpStart;
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;
2330 /* validate ptr */
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);
2353 return TRUE;
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);
2367 return TRUE;
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)
2382 return FALSE;
2384 if (b == 0)
2385 return FALSE;
2388 return TRUE;
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);
2402 return TRUE;
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);
2418 return TRUE;