Reduced huge (1GB) heap creation that caused Starcraft to fail.
[wine] / dlls / comctl32 / commctrl.c
1 /*              
2  * Common controls functions
3  *
4  * Copyright 1997 Dimitrie O. Paun
5  * Copyright 1998 Eric Kohl
6  *
7  */
8
9 #include "win.h"
10 #include "heap.h"
11 #include "commctrl.h"
12 #include "animate.h"
13 #include "comboex.h"
14 #include "header.h"
15 #include "hotkey.h"
16 #include "ipaddress.h"
17 #include "listview.h"
18 #include "nativefont.h"
19 #include "pager.h"
20 #include "progress.h"
21 #include "rebar.h"
22 #include "status.h"
23 #include "tab.h"
24 #include "toolbar.h"
25 #include "tooltips.h"
26 #include "trackbar.h"
27 #include "treeview.h"
28 #include "updown.h"
29 #include "debug.h"
30 #include "winerror.h"
31
32
33 HANDLE32 COMCTL32_hHeap = (HANDLE32)NULL;
34 DWORD    COMCTL32_dwProcessesAttached = 0;
35
36
37 /***********************************************************************
38  * ComCtl32LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
39  *
40  * PARAMS
41  *     hinstDLL    [I] handle to the 'dlls' instance
42  *     fdwReason   [I]
43  *     lpvReserved [I] reserverd, must be NULL
44  *
45  * RETURNS
46  *     Success: TRUE
47  *     Failure: FALSE
48  */
49
50 BOOL32 WINAPI
51 ComCtl32LibMain (HINSTANCE32 hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
52 {
53     TRACE (commctrl, "%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
54
55     switch (fdwReason) {
56         case DLL_PROCESS_ATTACH:
57             if (COMCTL32_dwProcessesAttached == 0) {
58                 /* create private heap */
59                 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
60                 TRACE (commctrl, "Heap created: 0x%x\n", COMCTL32_hHeap);
61
62                 /* register all Win95 common control classes */
63                 ANIMATE_Register ();
64                 HEADER_Register ();
65                 HOTKEY_Register ();
66                 LISTVIEW_Register ();
67                 PROGRESS_Register ();
68                 STATUS_Register ();
69                 TAB_Register ();
70                 TOOLBAR_Register ();
71                 TOOLTIPS_Register ();
72                 TRACKBAR_Register ();
73                 TREEVIEW_Register ();
74                 UPDOWN_Register ();
75             }
76             COMCTL32_dwProcessesAttached++;
77             break;
78
79         case DLL_PROCESS_DETACH:
80             COMCTL32_dwProcessesAttached--;
81             if (COMCTL32_dwProcessesAttached == 0) {
82                 /* unregister all common control classes */
83                 IPADDRESS_Unregister ();
84
85                 NATIVEFONT_Unregister ();
86
87                 TOOLTIPS_Unregister ();
88
89                 /* destroy private heap */
90                 HeapDestroy (COMCTL32_hHeap);
91                 TRACE (commctrl, "Heap destroyed: 0x%x\n", COMCTL32_hHeap);
92                 COMCTL32_hHeap = (HANDLE32)NULL;
93             }
94             break;
95     }
96
97     return TRUE;
98 }
99
100
101 /***********************************************************************
102  * MenuHelp [COMCTL32.2]
103  *
104  * PARAMS
105  *     uMsg       [I]
106  *     wParam     [I]
107  *     lParam     [I]
108  *     hMainMenu  [I] handle to the applications main menu
109  *     hInst      [I]
110  *     hwndStatus [I] handle to the status bar window
111  *     lpwIDs     [I] pointer to an array of intergers (see NOTES)
112  *
113  * RETURNS
114  *     No return value
115  *
116  * NOTES
117  *     The official documentation is incomplete!
118  */
119
120 VOID WINAPI
121 MenuHelp (UINT32 uMsg, WPARAM32 wParam, LPARAM lParam, HMENU32 hMainMenu,
122           HINSTANCE32 hInst, HWND32 hwndStatus, LPUINT32 lpwIDs)
123 {
124     UINT32 uMenuID = 0;
125
126     if (!IsWindow32 (hwndStatus))
127         return;
128
129     switch (uMsg) {
130         case WM_MENUSELECT:
131             TRACE (commctrl, "WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
132                    wParam, lParam);
133
134             if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
135                 /* menu was closed */
136                 TRACE (commctrl, "menu was closed!\n");
137                 SendMessage32A (hwndStatus, SB_SIMPLE, FALSE, 0);
138             }
139             else {
140                 /* menu item was selected */
141                 if (HIWORD(wParam) & MF_POPUP)
142                     uMenuID = (UINT32)*(lpwIDs+1);
143                 else
144                     uMenuID = (UINT32)LOWORD(wParam);
145                 TRACE (commctrl, "uMenuID = %u\n", uMenuID);
146
147                 if (uMenuID) {
148                     CHAR szText[256];
149
150                     if (!LoadString32A (hInst, uMenuID, szText, 256))
151                         szText[0] = '\0';
152
153                     SendMessage32A (hwndStatus, SB_SETTEXT32A,
154                                     255 | SBT_NOBORDERS, (LPARAM)szText);
155                     SendMessage32A (hwndStatus, SB_SIMPLE, TRUE, 0);
156                 }
157             }
158             break;
159
160         default:
161             FIXME (commctrl, "Invalid Message!\n");
162             break;
163     }
164 }
165
166
167 /***********************************************************************
168  * ShowHideMenuCtl [COMCTL32.3] 
169  *
170  * Shows or hides controls and updates the corresponding menu item.
171  *
172  * PARAMS
173  *     hwnd   [I] handle to the client window.
174  *     uFlags [I] menu command id.
175  *     lpInfo [I] pointer to an array of integers. (See NOTES.)
176  *
177  * RETURNS
178  *     Success: TRUE
179  *     Failure: FALSE
180  *
181  * NOTES
182  *     The official documentation is incomplete! This has been fixed.
183  *
184  *     lpInfo
185  *     The array of integers contains pairs of values. BOTH values of
186  *     the first pair must be the handles to application's main menu.
187  *     Each subsequent pair consists of a menu id and control id.
188  */
189
190 BOOL32 WINAPI
191 ShowHideMenuCtl (HWND32 hwnd, UINT32 uFlags, LPINT32 lpInfo)
192 {
193     LPINT32 lpMenuId;
194
195     TRACE (commctrl, "%x, %x, %p\n", hwnd, uFlags, lpInfo);
196
197     if (lpInfo == NULL)
198         return FALSE;
199
200     if (!(lpInfo[0]) || !(lpInfo[1]))
201         return FALSE;
202
203     /* search for control */
204     lpMenuId = &lpInfo[2];
205     while (*lpMenuId != uFlags)
206         lpMenuId += 2;
207
208     if (GetMenuState32 (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
209         /* uncheck menu item */
210         CheckMenuItem32 (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
211
212         /* hide control */
213         lpMenuId++;
214         SetWindowPos32 (GetDlgItem32 (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
215                         SWP_HIDEWINDOW);
216     }
217     else {
218         /* check menu item */
219         CheckMenuItem32 (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
220
221         /* show control */
222         lpMenuId++;
223         SetWindowPos32 (GetDlgItem32 (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
224                         SWP_SHOWWINDOW);
225     }
226
227     return TRUE;
228 }
229
230
231 /***********************************************************************
232  * GetEffectiveClientRect [COMCTL32.4]
233  *
234  * PARAMS
235  *     hwnd   [I] handle to the client window.
236  *     lpRect [O] pointer to the rectangle of the client window
237  *     lpInfo [I] pointer to an array of integers
238  *
239  * RETURNS
240  *     No return value.
241  *
242  * NOTES
243  *     The official documentation is incomplete!
244  */
245
246 VOID WINAPI
247 GetEffectiveClientRect (HWND32 hwnd, LPRECT32 lpRect, LPINT32 lpInfo)
248 {
249     RECT32 rcCtrl;
250     INT32  *lpRun;
251     HWND32 hwndCtrl;
252
253     TRACE (commctrl, "(0x%08lx 0x%08lx 0x%08lx)\n",
254            (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
255
256     GetClientRect32 (hwnd, lpRect);
257     lpRun = lpInfo;
258
259     do {
260         lpRun += 2;
261         if (*lpRun == 0)
262             return;
263         lpRun++;
264         hwndCtrl = GetDlgItem32 (hwnd, *lpRun);
265         if (GetWindowLong32A (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
266             TRACE (commctrl, "control id 0x%x\n", *lpRun);
267             GetWindowRect32 (hwndCtrl, &rcCtrl);
268             MapWindowPoints32 ((HWND32)0, hwnd, (LPPOINT32)&rcCtrl, 2);
269             SubtractRect32 (lpRect, lpRect, &rcCtrl);
270         }
271         lpRun++;
272     } while (*lpRun);
273 }
274
275
276 /***********************************************************************
277  * DrawStatusText32A [COMCTL32.5][COMCTL32.27]
278  *
279  * Draws text with borders, like in a status bar.
280  *
281  * PARAMS
282  *     hdc   [I] handle to the window's display context
283  *     lprc  [I] pointer to a rectangle
284  *     text  [I] pointer to the text
285  *     style [I] 
286  *
287  * RETURNS
288  *     No return value.
289  */
290
291 VOID WINAPI
292 DrawStatusText32A (HDC32 hdc, LPRECT32 lprc, LPCSTR text, UINT32 style)
293 {
294     RECT32 r = *lprc;
295     UINT32 border = BDR_SUNKENOUTER;
296
297     if (style == SBT_POPOUT)
298       border = BDR_RAISEDOUTER;
299     else if (style == SBT_NOBORDERS)
300       border = 0;
301
302     DrawEdge32 (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
303
304     /* now draw text */
305     if (text) {
306       int oldbkmode = SetBkMode32 (hdc, TRANSPARENT);
307       r.left += 3;
308       DrawText32A (hdc, text, lstrlen32A(text),
309                    &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);  
310       if (oldbkmode != TRANSPARENT)
311         SetBkMode32(hdc, oldbkmode);
312     }
313 }
314
315
316 /***********************************************************************
317  * DrawStatusText32W [COMCTL32.28]
318  *
319  * Draws text with borders, like in a status bar.
320  *
321  * PARAMS
322  *     hdc   [I] handle to the window's display context
323  *     lprc  [I] pointer to a rectangle
324  *     text  [I] pointer to the text
325  *     style [I]
326  *
327  * RETURNS
328  *     No return value.
329  */
330
331 VOID WINAPI
332 DrawStatusText32W (HDC32 hdc, LPRECT32 lprc, LPCWSTR text, UINT32 style)
333 {
334     LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
335     DrawStatusText32A (hdc, lprc, p, style);
336     HeapFree (GetProcessHeap (), 0, p );
337 }
338
339
340 /***********************************************************************
341  * CreateStatusWindow32A [COMCTL32.6][COMCTL32.21] Creates a status bar
342  *
343  * PARAMS
344  *     style  [I]
345  *     text   [I]
346  *     parent [I] handle to the parent window
347  *     wid    [I]
348  *
349  * RETURNS
350  *     Success: handle to the control
351  *     Failure: 0
352  */
353
354 HWND32 WINAPI
355 CreateStatusWindow32A (INT32 style, LPCSTR text, HWND32 parent, UINT32 wid)
356 {
357     return CreateWindow32A(STATUSCLASSNAME32A, text, style, 
358                            CW_USEDEFAULT32, CW_USEDEFAULT32,
359                            CW_USEDEFAULT32, CW_USEDEFAULT32, 
360                            parent, wid, 0, 0);
361 }
362
363
364 /***********************************************************************
365  * CreateStatusWindow32W [COMCTL32.22] Creates a status bar control
366  *
367  * PARAMS
368  *     style  [I]
369  *     text   [I]
370  *     parent [I] handle to the parent window
371  *     wid    [I] control id of the status bar
372  *
373  * RETURNS
374  *     Success: handle to the control
375  *     Failure: 0
376  */
377
378 HWND32 WINAPI
379 CreateStatusWindow32W (INT32 style, LPCWSTR text, HWND32 parent, UINT32 wid)
380 {
381     return CreateWindow32W((LPCWSTR)STATUSCLASSNAME32W, text, style,
382                            CW_USEDEFAULT32, CW_USEDEFAULT32,
383                            CW_USEDEFAULT32, CW_USEDEFAULT32,
384                            parent, wid, 0, 0);
385 }
386
387
388 /***********************************************************************
389  * CreateUpDownControl [COMCTL32.16] Creates an Up-Down control
390  *
391  * PARAMS
392  *     style
393  *     x
394  *     y
395  *     cx
396  *     cy
397  *     parent
398  *     id
399  *     inst
400  *     buddy
401  *     maxVal [I]
402  *     minVal [I]
403  *     curVal [I]
404  *
405  * RETURNS
406  *     Success: handle to the control
407  *     Failure: 0
408  */
409
410 HWND32 WINAPI
411 CreateUpDownControl (DWORD style, INT32 x, INT32 y, INT32 cx, INT32 cy,
412                      HWND32 parent, INT32 id, HINSTANCE32 inst,
413                      HWND32 buddy, INT32 maxVal, INT32 minVal, INT32 curVal)
414 {
415     HWND32 hUD =
416         CreateWindow32A (UPDOWN_CLASS32A, 0, style, x, y, cx, cy,
417                          parent, id, inst, 0);
418     if (hUD) {
419         SendMessage32A (hUD, UDM_SETBUDDY, buddy, 0);
420         SendMessage32A (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
421         SendMessage32A (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));     
422     }
423
424     return hUD;
425 }
426
427
428 /***********************************************************************
429  * InitCommonControls [COMCTL32.17]
430  *
431  * Registers the common controls.
432  *
433  * PARAMS
434  *     No parameters.
435  *
436  * RETURNS
437  *     No return values.
438  *
439  * NOTES
440  *     This function is just a dummy.
441  *     The Win95 controls are registered at the DLL's initialization.
442  *     To register other controls InitCommonControlsEx must be used.
443  */
444
445 VOID WINAPI
446 InitCommonControls (VOID)
447 {
448 }
449
450
451 /***********************************************************************
452  * InitCommonControlsEx [COMCTL32.81]
453  *
454  * Registers the common controls.
455  *
456  * PARAMS
457  *     lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
458  *
459  * RETURNS
460  *     Success: TRUE
461  *     Failure: FALSE
462  *
463  * NOTES
464  *     Only the additinal common controls are registered by this function.
465  *     The Win95 controls are registered at the DLL's initialization.
466  */
467
468 BOOL32 WINAPI
469 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
470 {
471     INT32 cCount;
472     DWORD dwMask;
473
474     if (!lpInitCtrls)
475         return FALSE;
476     if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
477         return FALSE;
478
479     TRACE(commctrl,"(0x%08lx)\n", lpInitCtrls->dwICC);
480
481     for (cCount = 0; cCount < 32; cCount++) {
482         dwMask = 1 << cCount;
483         if (!(lpInitCtrls->dwICC & dwMask))
484             continue;
485
486         switch (lpInitCtrls->dwICC & dwMask) {
487             /* dummy initialization */
488             case ICC_ANIMATE_CLASS:
489             case ICC_BAR_CLASSES:
490             case ICC_LISTVIEW_CLASSES:
491             case ICC_TREEVIEW_CLASSES:
492             case ICC_TAB_CLASSES:
493             case ICC_UPDOWN_CLASS:
494             case ICC_PROGRESS_CLASS:
495             case ICC_HOTKEY_CLASS:
496                 break;
497
498             /* advanced classes - not included in Win95 */
499             case ICC_DATE_CLASSES:
500                 FIXME (commctrl, "No month calendar class implemented!\n");
501                 FIXME (commctrl, "No date and time picker class implemented!\n");
502                 break;
503
504             case ICC_USEREX_CLASSES:
505                 COMBOEX_Register ();
506                 break;
507
508             case ICC_COOL_CLASSES:
509                 REBAR_Register ();
510                 break;
511
512             case ICC_INTERNET_CLASSES:
513                 IPADDRESS_Register ();
514                 break;
515
516             case ICC_PAGESCROLLER_CLASS:
517                 PAGER_Register ();
518                 break;
519
520             case ICC_NATIVEFNTCTL_CLASS:
521                 NATIVEFONT_Register ();
522                 break;
523
524             default:
525                 FIXME (commctrl, "Unknown class! dwICC=0x%lX\n", dwMask);
526                 break;
527         }
528     }
529
530     return TRUE;
531 }
532
533
534 /***********************************************************************
535  * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
536  *
537  * PARAMS
538  *     hwnd
539  *     style
540  *     wID
541  *     nBitmaps
542  *     hBMInst
543  *     wBMID
544  *     lpButtons
545  *     iNumButtons
546  *     dxButton
547  *     dyButton
548  *     dxBitmap
549  *     dyBitmap
550  *     uStructSize
551  *
552  * RETURNS
553  *     Success: handle to the tool bar control
554  *     Failure: 0
555  */
556
557 HWND32 WINAPI
558 CreateToolbarEx (HWND32 hwnd, DWORD style, UINT32 wID, INT32 nBitmaps,
559                  HINSTANCE32 hBMInst, UINT32 wBMID, LPCTBBUTTON lpButtons,
560                  INT32 iNumButtons, INT32 dxButton, INT32 dyButton,
561                  INT32 dxBitmap, INT32 dyBitmap, UINT32 uStructSize)
562 {
563     HWND32 hwndTB =
564         CreateWindowEx32A (0, TOOLBARCLASSNAME32A, "", style, 0, 0, 0, 0,
565                            hwnd, (HMENU32)wID, 0, NULL);
566     if(hwndTB) {
567         TBADDBITMAP tbab;
568
569         SendMessage32A (hwndTB, TB_BUTTONSTRUCTSIZE,
570                         (WPARAM32)uStructSize, 0);
571
572         /* set bitmap and button size */
573         if (hBMInst == HINST_COMMCTRL) {
574             if (wBMID & 1) {
575                 SendMessage32A (hwndTB, TB_SETBITMAPSIZE, 0,
576                                 MAKELPARAM(26, 25));
577                 SendMessage32A (hwndTB, TB_SETBUTTONSIZE, 0,
578                                 MAKELPARAM(33, 32));
579             }
580             else {
581                 SendMessage32A (hwndTB, TB_SETBITMAPSIZE, 0,
582                                 MAKELPARAM(16, 15));
583                 SendMessage32A (hwndTB, TB_SETBUTTONSIZE, 0,
584                                 MAKELPARAM(23, 22));
585             }
586         }
587         else {
588             SendMessage32A (hwndTB, TB_SETBITMAPSIZE, 0,
589                             MAKELPARAM((WORD)dyBitmap, (WORD)dxBitmap));
590             SendMessage32A (hwndTB, TB_SETBUTTONSIZE, 0,
591                             MAKELPARAM((WORD)dyButton, (WORD)dxButton));
592         }
593
594         /* add bitmaps */
595         tbab.hInst = hBMInst;
596         tbab.nID   = wBMID;
597         SendMessage32A (hwndTB, TB_ADDBITMAP,
598                         (WPARAM32)nBitmaps, (LPARAM)&tbab);
599
600         /* add buttons */
601         SendMessage32A (hwndTB, TB_ADDBUTTONS32A,
602                         (WPARAM32)iNumButtons, (LPARAM)lpButtons);
603     }
604
605     return hwndTB;
606 }
607
608
609 /***********************************************************************
610  * CreateMappedBitmap [COMCTL32.8]
611  *
612  * PARAMS
613  *     hInstance
614  *     idBitmap
615  *     wFlags
616  *     lpColorMap
617  *     iNumMaps
618  *
619  * RETURNS
620  *     Success: bitmap handle
621  *     Failure: 0
622  */
623
624 HBITMAP32 WINAPI
625 CreateMappedBitmap (HINSTANCE32 hInstance, INT32 idBitmap, UINT32 wFlags,
626                     LPCOLORMAP lpColorMap, INT32 iNumMaps)
627 {
628     HGLOBAL32 hglb;
629     HRSRC32 hRsrc;
630     LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
631     UINT32 nSize, nColorTableSize;
632     DWORD *pColorTable;
633     INT32 iColor, i, iMaps, nWidth, nHeight;
634     HDC32 hdcScreen;
635     HBITMAP32 hbm;
636     LPCOLORMAP sysColorMap;
637     COLORMAP internalColorMap[4] =
638         {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
639
640     /* initialize pointer to colortable and default color table */
641     if (lpColorMap) {
642         iMaps = iNumMaps;
643         sysColorMap = lpColorMap;
644     }
645     else {
646         internalColorMap[0].to = GetSysColor32 (COLOR_BTNTEXT);
647         internalColorMap[1].to = GetSysColor32 (COLOR_BTNSHADOW);
648         internalColorMap[2].to = GetSysColor32 (COLOR_BTNFACE);
649         internalColorMap[3].to = GetSysColor32 (COLOR_BTNHIGHLIGHT);
650         iMaps = 4;
651         sysColorMap = (LPCOLORMAP)internalColorMap;
652     }
653
654     hRsrc = FindResource32A (hInstance, (LPSTR)idBitmap, RT_BITMAP32A);
655     if (hRsrc == 0)
656         return 0;
657     hglb = LoadResource32 (hInstance, hRsrc);
658     if (hglb == 0)
659         return 0;
660     lpBitmap = (LPBITMAPINFOHEADER)LockResource32 (hglb);
661     if (lpBitmap == NULL)
662         return 0;
663
664     nColorTableSize = (1 << lpBitmap->biBitCount);
665     nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
666     lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc32 (GMEM_FIXED, nSize);
667     if (lpBitmapInfo == NULL)
668         return 0;
669     RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
670
671     pColorTable = (DWORD*)(((LPBYTE)lpBitmapInfo)+(UINT32)lpBitmapInfo->biSize);
672
673     for (iColor = 0; iColor < nColorTableSize; iColor++) {
674         for (i = 0; i < iMaps; i++) {
675             if (pColorTable[iColor] == sysColorMap[i].from) {
676 #if 0
677                 if (wFlags & CBS_MASKED) {
678                     if (sysColorMap[i].to != COLOR_BTNTEXT)
679                         pColorTable[iColor] = RGB(255, 255, 255);
680                 }
681                 else
682 #endif
683                     pColorTable[iColor] = sysColorMap[i].to;
684                 break;
685             }
686         }
687     }
688
689     nWidth  = (INT32)lpBitmapInfo->biWidth;
690     nHeight = (INT32)lpBitmapInfo->biHeight;
691     hdcScreen = GetDC32 ((HWND32)0);
692     hbm = CreateCompatibleBitmap32 (hdcScreen, nWidth, nHeight);
693     if (hbm) {
694         HDC32 hdcDst = CreateCompatibleDC32 (hdcScreen);
695         HBITMAP32 hbmOld = SelectObject32 (hdcDst, hbm);
696         LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
697         lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
698         StretchDIBits32 (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
699                          lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
700                          SRCCOPY);
701         SelectObject32 (hdcDst, hbmOld);
702         DeleteDC32 (hdcDst);
703     }
704     ReleaseDC32 ((HWND32)0, hdcScreen);
705     GlobalFree32 ((HGLOBAL32)lpBitmapInfo);
706     FreeResource32 (hglb);
707
708     return hbm;
709 }
710
711
712 /***********************************************************************
713  * CreateToolbar [COMCTL32.7] Creates a tool bar control
714  *
715  * PARAMS
716  *     hwnd
717  *     style
718  *     wID
719  *     nBitmaps
720  *     hBMInst
721  *     wBMID
722  *     lpButtons
723  *     iNumButtons
724  *
725  * RETURNS
726  *     Success: handle to the tool bar control
727  *     Failure: 0
728  *
729  * NOTES
730  *     Do not use this functions anymore. Use CreateToolbarEx instead.
731  */
732
733 HWND32 WINAPI
734 CreateToolbar (HWND32 hwnd, DWORD style, UINT32 wID, INT32 nBitmaps,
735                HINSTANCE32 hBMInst, UINT32 wBMID,
736                LPCOLDTBBUTTON lpButtons,INT32 iNumButtons)
737 {
738     return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
739                             hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
740                             iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
741 }
742
743
744 /***********************************************************************
745  * DllGetVersion [COMCTL32.25]
746  *
747  * Retrieves version information of the 'COMCTL32.DLL'
748  *
749  * PARAMS
750  *     pdvi [O] pointer to version information structure.
751  *
752  * RETURNS
753  *     Success: S_OK
754  *     Failure: E_INVALIDARG
755  *
756  * NOTES
757  *     Returns version of a comctl32.dll from IE4.01 SP1.
758  */
759
760 HRESULT WINAPI
761 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
762 {
763     if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
764         WARN (commctrl, "wrong DLLVERSIONINFO size from app");
765         return E_INVALIDARG;
766     }
767
768     pdvi->dwMajorVersion = 4;
769     pdvi->dwMinorVersion = 72;
770     pdvi->dwBuildNumber = 3110;
771     pdvi->dwPlatformID = 1;
772
773     TRACE (commctrl, "%lu.%lu.%lu.%lu\n",
774            pdvi->dwMajorVersion, pdvi->dwMinorVersion,
775            pdvi->dwBuildNumber, pdvi->dwPlatformID);
776
777     return S_OK;
778 }