source: trunk/src/comctl32/comctl32undoc.c@ 8266

Last change on this file since 8266 was 7815, checked in by sandervl, 24 years ago

Wine updates

File size: 66.0 KB
Line 
1/*
2 * Undocumented functions from COMCTL32.DLL
3 *
4 * Copyright 1998 Eric Kohl
5 * 1998 Juergen Schmied <j.schmied@metronet.de>
6 * 2000 Eric Kohl for CodeWeavers
7 *
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).
13 *
14 * TODO
15 * - Add more functions.
16 * - Write some documentation.
17 */
18#ifdef __WIN32OS2__
19#define WINE_LARGE_INTEGER
20#endif
21
22#include <string.h>
23#include <stdlib.h> /* atoi */
24#include <ctype.h>
25#include <limits.h>
26
27#include "commctrl.h"
28#include "objbase.h"
29#include "winbase.h"
30#include "winerror.h"
31#include "winreg.h"
32
33#include "wine/unicode.h"
34#include "comctl32.h"
35
36#include "debugtools.h"
37
38DEFAULT_DEBUG_CHANNEL(commctrl);
39
40
41extern HANDLE COMCTL32_hHeap; /* handle to the private heap */
42
43
44typedef struct _STREAMDATA
45{
46 DWORD dwSize;
47 DWORD dwData2;
48 DWORD dwItems;
49} STREAMDATA, *PSTREAMDATA;
50
51typedef struct _LOADDATA
52{
53 INT nCount;
54 PVOID ptr;
55} LOADDATA, *LPLOADDATA;
56
57#ifdef __WIN32OS2__
58typedef HRESULT (* CALLBACK DPALOADPROC)(LPLOADDATA,IStream*,LPARAM);
59#else
60typedef HRESULT (CALLBACK *DPALOADPROC)(LPLOADDATA,IStream*,LPARAM);
61#endif
62
63INT __cdecl _wtoi(LPWSTR string);
64
65/**************************************************************************
66 * DPA_LoadStream [COMCTL32.9]
67 *
68 * Loads a dynamic pointer array from a stream
69 *
70 * PARAMS
71 * phDpa [O] pointer to a handle to a dynamic pointer array
72 * loadProc [I] pointer to a callback function
73 * pStream [I] pointer to a stream
74 * lParam [I] application specific value
75 *
76 * NOTES
77 * No more information available yet!
78 */
79
80HRESULT WINAPI
81DPA_LoadStream (HDPA *phDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
82{
83 HRESULT errCode;
84 LARGE_INTEGER position;
85 ULARGE_INTEGER newPosition;
86 STREAMDATA streamData;
87 LOADDATA loadData;
88 ULONG ulRead;
89 HDPA hDpa;
90 PVOID *ptr;
91
92 FIXME ("phDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
93 phDpa, loadProc, pStream, lParam);
94
95 if (!phDpa || !loadProc || !pStream)
96 return E_INVALIDARG;
97
98 *phDpa = (HDPA)NULL;
99
100 position.s.LowPart = 0;
101 position.s.HighPart = 0;
102
103 /*
104 * Zero out our streamData
105 */
106 memset(&streamData,0,sizeof(STREAMDATA));
107
108 errCode = IStream_Seek (pStream, position, STREAM_SEEK_CUR, &newPosition);
109 if (errCode != S_OK)
110 return errCode;
111
112 errCode = IStream_Read (pStream, &streamData, sizeof(STREAMDATA), &ulRead);
113 if (errCode != S_OK)
114 return errCode;
115
116 FIXME ("dwSize=%lu dwData2=%lu dwItems=%lu\n",
117 streamData.dwSize, streamData.dwData2, streamData.dwItems);
118
119 if ( ulRead < sizeof(STREAMDATA) ||
120 lParam < sizeof(STREAMDATA) ||
121 streamData.dwSize < sizeof(STREAMDATA) ||
122 streamData.dwData2 < 1) {
123 errCode = E_FAIL;
124 }
125
126 if (streamData.dwItems > (UINT_MAX / 2 / sizeof(VOID*))) /* 536870911 */
127 return E_OUTOFMEMORY;
128
129 /* create the dpa */
130 hDpa = DPA_Create (streamData.dwItems);
131 if (!hDpa)
132 return E_OUTOFMEMORY;
133
134 if (!DPA_Grow (hDpa, streamData.dwItems))
135 return E_OUTOFMEMORY;
136
137 /* load data from the stream into the dpa */
138 ptr = hDpa->ptrs;
139 for (loadData.nCount = 0; loadData.nCount < streamData.dwItems; loadData.nCount++) {
140 errCode = (loadProc)(&loadData, pStream, lParam);
141 if (errCode != S_OK) {
142 errCode = S_FALSE;
143 break;
144 }
145
146 *ptr = loadData.ptr;
147 ptr++;
148 }
149
150 /* set the number of items */
151 hDpa->nItemCount = loadData.nCount;
152
153 /* store the handle to the dpa */
154 *phDpa = hDpa;
155 FIXME ("new hDpa=%p\n", hDpa);
156
157 return errCode;
158}
159
160
161/**************************************************************************
162 * DPA_SaveStream [COMCTL32.10]
163 *
164 * Saves a dynamic pointer array to a stream
165 *
166 * PARAMS
167 * hDpa [I] handle to a dynamic pointer array
168 * loadProc [I] pointer to a callback function
169 * pStream [I] pointer to a stream
170 * lParam [I] application specific value
171 *
172 * NOTES
173 * No more information available yet!
174 */
175
176HRESULT WINAPI
177DPA_SaveStream (const HDPA hDpa, DPALOADPROC loadProc, IStream *pStream, LPARAM lParam)
178{
179
180 FIXME ("hDpa=%p loadProc=%p pStream=%p lParam=%lx\n",
181 hDpa, loadProc, pStream, lParam);
182
183 return E_FAIL;
184}
185
186
187/**************************************************************************
188 * DPA_Merge [COMCTL32.11]
189 *
190 * PARAMS
191 * hdpa1 [I] handle to a dynamic pointer array
192 * hdpa2 [I] handle to a dynamic pointer array
193 * dwFlags [I] flags
194 * pfnCompare [I] pointer to sort function
195 * pfnMerge [I] pointer to merge function
196 * lParam [I] application specific value
197 *
198 * NOTES
199 * No more information available yet!
200 */
201
202BOOL WINAPI
203DPA_Merge (const HDPA hdpa1, const HDPA hdpa2, DWORD dwFlags,
204 PFNDPACOMPARE pfnCompare, PFNDPAMERGE pfnMerge, LPARAM lParam)
205{
206 INT nCount;
207 LPVOID *pWork1, *pWork2;
208 INT nResult;
209 INT nIndex;
210
211 TRACE("%p %p %08lx %p %p %08lx)\n",
212 hdpa1, hdpa2, dwFlags, pfnCompare, pfnMerge, lParam);
213
214 if (IsBadWritePtr (hdpa1, sizeof(DPA)))
215 return FALSE;
216
217 if (IsBadWritePtr (hdpa2, sizeof(DPA)))
218 return FALSE;
219
220 if (IsBadCodePtr ((FARPROC)pfnCompare))
221 return FALSE;
222
223 if (IsBadCodePtr ((FARPROC)pfnMerge))
224 return FALSE;
225
226 if (dwFlags & DPAM_SORT) {
227 TRACE("sorting dpa's!\n");
228 if (hdpa1->nItemCount > 0)
229 DPA_Sort (hdpa1, pfnCompare, lParam);
230 TRACE ("dpa 1 sorted!\n");
231 if (hdpa2->nItemCount > 0)
232 DPA_Sort (hdpa2, pfnCompare, lParam);
233 TRACE ("dpa 2 sorted!\n");
234 }
235
236 if (hdpa2->nItemCount < 1)
237 return TRUE;
238
239 TRACE("hdpa1->nItemCount=%d hdpa2->nItemCount=%d\n",
240 hdpa1->nItemCount, hdpa2->nItemCount);
241
242
243 /* working but untrusted implementation */
244
245 pWork1 = &(hdpa1->ptrs[hdpa1->nItemCount - 1]);
246 pWork2 = &(hdpa2->ptrs[hdpa2->nItemCount - 1]);
247
248 nIndex = hdpa1->nItemCount - 1;
249 nCount = hdpa2->nItemCount - 1;
250
251 do
252 {
253 if (nIndex < 0) break;
254 nResult = (pfnCompare)(*pWork1, *pWork2, lParam);
255 TRACE("compare result=%d, dpa1.cnt=%d, dpa2.cnt=%d\n",
256 nResult, nIndex, nCount);
257
258 if (nResult == 0)
259 {
260 PVOID ptr;
261
262 ptr = (pfnMerge)(1, *pWork1, *pWork2, lParam);
263 if (!ptr)
264 return FALSE;
265
266 nCount--;
267 pWork2--;
268 *pWork1 = ptr;
269 nIndex--;
270 pWork1--;
271 }
272 else if (nResult < 0)
273 {
274 if (!(dwFlags & 8))
275 {
276 PVOID ptr;
277
278 ptr = DPA_DeletePtr (hdpa1, hdpa1->nItemCount - 1);
279
280 (pfnMerge)(2, ptr, NULL, lParam);
281 }
282 nIndex--;
283 pWork1--;
284 }
285 else
286 {
287 if (!(dwFlags & 4))
288 {
289 PVOID ptr;
290
291 ptr = (pfnMerge)(3, *pWork2, NULL, lParam);
292 if (!ptr)
293 return FALSE;
294 DPA_InsertPtr (hdpa1, nIndex, ptr);
295 }
296 nCount--;
297 pWork2--;
298 }
299
300 }
301 while (nCount >= 0);
302
303 return TRUE;
304}
305
306
307/**************************************************************************
308 * Alloc [COMCTL32.71]
309 *
310 * Allocates memory block from the dll's private heap
311 *
312 * PARAMS
313 * dwSize [I] size of the allocated memory block
314 *
315 * RETURNS
316 * Success: pointer to allocated memory block
317 * Failure: NULL
318 */
319
320LPVOID WINAPI
321COMCTL32_Alloc (DWORD dwSize)
322{
323 LPVOID lpPtr;
324
325 TRACE("(0x%lx)\n", dwSize);
326
327 lpPtr = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
328
329 TRACE("-- ret=%p\n", lpPtr);
330
331 return lpPtr;
332}
333
334
335/**************************************************************************
336 * ReAlloc [COMCTL32.72]
337 *
338 * Changes the size of an allocated memory block or allocates a memory
339 * block using the dll's private heap.
340 *
341 * PARAMS
342 * lpSrc [I] pointer to memory block which will be resized
343 * dwSize [I] new size of the memory block.
344 *
345 * RETURNS
346 * Success: pointer to the resized memory block
347 * Failure: NULL
348 *
349 * NOTES
350 * If lpSrc is a NULL-pointer, then COMCTL32_ReAlloc allocates a memory
351 * block like COMCTL32_Alloc.
352 */
353
354LPVOID WINAPI
355COMCTL32_ReAlloc (LPVOID lpSrc, DWORD dwSize)
356{
357 LPVOID lpDest;
358
359 TRACE("(%p 0x%08lx)\n", lpSrc, dwSize);
360
361 if (lpSrc)
362 lpDest = HeapReAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, lpSrc, dwSize);
363 else
364 lpDest = HeapAlloc (COMCTL32_hHeap, HEAP_ZERO_MEMORY, dwSize);
365
366 TRACE("-- ret=%p\n", lpDest);
367
368 return lpDest;
369}
370
371
372/**************************************************************************
373 * Free [COMCTL32.73]
374 *
375 * Frees an allocated memory block from the dll's private heap.
376 *
377 * PARAMS
378 * lpMem [I] pointer to memory block which will be freed
379 *
380 * RETURNS
381 * Success: TRUE
382 * Failure: FALSE
383 */
384
385BOOL WINAPI
386COMCTL32_Free (LPVOID lpMem)
387{
388 TRACE("(%p)\n", lpMem);
389
390 return HeapFree (COMCTL32_hHeap, 0, lpMem);
391}
392
393
394/**************************************************************************
395 * GetSize [COMCTL32.74]
396 *
397 * Retrieves the size of the specified memory block from the dll's
398 * private heap.
399 *
400 * PARAMS
401 * lpMem [I] pointer to an allocated memory block
402 *
403 * RETURNS
404 * Success: size of the specified memory block
405 * Failure: 0
406 */
407
408DWORD WINAPI
409COMCTL32_GetSize (LPVOID lpMem)
410{
411 TRACE("(%p)\n", lpMem);
412
413 return HeapSize (COMCTL32_hHeap, 0, lpMem);
414}
415
416
417/**************************************************************************
418 * The MRU-API is a set of functions to manipulate MRU(Most Recently Used)
419 * lists.
420 *
421 * Stored in the reg. as a set of values under a single key. Each item in the
422 * list has a value name that is a single char. 'a' - 'z', '{', '|' or '}'.
423 * The order of the list is stored with value name 'MRUList' which is a string
424 * containing the value names (i.e. 'a', 'b', etc.) in the relevant order.
425 */
426
427typedef struct tagCREATEMRULISTA
428{
429 DWORD cbSize; /* size of struct */
430 DWORD nMaxItems; /* max no. of items in list */
431 DWORD dwFlags; /* see below */
432 HKEY hKey; /* root reg. key under which list is saved */
433 LPCSTR lpszSubKey; /* reg. subkey */
434 PROC lpfnCompare; /* item compare proc */
435} CREATEMRULISTA, *LPCREATEMRULISTA;
436
437typedef struct tagCREATEMRULISTW
438{
439 DWORD cbSize; /* size of struct */
440 DWORD nMaxItems; /* max no. of items in list */
441 DWORD dwFlags; /* see below */
442 HKEY hKey; /* root reg. key under which list is saved */
443 LPCWSTR lpszSubKey; /* reg. subkey */
444 PROC lpfnCompare; /* item compare proc */
445} CREATEMRULISTW, *LPCREATEMRULISTW;
446
447/* dwFlags */
448#define MRUF_STRING_LIST 0 /* list will contain strings */
449#define MRUF_BINARY_LIST 1 /* list will contain binary data */
450#define MRUF_DELAYED_SAVE 2 /* only save list order to reg. is FreeMRUList */
451
452/* If list is a string list lpfnCompare has the following prototype
453 * int CALLBACK MRUCompareString(LPCSTR s1, LPCSTR s2)
454 * for binary lists the prototype is
455 * int CALLBACK MRUCompareBinary(LPCVOID data1, LPCVOID data2, DWORD cbData)
456 * where cbData is the no. of bytes to compare.
457 * Need to check what return value means identical - 0?
458 */
459
460typedef struct tagWINEMRUITEM
461{
462 DWORD size; /* size of data stored */
463 DWORD itemFlag; /* flags */
464 BYTE datastart;
465} WINEMRUITEM, *LPWINEMRUITEM;
466
467/* itemFlag */
468#define WMRUIF_CHANGED 0x0001 /* this dataitem changed */
469
470typedef struct tagWINEMRULIST
471{
472 CREATEMRULISTW extview; /* original create information */
473 BOOL isUnicode; /* is compare fn Unicode */
474 DWORD wineFlags; /* internal flags */
475 DWORD cursize; /* current size of realMRU */
476 LPSTR realMRU; /* pointer to string of index names */
477 LPWINEMRUITEM *array; /* array of pointers to data */
478 /* in 'a' to 'z' order */
479} WINEMRULIST, *LPWINEMRULIST;
480
481/* wineFlags */
482#define WMRUF_CHANGED 0x0001 /* MRU list has changed */
483
484/**************************************************************************
485 * MRU_SaveChanged - Localize MRU saving code
486 *
487 */
488VOID MRU_SaveChanged( LPWINEMRULIST mp )
489{
490 INT i, err;
491 HKEY newkey;
492 WCHAR realname[2];
493 LPWINEMRUITEM witem;
494 WCHAR emptyW[] = {'\0'};
495
496 /* or should we do the following instead of RegOpenKeyEx:
497 */
498
499 /* open the sub key */
500 if ((err = RegOpenKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
501 0, KEY_WRITE, &newkey))) {
502 /* not present - what to do ??? */
503 ERR("Can not open key, error=%d, attempting to create\n",
504 err);
505 if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
506 0,
507 emptyW,
508 REG_OPTION_NON_VOLATILE,
509 KEY_READ | KEY_WRITE,
510 0,
511 &newkey,
512 0))) {
513 ERR("failed to create key /%s/, err=%d\n",
514 debugstr_w(mp->extview.lpszSubKey), err);
515 return;
516 }
517 }
518 if (mp->wineFlags & WMRUF_CHANGED) {
519 mp->wineFlags &= ~WMRUF_CHANGED;
520 err = RegSetValueExA(newkey, "MRUList", 0, REG_SZ,
521 mp->realMRU, strlen(mp->realMRU) + 1);
522 if (err) {
523 ERR("error saving MRUList, err=%d\n", err);
524 }
525 TRACE("saving MRUList=/%s/\n", mp->realMRU);
526 }
527 realname[1] = 0;
528 for(i=0; i<mp->cursize; i++) {
529 witem = mp->array[i];
530 if (witem->itemFlag & WMRUIF_CHANGED) {
531 witem->itemFlag &= ~WMRUIF_CHANGED;
532 realname[0] = 'a' + i;
533 err = RegSetValueExW(newkey, realname, 0,
534 (mp->extview.dwFlags & MRUF_BINARY_LIST) ?
535 REG_BINARY : REG_SZ,
536 &witem->datastart, witem->size);
537 if (err) {
538 ERR("error saving /%s/, err=%d\n", debugstr_w(realname), err);
539 }
540 TRACE("saving value for name /%s/ size=%ld\n",
541 debugstr_w(realname), witem->size);
542 }
543 }
544 RegCloseKey( newkey );
545}
546
547/**************************************************************************
548 * FreeMRUList [COMCTL32.152]
549 *
550 * PARAMS
551 * hMRUList [I] Handle to list.
552 *
553 */
554DWORD WINAPI
555FreeMRUList (HANDLE hMRUList)
556{
557 LPWINEMRULIST mp = (LPWINEMRULIST)hMRUList;
558 INT i;
559
560 TRACE("\n");
561 if (mp->wineFlags & WMRUF_CHANGED) {
562 /* need to open key and then save the info */
563 MRU_SaveChanged( mp );
564 }
565
566 for(i=0; i<mp->extview.nMaxItems; i++) {
567 if (mp->array[i])
568 COMCTL32_Free(mp->array[i]);
569 }
570 COMCTL32_Free(mp->realMRU);
571 COMCTL32_Free(mp->array);
572 COMCTL32_Free((LPWSTR)mp->extview.lpszSubKey);
573 return COMCTL32_Free(mp);
574}
575
576
577/**************************************************************************
578 * FindMRUData [COMCTL32.169]
579 *
580 * Searches binary list for item that matches lpData of length cbData.
581 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
582 * corresponding to item's reg. name will be stored in it ('a' -> 0).
583 *
584 * PARAMS
585 * hList [I] list handle
586 * lpData [I] data to find
587 * cbData [I] length of data
588 * lpRegNum [O] position in registry (maybe NULL)
589 *
590 * RETURNS
591 * Position in list 0 -> MRU. -1 if item not found.
592 */
593INT WINAPI
594FindMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum)
595{
596 LPWINEMRULIST mp = (LPWINEMRULIST)hList;
597 INT i, ret;
598 LPSTR dataA = NULL;
599
600 if (!mp->extview.lpfnCompare) {
601 ERR("MRU list not properly created. No compare procedure.\n");
602 return -1;
603 }
604
605 if(!(mp->extview.dwFlags & MRUF_BINARY_LIST) && !mp->isUnicode) {
606 DWORD len = WideCharToMultiByte(CP_ACP, 0, lpData, -1,
607 NULL, 0, NULL, NULL);
608 dataA = COMCTL32_Alloc(len);
609 WideCharToMultiByte(CP_ACP, 0, lpData, -1, dataA, len, NULL, NULL);
610 }
611
612 for(i=0; i<mp->cursize; i++) {
613 if (mp->extview.dwFlags & MRUF_BINARY_LIST) {
614 if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart,
615 cbData))
616 break;
617 }
618 else {
619 if(mp->isUnicode) {
620 if (!mp->extview.lpfnCompare(lpData, &mp->array[i]->datastart))
621 break;
622 } else {
623 DWORD len = WideCharToMultiByte(CP_ACP, 0,
624 (LPWSTR)&mp->array[i]->datastart, -1,
625 NULL, 0, NULL, NULL);
626 LPSTR itemA = COMCTL32_Alloc(len);
627 INT cmp;
628 WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&mp->array[i]->datastart, -1,
629 itemA, len, NULL, NULL);
630
631 cmp = mp->extview.lpfnCompare(dataA, itemA);
632 COMCTL32_Free(itemA);
633 if(!cmp)
634 break;
635 }
636 }
637 }
638 if(dataA)
639 COMCTL32_Free(dataA);
640 if (i < mp->cursize)
641 ret = i;
642 else
643 ret = -1;
644 if (lpRegNum && (ret != -1))
645 *lpRegNum = 'a' + i;
646
647 TRACE("(%08x, %p, %ld, %p) returning %d\n",
648 hList, lpData, cbData, lpRegNum, ret);
649
650 return ret;
651}
652
653
654/**************************************************************************
655 * AddMRUData [COMCTL32.167]
656 *
657 * Add item to MRU binary list. If item already exists in list then it is
658 * simply moved up to the top of the list and not added again. If list is
659 * full then the least recently used item is removed to make room.
660 *
661 * PARAMS
662 * hList [I] Handle to list.
663 * lpData [I] ptr to data to add.
664 * cbData [I] no. of bytes of data.
665 *
666 * RETURNS
667 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
668 * -1 on error.
669 */
670INT WINAPI
671AddMRUData (HANDLE hList, LPCVOID lpData, DWORD cbData)
672{
673 LPWINEMRULIST mp = (LPWINEMRULIST)hList;
674 LPWINEMRUITEM witem;
675 INT i, replace, ret;
676
677 if ((replace = FindMRUData (hList, lpData, cbData, NULL)) < 0) {
678 /* either add a new entry or replace oldest */
679 if (mp->cursize < mp->extview.nMaxItems) {
680 /* Add in a new item */
681 replace = mp->cursize;
682 mp->cursize++;
683 }
684 else {
685 /* get the oldest entry and replace data */
686 replace = mp->realMRU[mp->cursize - 1] - 'a';
687 COMCTL32_Free(mp->array[replace]);
688 }
689 }
690 else {
691 /* free up the old data */
692 COMCTL32_Free(mp->array[replace]);
693 }
694
695 /* Allocate space for new item and move in the data */
696 mp->array[replace] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(cbData +
697 sizeof(WINEMRUITEM));
698 witem->itemFlag |= WMRUIF_CHANGED;
699 witem->size = cbData;
700 memcpy( &witem->datastart, lpData, cbData);
701
702 /* now rotate MRU list */
703 mp->wineFlags |= WMRUF_CHANGED;
704 for(i=mp->cursize-1; i>=1; i--) {
705 mp->realMRU[i] = mp->realMRU[i-1];
706 }
707 mp->realMRU[0] = replace + 'a';
708 TRACE("(%08x, %p, %ld) adding data, /%c/ now most current\n",
709 hList, lpData, cbData, replace+'a');
710 ret = replace;
711
712 if (!(mp->extview.dwFlags & MRUF_DELAYED_SAVE)) {
713 /* save changed stuff right now */
714 MRU_SaveChanged( mp );
715 }
716
717 return ret;
718}
719
720/**************************************************************************
721 * AddMRUStringW [COMCTL32.401]
722 *
723 * Add item to MRU string list. If item already exists in list them it is
724 * simply moved up to the top of the list and not added again. If list is
725 * full then the least recently used item is removed to make room.
726 *
727 * PARAMS
728 * hList [I] Handle to list.
729 * lpszString [I] ptr to string to add.
730 *
731 * RETURNS
732 * No. corresponding to registry name where value is stored 'a' -> 0 etc.
733 * -1 on error.
734 */
735INT WINAPI
736AddMRUStringW(HANDLE hList, LPCWSTR lpszString)
737{
738 FIXME("(%08x, %s) empty stub!\n", hList, debugstr_w(lpszString));
739
740 return 0;
741}
742
743/**************************************************************************
744 * AddMRUStringA [COMCTL32.153]
745 */
746INT WINAPI
747AddMRUStringA(HANDLE hList, LPCSTR lpszString)
748{
749 FIXME("(%08x, %s) empty stub!\n", hList, debugstr_a(lpszString));
750
751 return 0;
752}
753
754/**************************************************************************
755 * DelMRUString [COMCTL32.156]
756 *
757 * Removes item from either string or binary list (despite its name)
758 *
759 * PARAMS
760 * hList [I] list handle
761 * nItemPos [I] item position to remove 0 -> MRU
762 *
763 * RETURNS
764 * TRUE if successful, FALSE if nItemPos is out of range.
765 */
766BOOL WINAPI
767DelMRUString(HANDLE hList, INT nItemPos)
768{
769 FIXME("(%08x, %d): stub\n", hList, nItemPos);
770 return TRUE;
771}
772
773/**************************************************************************
774 * FindMRUStringW [COMCTL32.402]
775 */
776INT WINAPI
777FindMRUStringW (HANDLE hList, LPCWSTR lpszString, LPINT lpRegNum)
778{
779 FIXME("stub\n");
780 return -1;
781}
782
783/**************************************************************************
784 * FindMRUStringA [COMCTL32.155]
785 *
786 * Searches string list for item that matches lpszString.
787 * Returns position in list order 0 -> MRU and if lpRegNum != NULL then value
788 * corresponding to item's reg. name will be stored in it ('a' -> 0).
789 *
790 * PARAMS
791 * hList [I] list handle
792 * lpszString [I] string to find
793 * lpRegNum [O] position in registry (maybe NULL)
794 *
795 * RETURNS
796 * Position in list 0 -> MRU. -1 if item not found.
797 */
798INT WINAPI
799FindMRUStringA (HANDLE hList, LPCSTR lpszString, LPINT lpRegNum)
800{
801 DWORD len = MultiByteToWideChar(CP_ACP, 0, lpszString, -1, NULL, 0);
802 LPWSTR stringW = COMCTL32_Alloc(len * sizeof(WCHAR));
803 INT ret;
804
805 MultiByteToWideChar(CP_ACP, 0, lpszString, -1, stringW, len);
806 ret = FindMRUData(hList, stringW, len * sizeof(WCHAR), lpRegNum);
807 COMCTL32_Free(stringW);
808 return ret;
809}
810
811/*************************************************************************
812 * CreateMRUListLazy_common
813 */
814HANDLE CreateMRUListLazy_common(LPWINEMRULIST mp)
815{
816 INT i, err;
817 HKEY newkey;
818 DWORD datasize, dwdisp;
819 WCHAR realname[2];
820 LPWINEMRUITEM witem;
821 DWORD type;
822 WCHAR emptyW[] = {'\0'};
823
824 /* get space to save indices that will turn into names
825 * but in order of most to least recently used
826 */
827 mp->realMRU = (LPSTR) COMCTL32_Alloc(mp->extview.nMaxItems + 2);
828
829 /* get space to save pointers to actual data in order of
830 * 'a' to 'z' (0 to n).
831 */
832 mp->array = (LPVOID) COMCTL32_Alloc(mp->extview.nMaxItems *
833 sizeof(LPVOID));
834
835 /* open the sub key */
836 if ((err = RegCreateKeyExW( mp->extview.hKey, mp->extview.lpszSubKey,
837 0,
838 emptyW,
839 REG_OPTION_NON_VOLATILE,
840 KEY_READ | KEY_WRITE,
841 0,
842 &newkey,
843 &dwdisp))) {
844 /* error - what to do ??? */
845 ERR("(%lu %lu %lx %lx \"%s\" %p): Can not open key, error=%d\n",
846 mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags,
847 (DWORD)mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
848 mp->extview.lpfnCompare, err);
849 return 0;
850 }
851
852 /* get values from key 'MRUList' */
853 if (newkey) {
854 datasize = mp->extview.nMaxItems + 1;
855 if((err=RegQueryValueExA( newkey, "MRUList", 0, &type, mp->realMRU,
856 &datasize))) {
857 /* not present - set size to 1 (will become 0 later) */
858 datasize = 1;
859 *mp->realMRU = 0;
860 }
861
862 TRACE("MRU list = %s\n", mp->realMRU);
863
864 mp->cursize = datasize - 1;
865 /* datasize now has number of items in the MRUList */
866
867 /* get actual values for each entry */
868 realname[1] = 0;
869 for(i=0; i<mp->cursize; i++) {
870 realname[0] = 'a' + i;
871 if(RegQueryValueExW( newkey, realname, 0, &type, 0, &datasize)) {
872 /* not present - what to do ??? */
873 ERR("Key %s not found 1\n", debugstr_w(realname));
874 }
875 mp->array[i] = witem = (LPWINEMRUITEM)COMCTL32_Alloc(datasize +
876 sizeof(WINEMRUITEM));
877 witem->size = datasize;
878 if(RegQueryValueExW( newkey, realname, 0, &type,
879 &witem->datastart, &datasize)) {
880 /* not present - what to do ??? */
881 ERR("Key %s not found 2\n", debugstr_w(realname));
882 }
883 }
884 RegCloseKey( newkey );
885 }
886 else
887 mp->cursize = 0;
888
889 TRACE("(%lu %lu %lx %lx \"%s\" %p): Current Size = %ld\n",
890 mp->extview.cbSize, mp->extview.nMaxItems, mp->extview.dwFlags,
891 (DWORD)mp->extview.hKey, debugstr_w(mp->extview.lpszSubKey),
892 mp->extview.lpfnCompare, mp->cursize);
893 return (HANDLE)mp;
894}
895
896/**************************************************************************
897 * CreateMRUListLazyW [COMCTL32.404]
898 */
899HANDLE WINAPI
900CreateMRUListLazyW (LPCREATEMRULISTW lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
901{
902 LPWINEMRULIST mp;
903
904 if (lpcml == NULL)
905 return 0;
906
907 if (lpcml->cbSize < sizeof(CREATEMRULISTW))
908 return 0;
909
910 mp = (LPWINEMRULIST) COMCTL32_Alloc(sizeof(WINEMRULIST));
911 memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW));
912 mp->extview.lpszSubKey = COMCTL32_Alloc((strlenW(lpcml->lpszSubKey) + 1) *
913 sizeof(WCHAR));
914 strcpyW((LPWSTR)mp->extview.lpszSubKey, lpcml->lpszSubKey);
915 mp->isUnicode = TRUE;
916
917 return CreateMRUListLazy_common(mp);
918}
919
920/**************************************************************************
921 * CreateMRUListLazyA [COMCTL32.157]
922 */
923HANDLE WINAPI
924CreateMRUListLazyA (LPCREATEMRULISTA lpcml, DWORD dwParam2, DWORD dwParam3, DWORD dwParam4)
925{
926 LPWINEMRULIST mp;
927 DWORD len;
928
929 if (lpcml == NULL)
930 return 0;
931
932 if (lpcml->cbSize < sizeof(CREATEMRULISTA))
933 return 0;
934
935 mp = (LPWINEMRULIST) COMCTL32_Alloc(sizeof(WINEMRULIST));
936 memcpy(&mp->extview, lpcml, sizeof(CREATEMRULISTW));
937 len = MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1, NULL, 0);
938 mp->extview.lpszSubKey = COMCTL32_Alloc(len * sizeof(WCHAR));
939 MultiByteToWideChar(CP_ACP, 0, lpcml->lpszSubKey, -1,
940 (LPWSTR)mp->extview.lpszSubKey, len);
941 mp->isUnicode = FALSE;
942 return CreateMRUListLazy_common(mp);
943}
944
945/**************************************************************************
946 * CreateMRUListW [COMCTL32.400]
947 *
948 * PARAMS
949 * lpcml [I] ptr to CREATEMRULIST structure.
950 *
951 * RETURNS
952 * Handle to MRU list.
953 */
954HANDLE WINAPI
955CreateMRUListW (LPCREATEMRULISTW lpcml)
956{
957 return CreateMRUListLazyW(lpcml, 0, 0, 0);
958}
959
960/**************************************************************************
961 * CreateMRUListA [COMCTL32.151]
962 */
963HANDLE WINAPI
964CreateMRUListA (LPCREATEMRULISTA lpcml)
965{
966 return CreateMRUListLazyA (lpcml, 0, 0, 0);
967}
968
969
970/**************************************************************************
971 * EnumMRUListW [COMCTL32.403]
972 *
973 * Enumerate item in a list
974 *
975 * PARAMS
976 * hList [I] list handle
977 * nItemPos [I] item position to enumerate
978 * lpBuffer [O] buffer to receive item
979 * nBufferSize [I] size of buffer
980 *
981 * RETURNS
982 * For binary lists specifies how many bytes were copied to buffer, for
983 * string lists specifies full length of string. Enumerating past the end
984 * of list returns -1.
985 * If lpBuffer == NULL or nItemPos is -ve return value is no. of items in
986 * the list.
987 */
988INT WINAPI EnumMRUListW(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
989DWORD nBufferSize)
990{
991 LPWINEMRULIST mp = (LPWINEMRULIST) hList;
992 LPWINEMRUITEM witem;
993 INT desired, datasize;
994
995 if (nItemPos >= mp->cursize) return -1;
996 if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
997 desired = mp->realMRU[nItemPos];
998 desired -= 'a';
999 TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
1000 witem = mp->array[desired];
1001 datasize = min( witem->size, nBufferSize );
1002 memcpy( lpBuffer, &witem->datastart, datasize);
1003 TRACE("(%08x, %d, %p, %ld): returning len=%d\n",
1004 hList, nItemPos, lpBuffer, nBufferSize, datasize);
1005 return datasize;
1006}
1007
1008/**************************************************************************
1009 * EnumMRUListA [COMCTL32.154]
1010 *
1011 */
1012INT WINAPI EnumMRUListA(HANDLE hList, INT nItemPos, LPVOID lpBuffer,
1013DWORD nBufferSize)
1014{
1015 LPWINEMRULIST mp = (LPWINEMRULIST) hList;
1016 LPWINEMRUITEM witem;
1017 INT desired, datasize;
1018 DWORD lenA;
1019
1020 if (nItemPos >= mp->cursize) return -1;
1021 if ((nItemPos < 0) || !lpBuffer) return mp->cursize;
1022 desired = mp->realMRU[nItemPos];
1023 desired -= 'a';
1024 TRACE("nItemPos=%d, desired=%d\n", nItemPos, desired);
1025 witem = mp->array[desired];
1026 if(mp->extview.dwFlags & MRUF_BINARY_LIST) {
1027 datasize = min( witem->size, nBufferSize );
1028 memcpy( lpBuffer, &witem->datastart, datasize);
1029 } else {
1030 lenA = WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1,
1031 NULL, 0, NULL, NULL);
1032 datasize = min( witem->size, nBufferSize );
1033 WideCharToMultiByte(CP_ACP, 0, (LPWSTR)&witem->datastart, -1,
1034 lpBuffer, datasize, NULL, NULL);
1035 }
1036 TRACE("(%08x, %d, %p, %ld): returning len=%d\n",
1037 hList, nItemPos, lpBuffer, nBufferSize, datasize);
1038 return datasize;
1039}
1040
1041
1042/**************************************************************************
1043 * Str_GetPtrA [COMCTL32.233]
1044 *
1045 * PARAMS
1046 * lpSrc [I]
1047 * lpDest [O]
1048 * nMaxLen [I]
1049 *
1050 * RETURNS
1051 */
1052
1053INT WINAPI
1054Str_GetPtrA (LPCSTR lpSrc, LPSTR lpDest, INT nMaxLen)
1055{
1056 INT len;
1057
1058 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
1059
1060 if (!lpDest && lpSrc)
1061 return strlen (lpSrc);
1062
1063 if (nMaxLen == 0)
1064 return 0;
1065
1066 if (lpSrc == NULL) {
1067 lpDest[0] = '\0';
1068 return 0;
1069 }
1070
1071 len = strlen (lpSrc);
1072 if (len >= nMaxLen)
1073 len = nMaxLen - 1;
1074
1075 RtlMoveMemory (lpDest, lpSrc, len);
1076 lpDest[len] = '\0';
1077
1078 return len;
1079}
1080
1081
1082/**************************************************************************
1083 * Str_SetPtrA [COMCTL32.234]
1084 *
1085 * PARAMS
1086 * lppDest [O]
1087 * lpSrc [I]
1088 *
1089 * RETURNS
1090 */
1091
1092BOOL WINAPI
1093Str_SetPtrA (LPSTR *lppDest, LPCSTR lpSrc)
1094{
1095 TRACE("(%p %p)\n", lppDest, lpSrc);
1096
1097 if (lpSrc) {
1098 LPSTR ptr = COMCTL32_ReAlloc (*lppDest, strlen (lpSrc) + 1);
1099 if (!ptr)
1100 return FALSE;
1101 strcpy (ptr, lpSrc);
1102 *lppDest = ptr;
1103 }
1104 else {
1105 if (*lppDest) {
1106 COMCTL32_Free (*lppDest);
1107 *lppDest = NULL;
1108 }
1109 }
1110
1111 return TRUE;
1112}
1113
1114
1115/**************************************************************************
1116 * Str_GetPtrW [COMCTL32.235]
1117 *
1118 * PARAMS
1119 * lpSrc [I]
1120 * lpDest [O]
1121 * nMaxLen [I]
1122 *
1123 * RETURNS
1124 */
1125
1126INT WINAPI
1127Str_GetPtrW (LPCWSTR lpSrc, LPWSTR lpDest, INT nMaxLen)
1128{
1129 INT len;
1130
1131 TRACE("(%p %p %d)\n", lpSrc, lpDest, nMaxLen);
1132
1133 if (!lpDest && lpSrc)
1134 return strlenW (lpSrc);
1135
1136 if (nMaxLen == 0)
1137 return 0;
1138
1139 if (lpSrc == NULL) {
1140 lpDest[0] = L'\0';
1141 return 0;
1142 }
1143
1144 len = strlenW (lpSrc);
1145 if (len >= nMaxLen)
1146 len = nMaxLen - 1;
1147
1148 RtlMoveMemory (lpDest, lpSrc, len*sizeof(WCHAR));
1149 lpDest[len] = L'\0';
1150
1151 return len;
1152}
1153
1154
1155/**************************************************************************
1156 * Str_SetPtrW [COMCTL32.236]
1157 *
1158 * PARAMS
1159 * lpDest [O]
1160 * lpSrc [I]
1161 *
1162 * RETURNS
1163 */
1164
1165BOOL WINAPI
1166Str_SetPtrW (LPWSTR *lppDest, LPCWSTR lpSrc)
1167{
1168 TRACE("(%p %p)\n", lppDest, lpSrc);
1169
1170 if (lpSrc) {
1171 INT len = strlenW (lpSrc) + 1;
1172 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len * sizeof(WCHAR));
1173 if (!ptr)
1174 return FALSE;
1175 strcpyW (ptr, lpSrc);
1176 *lppDest = ptr;
1177 }
1178 else {
1179 if (*lppDest) {
1180 COMCTL32_Free (*lppDest);
1181 *lppDest = NULL;
1182 }
1183 }
1184
1185 return TRUE;
1186}
1187
1188
1189/**************************************************************************
1190 * Str_GetPtrWtoA [internal]
1191 *
1192 * Converts a unicode string into a multi byte string
1193 *
1194 * PARAMS
1195 * lpSrc [I] Pointer to the unicode source string
1196 * lpDest [O] Pointer to caller supplied storage for the multi byte string
1197 * nMaxLen [I] Size, in bytes, of the destination buffer
1198 *
1199 * RETURNS
1200 * Length, in bytes, of the converted string.
1201 */
1202
1203INT
1204Str_GetPtrWtoA (LPCWSTR lpSrc, LPSTR lpDest, INT nMaxLen)
1205{
1206 INT len;
1207
1208 TRACE("(%s %p %d)\n", debugstr_w(lpSrc), lpDest, nMaxLen);
1209
1210 if (!lpDest && lpSrc)
1211 return WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
1212
1213 if (nMaxLen == 0)
1214 return 0;
1215
1216 if (lpSrc == NULL) {
1217 lpDest[0] = '\0';
1218 return 0;
1219 }
1220
1221 len = WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, 0, 0, NULL, NULL);
1222 if (len >= nMaxLen)
1223 len = nMaxLen - 1;
1224
1225 WideCharToMultiByte(CP_ACP, 0, lpSrc, -1, lpDest, len, NULL, NULL);
1226 lpDest[len] = '\0';
1227
1228 return len;
1229}
1230
1231
1232/**************************************************************************
1233 * Str_SetPtrAtoW [internal]
1234 *
1235 * Converts a multi byte string to a unicode string.
1236 * If the pointer to the destination buffer is NULL a buffer is allocated.
1237 * If the destination buffer is too small to keep the converted multi byte
1238 * string the destination buffer is reallocated. If the source pointer is
1239 * NULL, the destination buffer is freed.
1240 *
1241 * PARAMS
1242 * lppDest [I/O] pointer to a pointer to the destination buffer
1243 * lpSrc [I] pointer to a multi byte string
1244 *
1245 * RETURNS
1246 * TRUE: conversion successful
1247 * FALSE: error
1248 */
1249
1250BOOL
1251Str_SetPtrAtoW (LPWSTR *lppDest, LPCSTR lpSrc)
1252{
1253 TRACE("(%p %s)\n", lppDest, lpSrc);
1254
1255 if (lpSrc) {
1256 INT len = MultiByteToWideChar(CP_ACP,0,lpSrc,-1,NULL,0);
1257 LPWSTR ptr = COMCTL32_ReAlloc (*lppDest, len*sizeof(WCHAR));
1258
1259 if (!ptr)
1260 return FALSE;
1261 MultiByteToWideChar(CP_ACP,0,lpSrc,-1,ptr,len);
1262 *lppDest = ptr;
1263 }
1264 else {
1265 if (*lppDest) {
1266 COMCTL32_Free (*lppDest);
1267 *lppDest = NULL;
1268 }
1269 }
1270
1271 return TRUE;
1272}
1273
1274
1275/**************************************************************************
1276 * The DSA-API is a set of functions to create and manipulate arrays of
1277 * fixed-size memory blocks. These arrays can store any kind of data
1278 * (strings, icons...).
1279 */
1280
1281/**************************************************************************
1282 * DSA_Create [COMCTL32.320] Creates a dynamic storage array
1283 *
1284 * PARAMS
1285 * nSize [I] size of the array elements
1286 * nGrow [I] number of elements by which the array grows when it is filled
1287 *
1288 * RETURNS
1289 * Success: pointer to an array control structure. Use this like a handle.
1290 * Failure: NULL
1291 */
1292
1293HDSA WINAPI
1294DSA_Create (INT nSize, INT nGrow)
1295{
1296 HDSA hdsa;
1297
1298 TRACE("(size=%d grow=%d)\n", nSize, nGrow);
1299
1300 hdsa = (HDSA)COMCTL32_Alloc (sizeof(DSA));
1301 if (hdsa)
1302 {
1303 hdsa->nItemCount = 0;
1304 hdsa->pData = NULL;
1305 hdsa->nMaxCount = 0;
1306 hdsa->nItemSize = nSize;
1307 hdsa->nGrow = max(1, nGrow);
1308 }
1309
1310 return hdsa;
1311}
1312
1313
1314/**************************************************************************
1315 * DSA_Destroy [COMCTL32.321] Destroys a dynamic storage array
1316 *
1317 * PARAMS
1318 * hdsa [I] pointer to the array control structure
1319 *
1320 * RETURNS
1321 * Success: TRUE
1322 * Failure: FALSE
1323 */
1324
1325BOOL WINAPI
1326DSA_Destroy (const HDSA hdsa)
1327{
1328 TRACE("(%p)\n", hdsa);
1329
1330 if (!hdsa)
1331 return FALSE;
1332
1333 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1334 return FALSE;
1335
1336 return COMCTL32_Free (hdsa);
1337}
1338
1339
1340/**************************************************************************
1341 * DSA_GetItem [COMCTL32.322]
1342 *
1343 * PARAMS
1344 * hdsa [I] pointer to the array control structure
1345 * nIndex [I] number of the Item to get
1346 * pDest [O] destination buffer. Has to be >= dwElementSize.
1347 *
1348 * RETURNS
1349 * Success: TRUE
1350 * Failure: FALSE
1351 */
1352
1353BOOL WINAPI
1354DSA_GetItem (const HDSA hdsa, INT nIndex, LPVOID pDest)
1355{
1356 LPVOID pSrc;
1357
1358 TRACE("(%p %d %p)\n", hdsa, nIndex, pDest);
1359
1360 if (!hdsa)
1361 return FALSE;
1362 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
1363 return FALSE;
1364
1365 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1366 memmove (pDest, pSrc, hdsa->nItemSize);
1367
1368 return TRUE;
1369}
1370
1371
1372/**************************************************************************
1373 * DSA_GetItemPtr [COMCTL32.323]
1374 *
1375 * Retrieves a pointer to the specified item.
1376 *
1377 * PARAMS
1378 * hdsa [I] pointer to the array control structure
1379 * nIndex [I] index of the desired item
1380 *
1381 * RETURNS
1382 * Success: pointer to an item
1383 * Failure: NULL
1384 */
1385
1386LPVOID WINAPI
1387DSA_GetItemPtr (const HDSA hdsa, INT nIndex)
1388{
1389 LPVOID pSrc;
1390
1391 TRACE("(%p %d)\n", hdsa, nIndex);
1392
1393 if (!hdsa)
1394 return NULL;
1395 if ((nIndex < 0) || (nIndex >= hdsa->nItemCount))
1396 return NULL;
1397
1398 pSrc = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1399
1400 TRACE("-- ret=%p\n", pSrc);
1401
1402 return pSrc;
1403}
1404
1405
1406/**************************************************************************
1407 * DSA_SetItem [COMCTL32.325]
1408 *
1409 * Sets the contents of an item in the array.
1410 *
1411 * PARAMS
1412 * hdsa [I] pointer to the array control structure
1413 * nIndex [I] index for the item
1414 * pSrc [I] pointer to the new item data
1415 *
1416 * RETURNS
1417 * Success: TRUE
1418 * Failure: FALSE
1419 */
1420
1421BOOL WINAPI
1422DSA_SetItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
1423{
1424 INT nSize, nNewItems;
1425 LPVOID pDest, lpTemp;
1426
1427 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
1428
1429 if ((!hdsa) || nIndex < 0)
1430 return FALSE;
1431
1432 if (hdsa->nItemCount <= nIndex) {
1433 /* within the old array */
1434 if (hdsa->nMaxCount > nIndex) {
1435 /* within the allocated space, set a new boundary */
1436 hdsa->nItemCount = nIndex + 1;
1437 }
1438 else {
1439 /* resize the block of memory */
1440 nNewItems =
1441 hdsa->nGrow * ((INT)(((nIndex + 1) - 1) / hdsa->nGrow) + 1);
1442 nSize = hdsa->nItemSize * nNewItems;
1443
1444 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1445 if (!lpTemp)
1446 return FALSE;
1447
1448 hdsa->nMaxCount = nNewItems;
1449 hdsa->nItemCount = nIndex + 1;
1450 hdsa->pData = lpTemp;
1451 }
1452 }
1453
1454 /* put the new entry in */
1455 pDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1456 TRACE("-- move dest=%p src=%p size=%d\n",
1457 pDest, pSrc, hdsa->nItemSize);
1458 memmove (pDest, pSrc, hdsa->nItemSize);
1459
1460 return TRUE;
1461}
1462
1463
1464/**************************************************************************
1465 * DSA_InsertItem [COMCTL32.324]
1466 *
1467 * PARAMS
1468 * hdsa [I] pointer to the array control structure
1469 * nIndex [I] index for the new item
1470 * pSrc [I] pointer to the element
1471 *
1472 * RETURNS
1473 * Success: position of the new item
1474 * Failure: -1
1475 */
1476
1477INT WINAPI
1478DSA_InsertItem (const HDSA hdsa, INT nIndex, LPVOID pSrc)
1479{
1480 INT nNewItems, nSize;
1481 LPVOID lpTemp, lpDest;
1482
1483 TRACE("(%p %d %p)\n", hdsa, nIndex, pSrc);
1484
1485 if ((!hdsa) || nIndex < 0)
1486 return -1;
1487
1488 /* when nIndex >= nItemCount then append */
1489 if (nIndex >= hdsa->nItemCount)
1490 nIndex = hdsa->nItemCount;
1491
1492 /* do we need to resize ? */
1493 if (hdsa->nItemCount >= hdsa->nMaxCount) {
1494 nNewItems = hdsa->nMaxCount + hdsa->nGrow;
1495 nSize = hdsa->nItemSize * nNewItems;
1496
1497 lpTemp = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1498 if (!lpTemp)
1499 return -1;
1500
1501 hdsa->nMaxCount = nNewItems;
1502 hdsa->pData = lpTemp;
1503 }
1504
1505 /* do we need to move elements ? */
1506 if (nIndex < hdsa->nItemCount) {
1507 lpTemp = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1508 lpDest = (char *) lpTemp + hdsa->nItemSize;
1509 nSize = (hdsa->nItemCount - nIndex) * hdsa->nItemSize;
1510 TRACE("-- move dest=%p src=%p size=%d\n",
1511 lpDest, lpTemp, nSize);
1512 memmove (lpDest, lpTemp, nSize);
1513 }
1514
1515 /* ok, we can put the new Item in */
1516 hdsa->nItemCount++;
1517 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1518 TRACE("-- move dest=%p src=%p size=%d\n",
1519 lpDest, pSrc, hdsa->nItemSize);
1520 memmove (lpDest, pSrc, hdsa->nItemSize);
1521
1522 return nIndex;
1523}
1524
1525
1526/**************************************************************************
1527 * DSA_DeleteItem [COMCTL32.326]
1528 *
1529 * PARAMS
1530 * hdsa [I] pointer to the array control structure
1531 * nIndex [I] index for the element to delete
1532 *
1533 * RETURNS
1534 * Success: number of the deleted element
1535 * Failure: -1
1536 */
1537
1538INT WINAPI
1539DSA_DeleteItem (const HDSA hdsa, INT nIndex)
1540{
1541 LPVOID lpDest,lpSrc;
1542 INT nSize;
1543
1544 TRACE("(%p %d)\n", hdsa, nIndex);
1545
1546 if (!hdsa)
1547 return -1;
1548 if (nIndex < 0 || nIndex >= hdsa->nItemCount)
1549 return -1;
1550
1551 /* do we need to move ? */
1552 if (nIndex < hdsa->nItemCount - 1) {
1553 lpDest = (char *) hdsa->pData + (hdsa->nItemSize * nIndex);
1554 lpSrc = (char *) lpDest + hdsa->nItemSize;
1555 nSize = hdsa->nItemSize * (hdsa->nItemCount - nIndex - 1);
1556 TRACE("-- move dest=%p src=%p size=%d\n",
1557 lpDest, lpSrc, nSize);
1558 memmove (lpDest, lpSrc, nSize);
1559 }
1560
1561 hdsa->nItemCount--;
1562
1563 /* free memory ? */
1564 if ((hdsa->nMaxCount - hdsa->nItemCount) >= hdsa->nGrow) {
1565 nSize = hdsa->nItemSize * hdsa->nItemCount;
1566
1567 lpDest = (LPVOID)COMCTL32_ReAlloc (hdsa->pData, nSize);
1568 if (!lpDest)
1569 return -1;
1570
1571 hdsa->nMaxCount = hdsa->nItemCount;
1572 hdsa->pData = lpDest;
1573 }
1574
1575 return nIndex;
1576}
1577
1578
1579/**************************************************************************
1580 * DSA_DeleteAllItems [COMCTL32.327]
1581 *
1582 * Removes all items and reinitializes the array.
1583 *
1584 * PARAMS
1585 * hdsa [I] pointer to the array control structure
1586 *
1587 * RETURNS
1588 * Success: TRUE
1589 * Failure: FALSE
1590 */
1591
1592BOOL WINAPI
1593DSA_DeleteAllItems (const HDSA hdsa)
1594{
1595 TRACE("(%p)\n", hdsa);
1596
1597 if (!hdsa)
1598 return FALSE;
1599 if (hdsa->pData && (!COMCTL32_Free (hdsa->pData)))
1600 return FALSE;
1601
1602 hdsa->nItemCount = 0;
1603 hdsa->pData = NULL;
1604 hdsa->nMaxCount = 0;
1605
1606 return TRUE;
1607}
1608
1609
1610/**************************************************************************
1611 * The DPA-API is a set of functions to create and manipulate arrays of
1612 * pointers.
1613 */
1614
1615/**************************************************************************
1616 * DPA_Create [COMCTL32.328] Creates a dynamic pointer array
1617 *
1618 * PARAMS
1619 * nGrow [I] number of items by which the array grows when it is filled
1620 *
1621 * RETURNS
1622 * Success: handle (pointer) to the pointer array.
1623 * Failure: NULL
1624 */
1625
1626HDPA WINAPI
1627DPA_Create (INT nGrow)
1628{
1629 HDPA hdpa;
1630
1631 TRACE("(%d)\n", nGrow);
1632
1633 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
1634 if (hdpa) {
1635 hdpa->nGrow = max(8, nGrow);
1636 hdpa->hHeap = COMCTL32_hHeap;
1637 hdpa->nMaxCount = hdpa->nGrow * 2;
1638 hdpa->ptrs =
1639 (LPVOID*)COMCTL32_Alloc (hdpa->nMaxCount * sizeof(LPVOID));
1640 }
1641
1642 TRACE("-- %p\n", hdpa);
1643
1644 return hdpa;
1645}
1646
1647
1648/**************************************************************************
1649 * DPA_Destroy [COMCTL32.329] Destroys a dynamic pointer array
1650 *
1651 * PARAMS
1652 * hdpa [I] handle (pointer) to the pointer array
1653 *
1654 * RETURNS
1655 * Success: TRUE
1656 * Failure: FALSE
1657 */
1658
1659BOOL WINAPI
1660DPA_Destroy (const HDPA hdpa)
1661{
1662 TRACE("(%p)\n", hdpa);
1663
1664 if (!hdpa)
1665 return FALSE;
1666
1667 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
1668 return FALSE;
1669
1670 return HeapFree (hdpa->hHeap, 0, hdpa);
1671}
1672
1673
1674/**************************************************************************
1675 * DPA_Grow [COMCTL32.330]
1676 *
1677 * Sets the growth amount.
1678 *
1679 * PARAMS
1680 * hdpa [I] handle (pointer) to the existing (source) pointer array
1681 * nGrow [I] number of items by which the array grows when it's too small
1682 *
1683 * RETURNS
1684 * Success: TRUE
1685 * Failure: FALSE
1686 */
1687
1688BOOL WINAPI
1689DPA_Grow (const HDPA hdpa, INT nGrow)
1690{
1691 TRACE("(%p %d)\n", hdpa, nGrow);
1692
1693 if (!hdpa)
1694 return FALSE;
1695
1696 hdpa->nGrow = max(8, nGrow);
1697
1698 return TRUE;
1699}
1700
1701
1702/**************************************************************************
1703 * DPA_Clone [COMCTL32.331]
1704 *
1705 * Copies a pointer array to an other one or creates a copy
1706 *
1707 * PARAMS
1708 * hdpa [I] handle (pointer) to the existing (source) pointer array
1709 * hdpaNew [O] handle (pointer) to the destination pointer array
1710 *
1711 * RETURNS
1712 * Success: pointer to the destination pointer array.
1713 * Failure: NULL
1714 *
1715 * NOTES
1716 * - If the 'hdpaNew' is a NULL-Pointer, a copy of the source pointer
1717 * array will be created and it's handle (pointer) is returned.
1718 * - If 'hdpa' is a NULL-Pointer, the original implementation crashes,
1719 * this implementation just returns NULL.
1720 */
1721
1722HDPA WINAPI
1723DPA_Clone (const HDPA hdpa, const HDPA hdpaNew)
1724{
1725 INT nNewItems, nSize;
1726 HDPA hdpaTemp;
1727
1728 if (!hdpa)
1729 return NULL;
1730
1731 TRACE("(%p %p)\n", hdpa, hdpaNew);
1732
1733 if (!hdpaNew) {
1734 /* create a new DPA */
1735 hdpaTemp = (HDPA)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1736 sizeof(DPA));
1737 hdpaTemp->hHeap = hdpa->hHeap;
1738 hdpaTemp->nGrow = hdpa->nGrow;
1739 }
1740 else
1741 hdpaTemp = hdpaNew;
1742
1743 if (hdpaTemp->ptrs) {
1744 /* remove old pointer array */
1745 HeapFree (hdpaTemp->hHeap, 0, hdpaTemp->ptrs);
1746 hdpaTemp->ptrs = NULL;
1747 hdpaTemp->nItemCount = 0;
1748 hdpaTemp->nMaxCount = 0;
1749 }
1750
1751 /* create a new pointer array */
1752 nNewItems = hdpaTemp->nGrow *
1753 ((INT)((hdpa->nItemCount - 1) / hdpaTemp->nGrow) + 1);
1754 nSize = nNewItems * sizeof(LPVOID);
1755 hdpaTemp->ptrs =
1756 (LPVOID*)HeapAlloc (hdpaTemp->hHeap, HEAP_ZERO_MEMORY, nSize);
1757 hdpaTemp->nMaxCount = nNewItems;
1758
1759 /* clone the pointer array */
1760 hdpaTemp->nItemCount = hdpa->nItemCount;
1761 memmove (hdpaTemp->ptrs, hdpa->ptrs,
1762 hdpaTemp->nItemCount * sizeof(LPVOID));
1763
1764 return hdpaTemp;
1765}
1766
1767
1768/**************************************************************************
1769 * DPA_GetPtr [COMCTL32.332]
1770 *
1771 * Retrieves a pointer from a dynamic pointer array
1772 *
1773 * PARAMS
1774 * hdpa [I] handle (pointer) to the pointer array
1775 * nIndex [I] array index of the desired pointer
1776 *
1777 * RETURNS
1778 * Success: pointer
1779 * Failure: NULL
1780 */
1781
1782LPVOID WINAPI
1783DPA_GetPtr (const HDPA hdpa, INT i)
1784{
1785 TRACE("(%p %d)\n", hdpa, i);
1786
1787 if (!hdpa)
1788 return NULL;
1789 if (!hdpa->ptrs) {
1790 WARN("no pointer array.\n");
1791 return NULL;
1792 }
1793 if ((i < 0) || (i >= hdpa->nItemCount)) {
1794 WARN("not enough pointers in array (%d vs %d).\n",i,hdpa->nItemCount);
1795 return NULL;
1796 }
1797
1798 TRACE("-- %p\n", hdpa->ptrs[i]);
1799
1800 return hdpa->ptrs[i];
1801}
1802
1803
1804/**************************************************************************
1805 * DPA_GetPtrIndex [COMCTL32.333]
1806 *
1807 * Retrieves the index of the specified pointer
1808 *
1809 * PARAMS
1810 * hdpa [I] handle (pointer) to the pointer array
1811 * p [I] pointer
1812 *
1813 * RETURNS
1814 * Success: index of the specified pointer
1815 * Failure: -1
1816 */
1817
1818INT WINAPI
1819DPA_GetPtrIndex (const HDPA hdpa, LPVOID p)
1820{
1821 INT i;
1822
1823 if (!hdpa->ptrs)
1824 return -1;
1825
1826 for (i = 0; i < hdpa->nItemCount; i++) {
1827 if (hdpa->ptrs[i] == p)
1828 return i;
1829 }
1830
1831 return -1;
1832}
1833
1834
1835/**************************************************************************
1836 * DPA_InsertPtr [COMCTL32.334]
1837 *
1838 * Inserts a pointer into a dynamic pointer array
1839 *
1840 * PARAMS
1841 * hdpa [I] handle (pointer) to the array
1842 * i [I] array index
1843 * p [I] pointer to insert
1844 *
1845 * RETURNS
1846 * Success: index of the inserted pointer
1847 * Failure: -1
1848 */
1849
1850INT WINAPI
1851DPA_InsertPtr (const HDPA hdpa, INT i, LPVOID p)
1852{
1853 INT nNewItems, nSize, nIndex = 0;
1854 LPVOID *lpTemp, *lpDest;
1855
1856 TRACE("(%p %d %p)\n", hdpa, i, p);
1857
1858 if ((!hdpa) || (i < 0))
1859 return -1;
1860
1861 if (!hdpa->ptrs) {
1862 hdpa->ptrs =
1863 (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1864 2 * hdpa->nGrow * sizeof(LPVOID));
1865 if (!hdpa->ptrs)
1866 return -1;
1867 hdpa->nMaxCount = hdpa->nGrow * 2;
1868 nIndex = 0;
1869 }
1870 else {
1871 if (hdpa->nItemCount >= hdpa->nMaxCount) {
1872 TRACE("-- resizing\n");
1873 nNewItems = hdpa->nMaxCount + hdpa->nGrow;
1874 nSize = nNewItems * sizeof(LPVOID);
1875
1876 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1877 hdpa->ptrs, nSize);
1878 if (!lpTemp)
1879 return -1;
1880 hdpa->nMaxCount = nNewItems;
1881 hdpa->ptrs = lpTemp;
1882 }
1883
1884 if (i >= hdpa->nItemCount) {
1885 nIndex = hdpa->nItemCount;
1886 TRACE("-- appending at %d\n", nIndex);
1887 }
1888 else {
1889 TRACE("-- inserting at %d\n", i);
1890 lpTemp = hdpa->ptrs + i;
1891 lpDest = lpTemp + 1;
1892 nSize = (hdpa->nItemCount - i) * sizeof(LPVOID);
1893 TRACE("-- move dest=%p src=%p size=%x\n",
1894 lpDest, lpTemp, nSize);
1895 memmove (lpDest, lpTemp, nSize);
1896 nIndex = i;
1897 }
1898 }
1899
1900 /* insert item */
1901 hdpa->nItemCount++;
1902 hdpa->ptrs[nIndex] = p;
1903
1904 return nIndex;
1905}
1906
1907
1908/**************************************************************************
1909 * DPA_SetPtr [COMCTL32.335]
1910 *
1911 * Sets a pointer in the pointer array
1912 *
1913 * PARAMS
1914 * hdpa [I] handle (pointer) to the pointer array
1915 * i [I] index of the pointer that will be set
1916 * p [I] pointer to be set
1917 *
1918 * RETURNS
1919 * Success: TRUE
1920 * Failure: FALSE
1921 */
1922
1923BOOL WINAPI
1924DPA_SetPtr (const HDPA hdpa, INT i, LPVOID p)
1925{
1926 LPVOID *lpTemp;
1927
1928 TRACE("(%p %d %p)\n", hdpa, i, p);
1929
1930 if ((!hdpa) || i < 0)
1931 return FALSE;
1932
1933 if (hdpa->nItemCount <= i) {
1934 /* within the old array */
1935 if (hdpa->nMaxCount > i) {
1936 /* within the allocated space, set a new boundary */
1937 hdpa->nItemCount = i+1;
1938 }
1939 else {
1940 /* resize the block of memory */
1941 INT nNewItems =
1942 hdpa->nGrow * ((INT)(((i+1) - 1) / hdpa->nGrow) + 1);
1943 INT nSize = nNewItems * sizeof(LPVOID);
1944
1945 lpTemp = (LPVOID*)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
1946 hdpa->ptrs, nSize);
1947 if (!lpTemp)
1948 return FALSE;
1949
1950 hdpa->nItemCount = nNewItems;
1951 hdpa->ptrs = lpTemp;
1952 }
1953 }
1954
1955 /* put the new entry in */
1956 hdpa->ptrs[i] = p;
1957
1958 return TRUE;
1959}
1960
1961
1962/**************************************************************************
1963 * DPA_DeletePtr [COMCTL32.336]
1964 *
1965 * Removes a pointer from the pointer array.
1966 *
1967 * PARAMS
1968 * hdpa [I] handle (pointer) to the pointer array
1969 * i [I] index of the pointer that will be deleted
1970 *
1971 * RETURNS
1972 * Success: deleted pointer
1973 * Failure: NULL
1974 */
1975
1976LPVOID WINAPI
1977DPA_DeletePtr (const HDPA hdpa, INT i)
1978{
1979 LPVOID *lpDest, *lpSrc, lpTemp = NULL;
1980 INT nSize;
1981
1982 TRACE("(%p %d)\n", hdpa, i);
1983
1984 if ((!hdpa) || i < 0 || i >= hdpa->nItemCount)
1985 return NULL;
1986
1987 lpTemp = hdpa->ptrs[i];
1988
1989 /* do we need to move ?*/
1990 if (i < hdpa->nItemCount - 1) {
1991 lpDest = hdpa->ptrs + i;
1992 lpSrc = lpDest + 1;
1993 nSize = (hdpa->nItemCount - i - 1) * sizeof(LPVOID);
1994 TRACE("-- move dest=%p src=%p size=%x\n",
1995 lpDest, lpSrc, nSize);
1996 memmove (lpDest, lpSrc, nSize);
1997 }
1998
1999 hdpa->nItemCount --;
2000
2001 /* free memory ?*/
2002 if ((hdpa->nMaxCount - hdpa->nItemCount) >= hdpa->nGrow) {
2003 INT nNewItems = max(hdpa->nGrow * 2, hdpa->nItemCount);
2004 nSize = nNewItems * sizeof(LPVOID);
2005 lpDest = (LPVOID)HeapReAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
2006 hdpa->ptrs, nSize);
2007 if (!lpDest)
2008 return NULL;
2009
2010 hdpa->nMaxCount = nNewItems;
2011 hdpa->ptrs = (LPVOID*)lpDest;
2012 }
2013
2014 return lpTemp;
2015}
2016
2017
2018/**************************************************************************
2019 * DPA_DeleteAllPtrs [COMCTL32.337]
2020 *
2021 * Removes all pointers and reinitializes the array.
2022 *
2023 * PARAMS
2024 * hdpa [I] handle (pointer) to the pointer array
2025 *
2026 * RETURNS
2027 * Success: TRUE
2028 * Failure: FALSE
2029 */
2030
2031BOOL WINAPI
2032DPA_DeleteAllPtrs (const HDPA hdpa)
2033{
2034 TRACE("(%p)\n", hdpa);
2035
2036 if (!hdpa)
2037 return FALSE;
2038
2039 if (hdpa->ptrs && (!HeapFree (hdpa->hHeap, 0, hdpa->ptrs)))
2040 return FALSE;
2041
2042 hdpa->nItemCount = 0;
2043 hdpa->nMaxCount = hdpa->nGrow * 2;
2044 hdpa->ptrs = (LPVOID*)HeapAlloc (hdpa->hHeap, HEAP_ZERO_MEMORY,
2045 hdpa->nMaxCount * sizeof(LPVOID));
2046
2047 return TRUE;
2048}
2049
2050
2051/**************************************************************************
2052 * DPA_QuickSort [Internal]
2053 *
2054 * Ordinary quicksort (used by DPA_Sort).
2055 *
2056 * PARAMS
2057 * lpPtrs [I] pointer to the pointer array
2058 * l [I] index of the "left border" of the partition
2059 * r [I] index of the "right border" of the partition
2060 * pfnCompare [I] pointer to the compare function
2061 * lParam [I] user defined value (3rd parameter in compare function)
2062 *
2063 * RETURNS
2064 * NONE
2065 */
2066
2067static VOID
2068DPA_QuickSort (LPVOID *lpPtrs, INT l, INT r,
2069 PFNDPACOMPARE pfnCompare, LPARAM lParam)
2070{
2071 INT m;
2072 LPVOID t;
2073
2074 TRACE("l=%i r=%i\n", l, r);
2075
2076 if (l==r) /* one element is always sorted */
2077 return;
2078 if (r<l) /* oops, got it in the wrong order */
2079 {
2080 DPA_QuickSort(lpPtrs, r, l, pfnCompare, lParam);
2081 return;
2082 }
2083 m = (l+r)/2; /* divide by two */
2084 DPA_QuickSort(lpPtrs, l, m, pfnCompare, lParam);
2085 DPA_QuickSort(lpPtrs, m+1, r, pfnCompare, lParam);
2086
2087 /* join the two sides */
2088 while( (l<=m) && (m<r) )
2089 {
2090 if(pfnCompare(lpPtrs[l],lpPtrs[m+1],lParam)>0)
2091 {
2092 t = lpPtrs[m+1];
2093 memmove(&lpPtrs[l+1],&lpPtrs[l],(m-l+1)*sizeof lpPtrs[l]);
2094 lpPtrs[l] = t;
2095
2096 m++;
2097 }
2098 l++;
2099 }
2100}
2101
2102
2103/**************************************************************************
2104 * DPA_Sort [COMCTL32.338]
2105 *
2106 * Sorts a pointer array using a user defined compare function
2107 *
2108 * PARAMS
2109 * hdpa [I] handle (pointer) to the pointer array
2110 * pfnCompare [I] pointer to the compare function
2111 * lParam [I] user defined value (3rd parameter of compare function)
2112 *
2113 * RETURNS
2114 * Success: TRUE
2115 * Failure: FALSE
2116 */
2117
2118BOOL WINAPI
2119DPA_Sort (const HDPA hdpa, PFNDPACOMPARE pfnCompare, LPARAM lParam)
2120{
2121 if (!hdpa || !pfnCompare)
2122 return FALSE;
2123
2124 TRACE("(%p %p 0x%lx)\n", hdpa, pfnCompare, lParam);
2125
2126 if ((hdpa->nItemCount > 1) && (hdpa->ptrs))
2127 DPA_QuickSort (hdpa->ptrs, 0, hdpa->nItemCount - 1,
2128 pfnCompare, lParam);
2129
2130 return TRUE;
2131}
2132
2133
2134/**************************************************************************
2135 * DPA_Search [COMCTL32.339]
2136 *
2137 * Searches a pointer array for a specified pointer
2138 *
2139 * PARAMS
2140 * hdpa [I] handle (pointer) to the pointer array
2141 * pFind [I] pointer to search for
2142 * nStart [I] start index
2143 * pfnCompare [I] pointer to the compare function
2144 * lParam [I] user defined value (3rd parameter of compare function)
2145 * uOptions [I] search options
2146 *
2147 * RETURNS
2148 * Success: index of the pointer in the array.
2149 * Failure: -1
2150 *
2151 * NOTES
2152 * Binary search taken from R.Sedgewick "Algorithms in C"!
2153 * Function is NOT tested!
2154 * If something goes wrong, blame HIM not ME! (Eric Kohl)
2155 */
2156
2157INT WINAPI
2158DPA_Search (const HDPA hdpa, LPVOID pFind, INT nStart,
2159 PFNDPACOMPARE pfnCompare, LPARAM lParam, UINT uOptions)
2160{
2161 if (!hdpa || !pfnCompare || !pFind)
2162 return -1;
2163
2164 TRACE("(%p %p %d %p 0x%08lx 0x%08x)\n",
2165 hdpa, pFind, nStart, pfnCompare, lParam, uOptions);
2166
2167 if (uOptions & DPAS_SORTED) {
2168 /* array is sorted --> use binary search */
2169 INT l, r, x, n;
2170 LPVOID *lpPtr;
2171
2172 TRACE("binary search\n");
2173
2174 l = (nStart == -1) ? 0 : nStart;
2175 r = hdpa->nItemCount - 1;
2176 lpPtr = hdpa->ptrs;
2177 while (r >= l) {
2178 x = (l + r) / 2;
2179 n = (pfnCompare)(pFind, lpPtr[x], lParam);
2180 if (n < 0)
2181 r = x - 1;
2182 else
2183 l = x + 1;
2184 if (n == 0) {
2185 TRACE("-- ret=%d\n", n);
2186 return n;
2187 }
2188 }
2189
2190 if (uOptions & DPAS_INSERTBEFORE) {
2191 TRACE("-- ret=%d\n", r);
2192 return r;
2193 }
2194
2195 if (uOptions & DPAS_INSERTAFTER) {
2196 TRACE("-- ret=%d\n", l);
2197 return l;
2198 }
2199 }
2200 else {
2201 /* array is not sorted --> use linear search */
2202 LPVOID *lpPtr;
2203 INT nIndex;
2204
2205 TRACE("linear search\n");
2206
2207 nIndex = (nStart == -1)? 0 : nStart;
2208 lpPtr = hdpa->ptrs;
2209 for (; nIndex < hdpa->nItemCount; nIndex++) {
2210 if ((pfnCompare)(pFind, lpPtr[nIndex], lParam) == 0) {
2211 TRACE("-- ret=%d\n", nIndex);
2212 return nIndex;
2213 }
2214 }
2215 }
2216
2217 TRACE("-- not found: ret=-1\n");
2218 return -1;
2219}
2220
2221
2222/**************************************************************************
2223 * DPA_CreateEx [COMCTL32.340]
2224 *
2225 * Creates a dynamic pointer array using the specified size and heap.
2226 *
2227 * PARAMS
2228 * nGrow [I] number of items by which the array grows when it is filled
2229 * hHeap [I] handle to the heap where the array is stored
2230 *
2231 * RETURNS
2232 * Success: handle (pointer) to the pointer array.
2233 * Failure: NULL
2234 */
2235
2236HDPA WINAPI
2237DPA_CreateEx (INT nGrow, HANDLE hHeap)
2238{
2239 HDPA hdpa;
2240
2241 TRACE("(%d 0x%x)\n", nGrow, hHeap);
2242
2243 if (hHeap)
2244 hdpa = (HDPA)HeapAlloc (hHeap, HEAP_ZERO_MEMORY, sizeof(DPA));
2245 else
2246 hdpa = (HDPA)COMCTL32_Alloc (sizeof(DPA));
2247
2248 if (hdpa) {
2249 hdpa->nGrow = min(8, nGrow);
2250 hdpa->hHeap = hHeap ? hHeap : COMCTL32_hHeap;
2251 hdpa->nMaxCount = hdpa->nGrow * 2;
2252 hdpa->ptrs =
2253 (LPVOID*)HeapAlloc (hHeap, HEAP_ZERO_MEMORY,
2254 hdpa->nMaxCount * sizeof(LPVOID));
2255 }
2256
2257 TRACE("-- %p\n", hdpa);
2258
2259 return hdpa;
2260}
2261
2262
2263/**************************************************************************
2264 * Notification functions
2265 */
2266
2267typedef struct tagNOTIFYDATA
2268{
2269 HWND hwndFrom;
2270 HWND hwndTo;
2271 DWORD dwParam3;
2272 DWORD dwParam4;
2273 DWORD dwParam5;
2274 DWORD dwParam6;
2275} NOTIFYDATA, *LPNOTIFYDATA;
2276
2277
2278/**************************************************************************
2279 * DoNotify [Internal]
2280 */
2281
2282static LRESULT
2283DoNotify (LPNOTIFYDATA lpNotify, UINT uCode, LPNMHDR lpHdr)
2284{
2285 NMHDR nmhdr;
2286 LPNMHDR lpNmh = NULL;
2287 UINT idFrom = 0;
2288
2289 TRACE("(0x%04x 0x%04x %d %p 0x%08lx)\n",
2290 lpNotify->hwndFrom, lpNotify->hwndTo, uCode, lpHdr,
2291 lpNotify->dwParam5);
2292
2293 if (!lpNotify->hwndTo)
2294 return 0;
2295
2296 if (lpNotify->hwndFrom == -1) {
2297 lpNmh = lpHdr;
2298 idFrom = lpHdr->idFrom;
2299 }
2300 else {
2301 if (lpNotify->hwndFrom) {
2302 HWND hwndParent = GetParent (lpNotify->hwndFrom);
2303 if (hwndParent) {
2304 hwndParent = GetWindow (lpNotify->hwndFrom, GW_OWNER);
2305 /* the following is done even if the return from above
2306 * is zero. GLA 12/2001 */
2307 idFrom = GetDlgCtrlID (lpNotify->hwndFrom);
2308 }
2309 }
2310
2311 lpNmh = (lpHdr) ? lpHdr : &nmhdr;
2312
2313 lpNmh->hwndFrom = lpNotify->hwndFrom;
2314 lpNmh->idFrom = idFrom;
2315 lpNmh->code = uCode;
2316 }
2317
2318 return SendMessageA (lpNotify->hwndTo, WM_NOTIFY, idFrom, (LPARAM)lpNmh);
2319}
2320
2321
2322/**************************************************************************
2323 * SendNotify [COMCTL32.341]
2324 *
2325 * PARAMS
2326 * hwndTo [I]
2327 * hwndFrom [I]
2328 * uCode [I]
2329 * lpHdr [I]
2330 *
2331 * RETURNS
2332 * Success: return value from notification
2333 * Failure: 0
2334 */
2335
2336LRESULT WINAPI
2337COMCTL32_SendNotify (HWND hwndTo, HWND hwndFrom,
2338 UINT uCode, LPNMHDR lpHdr)
2339{
2340 NOTIFYDATA notify;
2341
2342 TRACE("(0x%04x 0x%04x %d %p)\n",
2343 hwndTo, hwndFrom, uCode, lpHdr);
2344
2345 notify.hwndFrom = hwndFrom;
2346 notify.hwndTo = hwndTo;
2347 notify.dwParam5 = 0;
2348 notify.dwParam6 = 0;
2349
2350 return DoNotify (&notify, uCode, lpHdr);
2351}
2352
2353
2354/**************************************************************************
2355 * SendNotifyEx [COMCTL32.342]
2356 *
2357 * PARAMS
2358 * hwndFrom [I]
2359 * hwndTo [I]
2360 * uCode [I]
2361 * lpHdr [I]
2362 * dwParam5 [I]
2363 *
2364 * RETURNS
2365 * Success: return value from notification
2366 * Failure: 0
2367 */
2368
2369LRESULT WINAPI
2370COMCTL32_SendNotifyEx (HWND hwndTo, HWND hwndFrom, UINT uCode,
2371 LPNMHDR lpHdr, DWORD dwParam5)
2372{
2373 NOTIFYDATA notify;
2374 HWND hwndNotify;
2375
2376 TRACE("(0x%04x 0x%04x %d %p 0x%08lx)\n",
2377 hwndFrom, hwndTo, uCode, lpHdr, dwParam5);
2378
2379 hwndNotify = hwndTo;
2380 if (!hwndTo) {
2381 if (IsWindow (hwndFrom)) {
2382 hwndNotify = GetParent (hwndFrom);
2383 if (!hwndNotify)
2384 return 0;
2385 }
2386 }
2387
2388 notify.hwndFrom = hwndFrom;
2389 notify.hwndTo = hwndNotify;
2390 notify.dwParam5 = dwParam5;
2391 notify.dwParam6 = 0;
2392
2393 return DoNotify (&notify, uCode, lpHdr);
2394}
2395
2396
2397/**************************************************************************
2398 * StrChrA [COMCTL32.350]
2399 *
2400 */
2401
2402LPSTR WINAPI
2403COMCTL32_StrChrA (LPCSTR lpString, CHAR cChar)
2404{
2405 return strchr (lpString, cChar);
2406}
2407
2408
2409/**************************************************************************
2410 * StrStrIA [COMCTL32.355]
2411 */
2412
2413LPSTR WINAPI
2414COMCTL32_StrStrIA (LPCSTR lpStr1, LPCSTR lpStr2)
2415{
2416 INT len1, len2, i;
2417 CHAR first;
2418
2419 if (*lpStr2 == 0)
2420 return ((LPSTR)lpStr1);
2421 len1 = 0;
2422 while (lpStr1[len1] != 0) ++len1;
2423 len2 = 0;
2424 while (lpStr2[len2] != 0) ++len2;
2425 if (len2 == 0)
2426 return ((LPSTR)(lpStr1 + len1));
2427 first = tolower (*lpStr2);
2428 while (len1 >= len2) {
2429 if (tolower(*lpStr1) == first) {
2430 for (i = 1; i < len2; ++i)
2431 if (tolower (lpStr1[i]) != tolower(lpStr2[i]))
2432 break;
2433 if (i >= len2)
2434 return ((LPSTR)lpStr1);
2435 }
2436 ++lpStr1; --len1;
2437 }
2438 return (NULL);
2439}
2440
2441
2442/**************************************************************************
2443 * StrToIntA [COMCTL32.357] Converts a string to a signed integer.
2444 */
2445
2446INT WINAPI
2447COMCTL32_StrToIntA (LPSTR lpString)
2448{
2449 return atoi(lpString);
2450}
2451
2452/**************************************************************************
2453 * StrToIntW [COMCTL32.365] Converts a wide char string to a signed integer.
2454 */
2455
2456INT WINAPI
2457COMCTL32_StrToIntW (LPWSTR lpString)
2458{
2459 return _wtoi(lpString);
2460}
2461
2462
2463/**************************************************************************
2464 * DPA_EnumCallback [COMCTL32.385]
2465 *
2466 * Enumerates all items in a dynamic pointer array.
2467 *
2468 * PARAMS
2469 * hdpa [I] handle to the dynamic pointer array
2470 * enumProc [I]
2471 * lParam [I]
2472 *
2473 * RETURNS
2474 * none
2475 */
2476
2477VOID WINAPI
2478DPA_EnumCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
2479{
2480 INT i;
2481
2482 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
2483
2484 if (!hdpa)
2485 return;
2486 if (hdpa->nItemCount <= 0)
2487 return;
2488
2489 for (i = 0; i < hdpa->nItemCount; i++) {
2490 if ((enumProc)(hdpa->ptrs[i], lParam) == 0)
2491 return;
2492 }
2493
2494 return;
2495}
2496
2497
2498/**************************************************************************
2499 * DPA_DestroyCallback [COMCTL32.386]
2500 *
2501 * Enumerates all items in a dynamic pointer array and destroys it.
2502 *
2503 * PARAMS
2504 * hdpa [I] handle to the dynamic pointer array
2505 * enumProc [I]
2506 * lParam [I]
2507 *
2508 * RETURNS
2509 * Success: TRUE
2510 * Failure: FALSE
2511 */
2512
2513BOOL WINAPI
2514DPA_DestroyCallback (const HDPA hdpa, DPAENUMPROC enumProc, LPARAM lParam)
2515{
2516 TRACE("(%p %p %08lx)\n", hdpa, enumProc, lParam);
2517
2518 DPA_EnumCallback (hdpa, enumProc, lParam);
2519
2520 return DPA_Destroy (hdpa);
2521}
2522
2523
2524/**************************************************************************
2525 * DSA_EnumCallback [COMCTL32.387]
2526 *
2527 * Enumerates all items in a dynamic storage array.
2528 *
2529 * PARAMS
2530 * hdsa [I] handle to the dynamic storage array
2531 * enumProc [I]
2532 * lParam [I]
2533 *
2534 * RETURNS
2535 * none
2536 */
2537
2538VOID WINAPI
2539DSA_EnumCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
2540{
2541 INT i;
2542
2543 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
2544
2545 if (!hdsa)
2546 return;
2547 if (hdsa->nItemCount <= 0)
2548 return;
2549
2550 for (i = 0; i < hdsa->nItemCount; i++) {
2551 LPVOID lpItem = DSA_GetItemPtr (hdsa, i);
2552 if ((enumProc)(lpItem, lParam) == 0)
2553 return;
2554 }
2555
2556 return;
2557}
2558
2559
2560/**************************************************************************
2561 * DSA_DestroyCallback [COMCTL32.388]
2562 *
2563 * Enumerates all items in a dynamic storage array and destroys it.
2564 *
2565 * PARAMS
2566 * hdsa [I] handle to the dynamic storage array
2567 * enumProc [I]
2568 * lParam [I]
2569 *
2570 * RETURNS
2571 * Success: TRUE
2572 * Failure: FALSE
2573 */
2574
2575BOOL WINAPI
2576DSA_DestroyCallback (const HDSA hdsa, DSAENUMPROC enumProc, LPARAM lParam)
2577{
2578 TRACE("(%p %p %08lx)\n", hdsa, enumProc, lParam);
2579
2580 DSA_EnumCallback (hdsa, enumProc, lParam);
2581
2582 return DSA_Destroy (hdsa);
2583}
2584
2585/**************************************************************************
2586 * StrCSpnA [COMCTL32.356]
2587 *
2588 */
2589INT WINAPI COMCTL32_StrCSpnA( LPCSTR lpStr, LPCSTR lpSet) {
2590 return strcspn(lpStr, lpSet);
2591}
2592
2593/**************************************************************************
2594 * StrChrW [COMCTL32.358]
2595 *
2596 */
2597LPWSTR WINAPI COMCTL32_StrChrW( LPCWSTR lpStart, WORD wMatch) {
2598 return strchrW(lpStart, wMatch);
2599}
2600
2601/**************************************************************************
2602 * StrCmpNA [COMCTL32.352]
2603 *
2604 */
2605INT WINAPI COMCTL32_StrCmpNA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
2606 return strncmp(lpStr1, lpStr2, nChar);
2607}
2608
2609/**************************************************************************
2610 * StrCmpNIA [COMCTL32.353]
2611 *
2612 */
2613INT WINAPI COMCTL32_StrCmpNIA( LPCSTR lpStr1, LPCSTR lpStr2, int nChar) {
2614 return strncasecmp(lpStr1, lpStr2, nChar);
2615}
2616
2617/**************************************************************************
2618 * StrCmpNW [COMCTL32.360]
2619 *
2620 */
2621INT WINAPI COMCTL32_StrCmpNW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
2622 return strncmpW(lpStr1, lpStr2, nChar);
2623}
2624
2625/**************************************************************************
2626 * StrCmpNIW [COMCTL32.361]
2627 *
2628 */
2629INT WINAPI COMCTL32_StrCmpNIW( LPCWSTR lpStr1, LPCWSTR lpStr2, int nChar) {
2630 FIXME("(%s, %s, %i): stub\n", debugstr_w(lpStr1), debugstr_w(lpStr2), nChar);
2631 return 0;
2632}
2633
2634/**************************************************************************
2635 * StrRChrA [COMCTL32.351]
2636 *
2637 */
2638LPSTR WINAPI COMCTL32_StrRChrA( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
2639{
2640 LPCSTR lpGotIt = NULL;
2641 BOOL dbcs = IsDBCSLeadByte( LOBYTE(wMatch) );
2642
2643 TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
2644
2645 if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
2646
2647 for(; lpStart < lpEnd; lpStart = CharNextA(lpStart))
2648 {
2649 if (*lpStart != LOBYTE(wMatch)) continue;
2650 if (dbcs && lpStart[1] != HIBYTE(wMatch)) continue;
2651 lpGotIt = lpStart;
2652 }
2653 return (LPSTR)lpGotIt;
2654}
2655
2656
2657/**************************************************************************
2658 * StrRChrW [COMCTL32.359]
2659 *
2660 */
2661LPWSTR WINAPI COMCTL32_StrRChrW( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch)
2662{
2663 LPCWSTR lpGotIt = NULL;
2664
2665 TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
2666 if (!lpEnd) lpEnd = lpStart + strlenW(lpStart);
2667
2668 for(; lpStart < lpEnd; lpStart = CharNextW(lpStart))
2669 if (*lpStart == wMatch) lpGotIt = lpStart;
2670
2671 return (LPWSTR)lpGotIt;
2672}
2673
2674
2675/**************************************************************************
2676 * StrStrA [COMCTL32.354]
2677 *
2678 */
2679LPSTR WINAPI COMCTL32_StrStrA( LPCSTR lpFirst, LPCSTR lpSrch) {
2680 return strstr(lpFirst, lpSrch);
2681}
2682
2683/**************************************************************************
2684 * StrStrW [COMCTL32.362]
2685 *
2686 */
2687LPWSTR WINAPI COMCTL32_StrStrW( LPCWSTR lpFirst, LPCWSTR lpSrch) {
2688 return strstrW(lpFirst, lpSrch);
2689}
2690
2691/**************************************************************************
2692 * StrSpnW [COMCTL32.364]
2693 *
2694 */
2695INT WINAPI COMCTL32_StrSpnW( LPWSTR lpStr, LPWSTR lpSet) {
2696 LPWSTR lpLoop = lpStr;
2697
2698 /* validate ptr */
2699 if ((lpStr == 0) || (lpSet == 0)) return 0;
2700
2701/* while(*lpLoop) { if lpLoop++; } */
2702
2703 for(; (*lpLoop != 0); lpLoop++)
2704 if( strchrW(lpSet, *(WORD*)lpLoop))
2705 return (INT)(lpLoop-lpStr);
2706
2707 return (INT)(lpLoop-lpStr);
2708}
2709
2710/**************************************************************************
2711 * @ [COMCTL32.410]
2712 *
2713 * FIXME: What's this supposed to do?
2714 * Parameter 1 is an HWND, you're on your own for the rest.
2715 */
2716
2717BOOL WINAPI COMCTL32_410( HWND hw, DWORD b, DWORD c, DWORD d) {
2718
2719 FIXME("(%x, %lx, %lx, %lx): stub!\n", hw, b, c, d);
2720
2721 return TRUE;
2722}
2723
2724/**************************************************************************
2725 * @ [COMCTL32.411]
2726 *
2727 * FIXME: What's this supposed to do?
2728 * Parameter 1 is an HWND, you're on your own for the rest.
2729 */
2730
2731BOOL WINAPI COMCTL32_411( HWND hw, DWORD b, DWORD c) {
2732
2733 FIXME("(%x, %lx, %lx): stub!\n", hw, b, c);
2734
2735 return TRUE;
2736}
2737
2738/**************************************************************************
2739 * @ [COMCTL32.412]
2740 *
2741 * FIXME: What's this supposed to do?
2742 * Parameter 1 is an HWND, you're on your own for the rest.
2743 */
2744
2745BOOL WINAPI COMCTL32_412( HWND hwnd, DWORD b, DWORD c)
2746{
2747 FIXME("(%x, %lx, %lx): stub!\n", hwnd, b, c);
2748
2749 if (IsWindow (hwnd) == FALSE)
2750 return FALSE;
2751
2752 if (b == 0)
2753 return FALSE;
2754
2755
2756 return TRUE;
2757}
2758
2759/**************************************************************************
2760 * @ [COMCTL32.413]
2761 *
2762 * FIXME: What's this supposed to do?
2763 * Parameter 1 is an HWND, you're on your own for the rest.
2764 */
2765
2766BOOL WINAPI COMCTL32_413( HWND hw, DWORD b, DWORD c, DWORD d) {
2767
2768 FIXME("(%x, %lx, %lx, %lx): stub!\n", hw, b, c, d);
2769
2770 return TRUE;
2771}
2772
2773
2774/**************************************************************************
2775 * @ [COMCTL32.415]
2776 *
2777 * FIXME: What's this supposed to do?
2778 * Parameter 1 is an HWND, you're on your own for the rest.
2779 */
2780
2781BOOL WINAPI COMCTL32_415( HWND hwnd, DWORD b, DWORD c, DWORD d, DWORD e)
2782{
2783
2784 FIXME("(%x, %lx, %lx, %lx, %lx): stub!\n", hwnd, b, c, d, e);
2785
2786 return TRUE;
2787}
2788
2789/**************************************************************************
2790 * @ [COMCTL32.419]
2791 *
2792 * FIXME: What's this supposed to do?
2793 */
2794
2795BOOL WINAPI COMCTL32_419( DWORD a, DWORD b, DWORD c, DWORD d)
2796{
2797
2798 FIXME("(%lx, %lx, %lx, %lx): stub!\n", a, b, c, d);
2799
2800 return TRUE;
2801}
2802
Note: See TracBrowser for help on using the repository browser.