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

Last change on this file since 7029 was 6810, checked in by sandervl, 24 years ago

wine update

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