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

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

removed TRACE/WARN macro redefinition

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