Declaration, implemention and test for BuildTrusteeWithSid.
[wine] / dlls / comctl32 / commctrl.c
1 /*
2  * Common controls functions
3  *
4  * Copyright 1997 Dimitrie O. Paun
5  * Copyright 1998,2000 Eric Kohl
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * NOTES
22  * 
23  * This code was audited for completeness against the documented features
24  * of Comctl32.dll version 6.0 on Oct. 21, 2002, by Christian Neumair.
25  *
26  * Unless otherwise noted, we believe this code to be complete, as per
27  * the specification mentioned above.
28  * If you discover missing features, or bugs, please note them below.
29  *
30  * TODO
31  *   -- implement GetMUILanguage + InitMUILanguage
32  *   -- LibMain => DLLMain ("DLLMain takes over the functionality of both the
33  *                           LibMain and the WEP function.", MSDN)
34  *   -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW
35  *   -- FIXMEs + BUGS (search for them)
36  *
37  * Control Classes
38  *   -- ICC_ANIMATE_CLASS
39  *   -- ICC_BAR_CLASSES
40  *   -- ICC_COOL_CLASSES
41  *   -- ICC_DATE_CLASSES
42  *   -- ICC_HOTKEY_CLASS
43  *   -- ICC_INTERNET_CLASSES
44  *   -- ICC_LINK_CLASS (not yet implemented)
45  *   -- ICC_LISTVIEW_CLASSES
46  *   -- ICC_NATIVEFNTCTL_CLASS
47  *   -- ICC_PAGESCROLLER_CLASS
48  *   -- ICC_PROGRESS_CLASS
49  *   -- ICC_STANDARD_CLASSES (not yet implemented)
50  *   -- ICC_TAB_CLASSES
51  *   -- ICC_TREEVIEW_CLASSES
52  *   -- ICC_UPDOWN_CLASS
53  *   -- ICC_USEREX_CLASSES
54  *   -- ICC_WIN95_CLASSES
55  */
56
57 #include <stdarg.h>
58 #include <string.h>
59 #include <stdlib.h>
60
61 #include "windef.h"
62 #include "winbase.h"
63 #include "wingdi.h"
64 #include "winuser.h"
65 #include "winnls.h"
66 #include "commctrl.h"
67 #include "winerror.h"
68 #include "winreg.h"
69 #define NO_SHLWAPI_STREAM
70 #include "shlwapi.h"
71 #include "comctl32.h"
72 #include "wine/debug.h"
73
74 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
75
76 extern void ANIMATE_Register(void);
77 extern void ANIMATE_Unregister(void);
78 extern void COMBOEX_Register(void);
79 extern void COMBOEX_Unregister(void);
80 extern void DATETIME_Register(void);
81 extern void DATETIME_Unregister(void);
82 extern void FLATSB_Register(void);
83 extern void FLATSB_Unregister(void);
84 extern void HEADER_Register(void);
85 extern void HEADER_Unregister(void);
86 extern void HOTKEY_Register(void);
87 extern void HOTKEY_Unregister(void);
88 extern void IPADDRESS_Register(void);
89 extern void IPADDRESS_Unregister(void);
90 extern void LISTVIEW_Register(void);
91 extern void LISTVIEW_Unregister(void);
92 extern void MONTHCAL_Register(void);
93 extern void MONTHCAL_Unregister(void);
94 extern void NATIVEFONT_Register(void);
95 extern void NATIVEFONT_Unregister(void);
96 extern void PAGER_Register(void);
97 extern void PAGER_Unregister(void);
98 extern void PROGRESS_Register(void);
99 extern void PROGRESS_Unregister(void);
100 extern void REBAR_Register(void);
101 extern void REBAR_Unregister(void);
102 extern void STATUS_Register(void);
103 extern void STATUS_Unregister(void);
104 extern void SYSLINK_Register(void);
105 extern void SYSLINK_Unregister(void);
106 extern void TAB_Register(void);
107 extern void TAB_Unregister(void);
108 extern void TOOLBAR_Register(void);
109 extern void TOOLBAR_Unregister(void);
110 extern void TOOLTIPS_Register(void);
111 extern void TOOLTIPS_Unregister(void);
112 extern void TRACKBAR_Register(void);
113 extern void TRACKBAR_Unregister(void);
114 extern void TREEVIEW_Register(void);
115 extern void TREEVIEW_Unregister(void);
116 extern void UPDOWN_Register(void);
117 extern void UPDOWN_Unregister(void);
118
119
120 LPSTR    COMCTL32_aSubclass = NULL;
121 HMODULE COMCTL32_hModule = 0;
122 LANGID  COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
123 HBRUSH  COMCTL32_hPattern55AABrush = NULL;
124 COMCTL32_SysColor  comctl32_color;
125
126 static HBITMAP COMCTL32_hPattern55AABitmap = NULL;
127
128 static const WORD wPattern55AA[] =
129 {
130     0x5555, 0xaaaa, 0x5555, 0xaaaa,
131     0x5555, 0xaaaa, 0x5555, 0xaaaa
132 };
133
134
135 /***********************************************************************
136  * DllMain [Internal]
137  *
138  * Initializes the internal 'COMCTL32.DLL'.
139  *
140  * PARAMS
141  *     hinstDLL    [I] handle to the 'dlls' instance
142  *     fdwReason   [I]
143  *     lpvReserved [I] reserverd, must be NULL
144  *
145  * RETURNS
146  *     Success: TRUE
147  *     Failure: FALSE
148  */
149
150 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
151 {
152     TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
153
154     switch (fdwReason) {
155         case DLL_PROCESS_ATTACH:
156             DisableThreadLibraryCalls(hinstDLL);
157
158             COMCTL32_hModule = (HMODULE)hinstDLL;
159
160             /* add global subclassing atom (used by 'tooltip' and 'updown') */
161             COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
162             TRACE("Subclassing atom added: %p\n", COMCTL32_aSubclass);
163
164             /* create local pattern brush */
165             COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
166             COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
167
168             /* Get all the colors at DLL load */
169             COMCTL32_RefreshSysColors();
170
171             /* register all Win95 common control classes */
172             ANIMATE_Register ();
173             FLATSB_Register ();
174             HEADER_Register ();
175             HOTKEY_Register ();
176             LISTVIEW_Register ();
177             PROGRESS_Register ();
178             STATUS_Register ();
179             SYSLINK_Register ();
180             TAB_Register ();
181             TOOLBAR_Register ();
182             TOOLTIPS_Register ();
183             TRACKBAR_Register ();
184             TREEVIEW_Register ();
185             UPDOWN_Register ();
186             break;
187
188         case DLL_PROCESS_DETACH:
189             /* unregister all common control classes */
190             ANIMATE_Unregister ();
191             COMBOEX_Unregister ();
192             DATETIME_Unregister ();
193             FLATSB_Unregister ();
194             HEADER_Unregister ();
195             HOTKEY_Unregister ();
196             IPADDRESS_Unregister ();
197             LISTVIEW_Unregister ();
198             MONTHCAL_Unregister ();
199             NATIVEFONT_Unregister ();
200             PAGER_Unregister ();
201             PROGRESS_Unregister ();
202             REBAR_Unregister ();
203             STATUS_Unregister ();
204             SYSLINK_Unregister ();
205             TAB_Unregister ();
206             TOOLBAR_Unregister ();
207             TOOLTIPS_Unregister ();
208             TRACKBAR_Unregister ();
209             TREEVIEW_Unregister ();
210             UPDOWN_Unregister ();
211
212             /* delete local pattern brush */
213             DeleteObject (COMCTL32_hPattern55AABrush);
214             COMCTL32_hPattern55AABrush = NULL;
215             DeleteObject (COMCTL32_hPattern55AABitmap);
216             COMCTL32_hPattern55AABitmap = NULL;
217
218             /* delete global subclassing atom */
219             GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
220             TRACE("Subclassing atom deleted: %p\n", COMCTL32_aSubclass);
221             COMCTL32_aSubclass = NULL;
222             break;
223     }
224
225     return TRUE;
226 }
227
228
229 /***********************************************************************
230  * MenuHelp [COMCTL32.2]
231  *
232  * Handles the setting of status bar help messages when the user
233  * selects menu items.
234  *
235  * PARAMS
236  *     uMsg       [I] message (WM_MENUSELECT) (see NOTES)
237  *     wParam     [I] wParam of the message uMsg
238  *     lParam     [I] lParam of the message uMsg
239  *     hMainMenu  [I] handle to the application's main menu
240  *     hInst      [I] handle to the module that contains string resources
241  *     hwndStatus [I] handle to the status bar window
242  *     lpwIDs     [I] pointer to an array of integers (see NOTES)
243  *
244  * RETURNS
245  *     No return value
246  *
247  * NOTES
248  *     The official documentation is incomplete!
249  *     This is the correct documentation:
250  *
251  *     uMsg:
252  *     MenuHelp() does NOT handle WM_COMMAND messages! It only handles
253  *     WM_MENUSELECT messages.
254  *
255  *     lpwIDs:
256  *     (will be written ...)
257  */
258
259 VOID WINAPI
260 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
261           HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
262 {
263     UINT uMenuID = 0;
264
265     if (!IsWindow (hwndStatus))
266         return;
267
268     switch (uMsg) {
269         case WM_MENUSELECT:
270             TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
271                    wParam, lParam);
272
273             if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
274                 /* menu was closed */
275                 TRACE("menu was closed!\n");
276                 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
277             }
278             else {
279                 /* menu item was selected */
280                 if (HIWORD(wParam) & MF_POPUP)
281                     uMenuID = (UINT)*(lpwIDs+1);
282                 else
283                     uMenuID = (UINT)LOWORD(wParam);
284                 TRACE("uMenuID = %u\n", uMenuID);
285
286                 if (uMenuID) {
287                     CHAR szText[256];
288
289                     if (!LoadStringA (hInst, uMenuID, szText, 256))
290                         szText[0] = '\0';
291
292                     SendMessageA (hwndStatus, SB_SETTEXTA,
293                                     255 | SBT_NOBORDERS, (LPARAM)szText);
294                     SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
295                 }
296             }
297             break;
298
299         case WM_COMMAND :
300             TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
301                    wParam, lParam);
302             /* WM_COMMAND is not invalid since it is documented
303              * in the windows api reference. So don't output
304              * any FIXME for WM_COMMAND
305              */
306             WARN("We don't care about the WM_COMMAND\n");
307             break;
308
309         default:
310             FIXME("Invalid Message 0x%x!\n", uMsg);
311             break;
312     }
313 }
314
315
316 /***********************************************************************
317  * ShowHideMenuCtl [COMCTL32.3]
318  *
319  * Shows or hides controls and updates the corresponding menu item.
320  *
321  * PARAMS
322  *     hwnd   [I] handle to the client window.
323  *     uFlags [I] menu command id.
324  *     lpInfo [I] pointer to an array of integers. (See NOTES.)
325  *
326  * RETURNS
327  *     Success: TRUE
328  *     Failure: FALSE
329  *
330  * NOTES
331  *     The official documentation is incomplete!
332  *     This is the correct documentation:
333  *
334  *     hwnd
335  *     Handle to the window that contains the menu and controls.
336  *
337  *     uFlags
338  *     Identifier of the menu item to receive or loose a check mark.
339  *
340  *     lpInfo
341  *     The array of integers contains pairs of values. BOTH values of
342  *     the first pair must be the handles to the application's main menu.
343  *     Each subsequent pair consists of a menu id and control id.
344  */
345
346 BOOL WINAPI
347 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
348 {
349     LPINT lpMenuId;
350
351     TRACE("%p, %x, %p\n", hwnd, uFlags, lpInfo);
352
353     if (lpInfo == NULL)
354         return FALSE;
355
356     if (!(lpInfo[0]) || !(lpInfo[1]))
357         return FALSE;
358
359     /* search for control */
360     lpMenuId = &lpInfo[2];
361     while (*lpMenuId != uFlags)
362         lpMenuId += 2;
363
364     if (GetMenuState ((HMENU)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
365         /* uncheck menu item */
366         CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
367
368         /* hide control */
369         lpMenuId++;
370         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
371                         SWP_HIDEWINDOW);
372     }
373     else {
374         /* check menu item */
375         CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
376
377         /* show control */
378         lpMenuId++;
379         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
380                         SWP_SHOWWINDOW);
381     }
382
383     return TRUE;
384 }
385
386
387 /***********************************************************************
388  * GetEffectiveClientRect [COMCTL32.4]
389  *
390  * Calculates the coordinates of a rectangle in the client area.
391  *
392  * PARAMS
393  *     hwnd   [I] handle to the client window.
394  *     lpRect [O] pointer to the rectangle of the client window
395  *     lpInfo [I] pointer to an array of integers (see NOTES)
396  *
397  * RETURNS
398  *     No return value.
399  *
400  * NOTES
401  *     The official documentation is incomplete!
402  *     This is the correct documentation:
403  *
404  *     lpInfo
405  *     (will be written ...)
406  */
407
408 VOID WINAPI
409 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
410 {
411     RECT rcCtrl;
412     INT  *lpRun;
413     HWND hwndCtrl;
414
415     TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
416            (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
417
418     GetClientRect (hwnd, lpRect);
419     lpRun = lpInfo;
420
421     do {
422         lpRun += 2;
423         if (*lpRun == 0)
424             return;
425         lpRun++;
426         hwndCtrl = GetDlgItem (hwnd, *lpRun);
427         if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
428             TRACE("control id 0x%x\n", *lpRun);
429             GetWindowRect (hwndCtrl, &rcCtrl);
430             MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2);
431             SubtractRect (lpRect, lpRect, &rcCtrl);
432         }
433         lpRun++;
434     } while (*lpRun);
435 }
436
437
438 /***********************************************************************
439  * DrawStatusTextW [COMCTL32.@]
440  *
441  * Draws text with borders, like in a status bar.
442  *
443  * PARAMS
444  *     hdc   [I] handle to the window's display context
445  *     lprc  [I] pointer to a rectangle
446  *     text  [I] pointer to the text
447  *     style [I] drawing style
448  *
449  * RETURNS
450  *     No return value.
451  *
452  * NOTES
453  *     The style variable can have one of the following values:
454  *     (will be written ...)
455  */
456
457 void WINAPI DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
458 {
459     RECT r = *lprc;
460     UINT border = BDR_SUNKENOUTER;
461
462     if (style & SBT_POPOUT)
463         border = BDR_RAISEDOUTER;
464     else if (style & SBT_NOBORDERS)
465         border = 0;
466
467     DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
468
469     /* now draw text */
470     if (text) {
471         int oldbkmode = SetBkMode (hdc, TRANSPARENT);
472         UINT align = DT_LEFT;
473         if (*text == L'\t') {
474             text++;
475             align = DT_CENTER;
476             if (*text == L'\t') {
477                 text++;
478                 align = DT_RIGHT;
479             }
480         }
481         r.left += 3;
482         if (style & SBT_RTLREADING)
483             FIXME("Unsupported RTL style!\n");
484         DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE);
485         SetBkMode(hdc, oldbkmode);
486     }
487 }
488
489
490 /***********************************************************************
491  * DrawStatusText  [COMCTL32.@]
492  * DrawStatusTextA [COMCTL32.5]
493  *
494  * Draws text with borders, like in a status bar.
495  *
496  * PARAMS
497  *     hdc   [I] handle to the window's display context
498  *     lprc  [I] pointer to a rectangle
499  *     text  [I] pointer to the text
500  *     style [I] drawing style
501  *
502  * RETURNS
503  *     No return value.
504  */
505
506 void WINAPI DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
507 {
508     INT len;
509     LPWSTR textW = NULL;
510
511     if ( text ) {
512         if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
513             if ( (textW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )) )
514                 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
515         }
516     }
517     DrawStatusTextW( hdc, lprc, textW, style );
518     HeapFree( GetProcessHeap(), 0, textW );
519 }
520
521
522 /***********************************************************************
523  * CreateStatusWindow  [COMCTL32.@]
524  * CreateStatusWindowA [COMCTL32.6]
525  *
526  * Creates a status bar
527  *
528  * PARAMS
529  *     style  [I] window style
530  *     text   [I] pointer to the window text
531  *     parent [I] handle to the parent window
532  *     wid    [I] control id of the status bar
533  *
534  * RETURNS
535  *     Success: handle to the status window
536  *     Failure: 0
537  */
538
539 HWND WINAPI
540 CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
541 {
542     return CreateWindowA(STATUSCLASSNAMEA, text, style,
543                            CW_USEDEFAULT, CW_USEDEFAULT,
544                            CW_USEDEFAULT, CW_USEDEFAULT,
545                            parent, (HMENU)wid, 0, 0);
546 }
547
548
549 /***********************************************************************
550  * CreateStatusWindowW [COMCTL32.@]
551  *
552  * Creates a status bar control
553  *
554  * PARAMS
555  *     style  [I] window style
556  *     text   [I] pointer to the window text
557  *     parent [I] handle to the parent window
558  *     wid    [I] control id of the status bar
559  *
560  * RETURNS
561  *     Success: handle to the status window
562  *     Failure: 0
563  */
564
565 HWND WINAPI
566 CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
567 {
568     return CreateWindowW(STATUSCLASSNAMEW, text, style,
569                            CW_USEDEFAULT, CW_USEDEFAULT,
570                            CW_USEDEFAULT, CW_USEDEFAULT,
571                            parent, (HMENU)wid, 0, 0);
572 }
573
574
575 /***********************************************************************
576  * CreateUpDownControl [COMCTL32.16]
577  *
578  * Creates an up-down control
579  *
580  * PARAMS
581  *     style  [I] window styles
582  *     x      [I] horizontal position of the control
583  *     y      [I] vertical position of the control
584  *     cx     [I] with of the control
585  *     cy     [I] height of the control
586  *     parent [I] handle to the parent window
587  *     id     [I] the control's identifier
588  *     inst   [I] handle to the application's module instance
589  *     buddy  [I] handle to the buddy window, can be NULL
590  *     maxVal [I] upper limit of the control
591  *     minVal [I] lower limit of the control
592  *     curVal [I] current value of the control
593  *
594  * RETURNS
595  *     Success: handle to the updown control
596  *     Failure: 0
597  */
598
599 HWND WINAPI
600 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
601                      HWND parent, INT id, HINSTANCE inst,
602                      HWND buddy, INT maxVal, INT minVal, INT curVal)
603 {
604     HWND hUD =
605         CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
606                          parent, (HMENU)id, inst, 0);
607     if (hUD) {
608         SendMessageA (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
609         SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
610         SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
611     }
612
613     return hUD;
614 }
615
616
617 /***********************************************************************
618  * InitCommonControls [COMCTL32.17]
619  *
620  * Registers the common controls.
621  *
622  * PARAMS
623  *     No parameters.
624  *
625  * RETURNS
626  *     No return values.
627  *
628  * NOTES
629  *     This function is just a dummy.
630  *     The Win95 controls are registered at the DLL's initialization.
631  *     To register other controls InitCommonControlsEx() must be used.
632  */
633
634 VOID WINAPI
635 InitCommonControls (void)
636 {
637 }
638
639
640 /***********************************************************************
641  * InitCommonControlsEx [COMCTL32.@]
642  *
643  * Registers the common controls.
644  *
645  * PARAMS
646  *     lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
647  *
648  * RETURNS
649  *     Success: TRUE
650  *     Failure: FALSE
651  *
652  * NOTES
653  *     Only the additional common controls are registered by this function.
654  *     The Win95 controls are registered at the DLL's initialization.
655  *
656  * FIXME
657  *     implement the following control classes:
658  *       ICC_LINK_CLASS
659  *       ICC_STANDARD_CLASSES
660  */
661
662 BOOL WINAPI
663 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
664 {
665     INT cCount;
666     DWORD dwMask;
667
668     if (!lpInitCtrls)
669         return FALSE;
670     if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
671         return FALSE;
672
673     TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
674
675     for (cCount = 0; cCount < 32; cCount++) {
676         dwMask = 1 << cCount;
677         if (!(lpInitCtrls->dwICC & dwMask))
678             continue;
679
680         switch (lpInitCtrls->dwICC & dwMask) {
681             /* dummy initialization */
682             case ICC_ANIMATE_CLASS:
683             case ICC_BAR_CLASSES:
684             case ICC_LISTVIEW_CLASSES:
685             case ICC_TREEVIEW_CLASSES:
686             case ICC_TAB_CLASSES:
687             case ICC_UPDOWN_CLASS:
688             case ICC_PROGRESS_CLASS:
689             case ICC_HOTKEY_CLASS:
690                 break;
691
692             /* advanced classes - not included in Win95 */
693             case ICC_DATE_CLASSES:
694                 MONTHCAL_Register ();
695                 DATETIME_Register ();
696                 break;
697
698             case ICC_USEREX_CLASSES:
699                 COMBOEX_Register ();
700                 break;
701
702             case ICC_COOL_CLASSES:
703                 REBAR_Register ();
704                 break;
705
706             case ICC_INTERNET_CLASSES:
707                 IPADDRESS_Register ();
708                 break;
709
710             case ICC_PAGESCROLLER_CLASS:
711                 PAGER_Register ();
712                 break;
713
714             case ICC_NATIVEFNTCTL_CLASS:
715                 NATIVEFONT_Register ();
716                 break;
717
718             case ICC_LINK_CLASS:
719                 SYSLINK_Register ();
720                 break;
721
722             default:
723                 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
724                 break;
725         }
726     }
727
728     return TRUE;
729 }
730
731
732 /***********************************************************************
733  * CreateToolbarEx [COMCTL32.@]
734  *
735  * Creates a toolbar window.
736  *
737  * PARAMS
738  *     hwnd
739  *     style
740  *     wID
741  *     nBitmaps
742  *     hBMInst
743  *     wBMID
744  *     lpButtons
745  *     iNumButtons
746  *     dxButton
747  *     dyButton
748  *     dxBitmap
749  *     dyBitmap
750  *     uStructSize
751  *
752  * RETURNS
753  *     Success: handle to the tool bar control
754  *     Failure: 0
755  */
756
757 HWND WINAPI
758 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
759                  HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
760                  INT iNumButtons, INT dxButton, INT dyButton,
761                  INT dxBitmap, INT dyBitmap, UINT uStructSize)
762 {
763     HWND hwndTB;
764
765     hwndTB =
766         CreateWindowExA(0, TOOLBARCLASSNAMEA, NULL, style|WS_CHILD, 0,0,100,30,
767                         hwnd, (HMENU)wID, COMCTL32_hModule, NULL);
768     if(hwndTB) {
769         TBADDBITMAP tbab;
770
771         SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
772                         (WPARAM)uStructSize, 0);
773
774        /* set bitmap and button size */
775        /*If CreateToolbarEx receives 0, windows sets default values*/
776        if (dxBitmap <= 0)
777            dxBitmap = 16;
778        if (dyBitmap <= 0)
779            dyBitmap = 15;
780        SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
781                        MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
782
783        if (dxButton <= 0)
784            dxButton = 24;
785        if (dyButton <= 0)
786            dyButton = 22;
787        SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
788                        MAKELPARAM((WORD)dxButton, (WORD)dyButton));
789
790
791         /* add bitmaps */
792         if (nBitmaps > 0)
793         {
794         tbab.hInst = hBMInst;
795         tbab.nID   = wBMID;
796
797         SendMessageA (hwndTB, TB_ADDBITMAP,
798                         (WPARAM)nBitmaps, (LPARAM)&tbab);
799         }
800         /* add buttons */
801         if(iNumButtons > 0)
802         SendMessageA (hwndTB, TB_ADDBUTTONSA,
803                         (WPARAM)iNumButtons, (LPARAM)lpButtons);
804     }
805
806     return hwndTB;
807 }
808
809
810 /***********************************************************************
811  * CreateMappedBitmap [COMCTL32.8]
812  *
813  * Loads a bitmap resource using a colour map.
814  *
815  * PARAMS
816  *     hInstance  [I] Handle to the module containing the bitmap.
817  *     idBitmap   [I] The bitmap resource ID.
818  *     wFlags     [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
819  *     lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
820  *     iNumMaps   [I] Number of COLORMAP's pointed to by lpColorMap.
821  *
822  * RETURNS
823  *     Success: handle to the new bitmap
824  *     Failure: 0
825  */
826
827 HBITMAP WINAPI
828 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
829                     LPCOLORMAP lpColorMap, INT iNumMaps)
830 {
831     HGLOBAL hglb;
832     HRSRC hRsrc;
833     LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
834     UINT nSize, nColorTableSize;
835     RGBQUAD *pColorTable;
836     INT iColor, i, iMaps, nWidth, nHeight;
837     HDC hdcScreen;
838     HBITMAP hbm;
839     LPCOLORMAP sysColorMap;
840     COLORREF cRef;
841     COLORMAP internalColorMap[4] =
842         {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
843
844     /* initialize pointer to colortable and default color table */
845     if (lpColorMap) {
846         iMaps = iNumMaps;
847         sysColorMap = lpColorMap;
848     }
849     else {
850         internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
851         internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
852         internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
853         internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
854         iMaps = 4;
855         sysColorMap = (LPCOLORMAP)internalColorMap;
856     }
857
858     hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, (LPSTR)RT_BITMAP);
859     if (hRsrc == 0)
860         return 0;
861     hglb = LoadResource (hInstance, hRsrc);
862     if (hglb == 0)
863         return 0;
864     lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
865     if (lpBitmap == NULL)
866         return 0;
867
868     if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
869         nColorTableSize = lpBitmap->biClrUsed;
870     else if (lpBitmap->biBitCount <= 8) 
871         nColorTableSize = (1 << lpBitmap->biBitCount);
872     else
873         nColorTableSize = 0;
874     nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
875     lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
876     if (lpBitmapInfo == NULL)
877         return 0;
878     RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
879
880     pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
881
882     for (iColor = 0; iColor < nColorTableSize; iColor++) {
883         for (i = 0; i < iMaps; i++) {
884             cRef = RGB(pColorTable[iColor].rgbRed,
885                        pColorTable[iColor].rgbGreen,
886                        pColorTable[iColor].rgbBlue);
887             if ( cRef  == sysColorMap[i].from) {
888 #if 0
889                 if (wFlags & CBS_MASKED) {
890                     if (sysColorMap[i].to != COLOR_BTNTEXT)
891                         pColorTable[iColor] = RGB(255, 255, 255);
892                 }
893                 else
894 #endif
895                     pColorTable[iColor].rgbBlue  = GetBValue(sysColorMap[i].to);
896                     pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
897                     pColorTable[iColor].rgbRed   = GetRValue(sysColorMap[i].to);
898                 break;
899             }
900         }
901     }
902     nWidth  = (INT)lpBitmapInfo->biWidth;
903     nHeight = (INT)lpBitmapInfo->biHeight;
904     hdcScreen = GetDC (NULL);
905     hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
906     if (hbm) {
907         HDC hdcDst = CreateCompatibleDC (hdcScreen);
908         HBITMAP hbmOld = SelectObject (hdcDst, hbm);
909         LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
910         lpBits += nColorTableSize * sizeof(RGBQUAD);
911         StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
912                          lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
913                          SRCCOPY);
914         SelectObject (hdcDst, hbmOld);
915         DeleteDC (hdcDst);
916     }
917     ReleaseDC (NULL, hdcScreen);
918     GlobalFree ((HGLOBAL)lpBitmapInfo);
919     FreeResource (hglb);
920
921     return hbm;
922 }
923
924
925 /***********************************************************************
926  * CreateToolbar [COMCTL32.7]
927  *
928  * Creates a toolbar control.
929  *
930  * PARAMS
931  *     hwnd
932  *     style
933  *     wID
934  *     nBitmaps
935  *     hBMInst
936  *     wBMID
937  *     lpButtons
938  *     iNumButtons
939  *
940  * RETURNS
941  *     Success: handle to the tool bar control
942  *     Failure: 0
943  *
944  * NOTES
945  *     Do not use this functions anymore. Use CreateToolbarEx instead.
946  */
947
948 HWND WINAPI
949 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
950                HINSTANCE hBMInst, UINT wBMID,
951                LPCTBBUTTON lpButtons,INT iNumButtons)
952 {
953     return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
954                             hBMInst, wBMID, lpButtons,
955                             iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
956 }
957
958
959 /***********************************************************************
960  * DllGetVersion [COMCTL32.@]
961  *
962  * Retrieves version information of the 'COMCTL32.DLL'
963  *
964  * PARAMS
965  *     pdvi [O] pointer to version information structure.
966  *
967  * RETURNS
968  *     Success: S_OK
969  *     Failure: E_INVALIDARG
970  *
971  * NOTES
972  *     Returns version of a comctl32.dll from IE4.01 SP1.
973  */
974
975 HRESULT WINAPI
976 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
977 {
978     if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
979         WARN("wrong DLLVERSIONINFO size from app\n");
980         return E_INVALIDARG;
981     }
982
983     pdvi->dwMajorVersion = COMCTL32_VERSION;
984     pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
985     pdvi->dwBuildNumber = 2919;
986     pdvi->dwPlatformID = 6304;
987
988     TRACE("%lu.%lu.%lu.%lu\n",
989            pdvi->dwMajorVersion, pdvi->dwMinorVersion,
990            pdvi->dwBuildNumber, pdvi->dwPlatformID);
991
992     return S_OK;
993 }
994
995 /***********************************************************************
996  *              DllInstall (COMCTL32.@)
997  *
998  * Installs the ComCtl32 DLL.
999  *
1000  * RETURNS
1001  *     Success: S_OK
1002  *     Failure: A HRESULT error
1003  */
1004 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
1005 {
1006   FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
1007         debugstr_w(cmdline));
1008
1009   return S_OK;
1010 }
1011
1012 /***********************************************************************
1013  * _TrackMouseEvent [COMCTL32.@]
1014  *
1015  * Requests notification of mouse events
1016  *
1017  * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
1018  * to the hwnd specified in the ptme structure.  After the event message
1019  * is posted to the hwnd, the entry in the queue is removed.
1020  *
1021  * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
1022  * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
1023  * immediately and the TME_LEAVE flag being ignored.
1024  *
1025  * PARAMS
1026  *     ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1027  *
1028  * RETURNS
1029  *     Success: non-zero
1030  *     Failure: zero
1031  *
1032  * IMPLEMENTATION moved to USER32.TrackMouseEvent
1033  *
1034  */
1035
1036 BOOL WINAPI
1037 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1038 {
1039     return TrackMouseEvent (ptme);
1040 }
1041
1042 /*************************************************************************
1043  * GetMUILanguage [COMCTL32.@]
1044  *
1045  * Returns the user interface language in use by the current process.
1046  *
1047  * RETURNS
1048  *      Language ID in use by the current process.
1049  */
1050 LANGID WINAPI GetMUILanguage (VOID)
1051 {
1052     return COMCTL32_uiLang;
1053 }
1054
1055
1056 /*************************************************************************
1057  * InitMUILanguage [COMCTL32.@]
1058  *
1059  * Sets the user interface language to be used by the current process.
1060  *
1061  * RETURNS
1062  *      Nothing.
1063  */
1064 VOID WINAPI InitMUILanguage (LANGID uiLang)
1065 {
1066    COMCTL32_uiLang = uiLang;
1067 }
1068
1069
1070 /***********************************************************************
1071  * SetWindowSubclass [COMCTL32.410]
1072  *
1073  * Starts a window subclass
1074  *
1075  * PARAMS
1076  *     hWnd [in] handle to window subclass.
1077  *     pfnSubclass [in] Pointer to new window procedure.
1078  *     uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.
1079  *     dwRef [in] Reference data to pass to window procedure.
1080  *
1081  * RETURNS
1082  *     Success: non-zero
1083  *     Failure: zero
1084  *
1085  * BUGS
1086  *     If an application manually subclasses a window after subclassing it with
1087  *     this API and then with this API again, then none of the previous 
1088  *     subclasses get called or the origional window procedure.
1089  */
1090
1091 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1092                         UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1093 {
1094    LPSUBCLASS_INFO stack;
1095    int n;
1096
1097    TRACE ("(%p, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1098
1099    /* Since the window procedure that we set here has two additional arguments,
1100     * we can't simply set it as the new window procedure of the window. So we
1101     * set our own window procedure and then calculate the other two arguments
1102     * from there. */
1103
1104    /* See if we have been called for this window */
1105    stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1106    if (!stack) {
1107       /* allocate stack */
1108       stack = (LPSUBCLASS_INFO)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY,
1109                                          sizeof(SUBCLASS_INFO));
1110       if (!stack) {
1111          ERR ("Failed to allocate our Subclassing stack\n");
1112          return FALSE;
1113       }
1114       SetPropA (hWnd, COMCTL32_aSubclass, (HANDLE)stack);
1115
1116       /* set window procedure to our own and save the current one */
1117       if (IsWindowUnicode (hWnd))
1118          stack->origproc = (WNDPROC)SetWindowLongW (hWnd, GWL_WNDPROC,
1119                                                    (LONG)DefSubclassProc);
1120       else
1121          stack->origproc = (WNDPROC)SetWindowLongA (hWnd, GWL_WNDPROC,
1122                                                    (LONG)DefSubclassProc);
1123    } else {
1124       WNDPROC current;
1125       if (IsWindowUnicode (hWnd))
1126          current = (WNDPROC)GetWindowLongW (hWnd, GWL_WNDPROC);
1127       else
1128          current = (WNDPROC)GetWindowLongA (hWnd, GWL_WNDPROC);
1129
1130       if (current != DefSubclassProc) {
1131          ERR ("Application has subclassed with our procedure, then manually, then with us again.  The current implementation can't handle this.\n");
1132          return FALSE;
1133       }
1134    }
1135
1136    /* Check to see if we have called this function with the same uIDSubClass
1137     * and pfnSubclass */
1138    for (n = 0; n < stack->stacknum; n++)
1139       if ((stack->SubclassProcs[n].id == uIDSubclass) && 
1140          (stack->SubclassProcs[n].subproc == pfnSubclass)) {
1141          stack->SubclassProcs[n].ref = dwRef;
1142          return TRUE;
1143       }
1144
1145    if (stack->stacknum >= 32) {
1146       ERR ("We have a Subclass stack overflow, please increment size\n");
1147       return FALSE;
1148    }
1149
1150    memmove (&stack->SubclassProcs[1], &stack->SubclassProcs[0],
1151             sizeof(stack->SubclassProcs[0]) * stack->stacknum);
1152
1153    stack->stacknum++;
1154    if (stack->wndprocrecursion)
1155       stack->stackpos++;
1156
1157    stack->SubclassProcs[0].subproc = pfnSubclass;
1158    stack->SubclassProcs[0].ref = dwRef;
1159    stack->SubclassProcs[0].id = uIDSubclass;
1160    
1161    return TRUE;
1162 }
1163
1164
1165 /***********************************************************************
1166  * GetWindowSubclass [COMCTL32.411]
1167  *
1168  * Gets the Reference data from a subclass.
1169  *
1170  * PARAMS
1171  *     hWnd [in] Handle to window which were subclassing
1172  *     pfnSubclass [in] Pointer to the subclass procedure
1173  *     uID [in] Unique indentifier of the subclassing procedure
1174  *     pdwRef [out] Pointer to the reference data
1175  *
1176  * RETURNS
1177  *     Success: Non-zero
1178  *     Failure: 0
1179  */
1180
1181 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1182                               UINT_PTR uID, DWORD_PTR *pdwRef)
1183 {
1184    LPSUBCLASS_INFO stack;
1185    int n;
1186
1187    TRACE ("(%p, %p, %x, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1188
1189    /* See if we have been called for this window */
1190    stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1191    if (!stack)
1192       return FALSE;
1193
1194    for (n = 0; n < stack->stacknum; n++)
1195       if ((stack->SubclassProcs[n].id == uID) &&
1196          (stack->SubclassProcs[n].subproc == pfnSubclass)) {
1197          *pdwRef = stack->SubclassProcs[n].ref;
1198          return TRUE;
1199       }
1200
1201    return FALSE;
1202 }
1203
1204
1205 /***********************************************************************
1206  * RemoveWindowSubclass [COMCTL32.412]
1207  *
1208  * Removes a window subclass.
1209  *
1210  * PARAMS
1211  *     hWnd [in] Handle to the window were subclassing
1212  *     pfnSubclass [in] Pointer to the subclass procedure
1213  *     uID [in] Unique identifier of this subclass
1214  *
1215  * RETURNS
1216  *     Success: non-zero
1217  *     Failure: zero
1218  */
1219
1220 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1221 {
1222    LPSUBCLASS_INFO stack;
1223    int n;
1224
1225    TRACE ("(%p, %p, %x)\n", hWnd, pfnSubclass, uID);
1226
1227    /* Find the Subclass to remove */
1228    stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1229    if (!stack)
1230       return FALSE;
1231
1232    if ((stack->stacknum == 1) && (stack->stackpos == 1) &&
1233        !stack->wndprocrecursion) {
1234       TRACE("Last Subclass removed, cleaning up\n");
1235       /* clean up our heap and reset the origional window procedure */
1236       if (IsWindowUnicode (hWnd))
1237          SetWindowLongW (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1238       else
1239          SetWindowLongA (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1240       HeapFree (GetProcessHeap (), 0, stack);
1241       RemovePropA( hWnd, COMCTL32_aSubclass );
1242       return TRUE;
1243    }
1244  
1245    for (n = stack->stacknum - 1; n >= 0; n--)
1246       if ((stack->SubclassProcs[n].id == uID) &&
1247          (stack->SubclassProcs[n].subproc == pfnSubclass)) {
1248          if (n != stack->stacknum)
1249             /* Fill the hole in the stack */
1250             memmove (&stack->SubclassProcs[n], &stack->SubclassProcs[n + 1],
1251                     sizeof(stack->SubclassProcs[0]) * (stack->stacknum - n));
1252          stack->SubclassProcs[n].subproc = NULL;
1253          stack->SubclassProcs[n].ref = 0;
1254          stack->SubclassProcs[n].id = 0;
1255
1256          stack->stacknum--;
1257          if (n < stack->stackpos && stack->wndprocrecursion)
1258             stack->stackpos--;
1259
1260          return TRUE;
1261       }
1262
1263    return FALSE;
1264 }
1265
1266
1267 /***********************************************************************
1268  * DefSubclassProc [COMCTL32.413]
1269  *
1270  * Calls the next window procedure (ie. the one before this subclass)
1271  *
1272  * PARAMS
1273  *     hWnd [in] The window that we're subclassing
1274  *     uMsg [in] Message
1275  *     wParam [in] WPARAM
1276  *     lParam [in] LPARAM
1277  *
1278  * RETURNS
1279  *     Success: non-zero
1280  *     Failure: zero
1281  */
1282
1283 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1284 {
1285    LPSUBCLASS_INFO stack;
1286    LRESULT ret;
1287
1288    /* retrieve our little stack from the Properties */
1289    stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1290    if (!stack) {
1291       ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1292       return 0;
1293    }
1294
1295    stack->wndprocrecursion++;
1296
1297    /* If we are at the end of stack then we have to call the original
1298     * window procedure */
1299    if (stack->stackpos == stack->stacknum) {
1300       if (IsWindowUnicode (hWnd))
1301          ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1302       else
1303          ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1304    } else {
1305       stack->stackpos++;
1306       /* call the Subclass procedure from the stack */
1307       ret = stack->SubclassProcs[stack->stackpos - 1].subproc (hWnd, uMsg, wParam, lParam,
1308             stack->SubclassProcs[stack->stackpos - 1].id, stack->SubclassProcs[stack->stackpos - 1].ref);
1309       stack->stackpos--;
1310    }
1311
1312    /* We finished the recursion, so let's reinitalize the stack position to
1313     * beginning */
1314    if ((--stack->wndprocrecursion) == 0) {
1315       stack->stackpos = 0;
1316    }
1317
1318    /* If we removed the last entry in our stack while a window procedure was
1319     * running then we have to clean up */
1320    if ((stack->stackpos == 0) && (stack->stacknum == 0)) {
1321       TRACE("Last Subclass removed, cleaning up\n");
1322       /* clean up our heap and reset the origional window procedure */
1323       if (IsWindowUnicode (hWnd))
1324          SetWindowLongW (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1325       else
1326          SetWindowLongA (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1327       HeapFree (GetProcessHeap (), 0, stack);
1328       RemovePropA( hWnd, COMCTL32_aSubclass );
1329       return TRUE;
1330    }
1331
1332    return ret;
1333 }
1334
1335
1336 /***********************************************************************
1337  * COMCTL32_CreateToolTip [NOT AN API]
1338  *
1339  * Creates a tooltip for the control specified in hwnd and does all
1340  * necessary setup and notifications.
1341  *
1342  * PARAMS
1343  *     hwndOwner [I] Handle to the window that will own the tool tip.
1344  *
1345  * RETURNS
1346  *     Success: Handle of tool tip window.
1347  *     Failure: NULL
1348  */
1349
1350 HWND
1351 COMCTL32_CreateToolTip(HWND hwndOwner)
1352 {
1353     HWND hwndToolTip;
1354
1355     hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1356                                   CW_USEDEFAULT, CW_USEDEFAULT,
1357                                   CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1358                                   0, 0, 0);
1359
1360     /* Send NM_TOOLTIPSCREATED notification */
1361     if (hwndToolTip)
1362     {
1363         NMTOOLTIPSCREATED nmttc;
1364         /* true owner can be different if hwndOwner is a child window */
1365         HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1366         nmttc.hdr.hwndFrom = hwndTrueOwner;
1367         nmttc.hdr.idFrom = GetWindowLongA(hwndTrueOwner, GWL_ID);
1368         nmttc.hdr.code = NM_TOOLTIPSCREATED;
1369         nmttc.hwndToolTips = hwndToolTip;
1370
1371        SendMessageA(GetParent(hwndTrueOwner), WM_NOTIFY,
1372                     (WPARAM)GetWindowLongA(hwndTrueOwner, GWL_ID),
1373                      (LPARAM)&nmttc);
1374     }
1375
1376     return hwndToolTip;
1377 }
1378
1379
1380 /***********************************************************************
1381  * COMCTL32_RefreshSysColors [NOT AN API]
1382  *
1383  * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1384  * refresh the color values in the color structure
1385  *
1386  * PARAMS
1387  *     none
1388  *
1389  * RETURNS
1390  *     none
1391  */
1392
1393 VOID
1394 COMCTL32_RefreshSysColors(void)
1395 {
1396     comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1397     comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1398     comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1399     comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1400     comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1401     comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1402     comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1403     comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1404     comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1405     comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1406     comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1407     comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1408     comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1409     comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1410     comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1411     comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1412 }