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

Last change on this file since 7502 was 7502, checked in by phaller, 24 years ago

Fixed out-of-scope FIXME,TRACE,WARN macros

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