user32: Add support for SPI_GETFOCUSBORDERWIDTH and SPI_GETFOCUSBORDERHEIGHT.
[wine] / dlls / user32 / user16.c
1 /*
2  * Misc 16-bit USER functions
3  *
4  * Copyright 1993, 1996 Alexandre Julliard
5  * Copyright 2002 Patrik Stridvall
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #define OEMRESOURCE
28
29 #include "wine/winuser16.h"
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wownt32.h"
33 #include "user_private.h"
34 #include "win.h"
35 #include "controls.h"
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(user);
39
40 /* handle to handle 16 conversions */
41 #define HANDLE_16(h32)          (LOWORD(h32))
42
43 /* handle16 to handle conversions */
44 #define HANDLE_32(h16)          ((HANDLE)(ULONG_PTR)(h16))
45 #define HINSTANCE_32(h16)       ((HINSTANCE)(ULONG_PTR)(h16))
46
47 #define IS_MENU_STRING_ITEM(flags) \
48     (((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR)) == MF_STRING)
49
50 /* UserSeeUserDo parameters */
51 #define USUD_LOCALALLOC        0x0001
52 #define USUD_LOCALFREE         0x0002
53 #define USUD_LOCALCOMPACT      0x0003
54 #define USUD_LOCALHEAP         0x0004
55 #define USUD_FIRSTCLASS        0x0005
56
57 WORD WINAPI DestroyIcon32(HGLOBAL16, UINT16);
58
59
60 struct gray_string_info
61 {
62     GRAYSTRINGPROC16 proc;
63     LPARAM           param;
64     char             str[1];
65 };
66
67 /* callback for 16-bit gray string proc with opaque pointer */
68 static BOOL CALLBACK gray_string_callback( HDC hdc, LPARAM param, INT len )
69 {
70     const struct gray_string_info *info = (struct gray_string_info *)param;
71     WORD args[4];
72     DWORD ret;
73
74     args[3] = HDC_16(hdc);
75     args[2] = HIWORD(info->param);
76     args[1] = LOWORD(info->param);
77     args[0] = len;
78     WOWCallback16Ex( (DWORD)info->proc, WCB16_PASCAL, sizeof(args), args, &ret );
79     return LOWORD(ret);
80 }
81
82 /* callback for 16-bit gray string proc with string pointer */
83 static BOOL CALLBACK gray_string_callback_ptr( HDC hdc, LPARAM param, INT len )
84 {
85     const struct gray_string_info *info;
86     char *str = (char *)param;
87
88     info = (struct gray_string_info *)(str - offsetof( struct gray_string_info, str ));
89     return gray_string_callback( hdc, (LPARAM)info, len );
90 }
91
92 struct draw_state_info
93 {
94     DRAWSTATEPROC16 proc;
95     LPARAM          param;
96 };
97
98 /* callback for 16-bit DrawState functions */
99 static BOOL CALLBACK draw_state_callback( HDC hdc, LPARAM lparam, WPARAM wparam, int cx, int cy )
100 {
101     const struct draw_state_info *info = (struct draw_state_info *)lparam;
102     WORD args[6];
103     DWORD ret;
104
105     args[5] = HDC_16(hdc);
106     args[4] = HIWORD(info->param);
107     args[3] = LOWORD(info->param);
108     args[2] = wparam;
109     args[1] = cx;
110     args[0] = cy;
111     WOWCallback16Ex( (DWORD)info->proc, WCB16_PASCAL, sizeof(args), args, &ret );
112     return LOWORD(ret);
113 }
114
115
116 /**********************************************************************
117  *              InitApp (USER.5)
118  */
119 INT16 WINAPI InitApp16( HINSTANCE16 hInstance )
120 {
121     /* Create task message queue */
122     return (InitThreadInput16( 0, 0 ) != 0);
123 }
124
125
126 /***********************************************************************
127  *              ExitWindows (USER.7)
128  */
129 BOOL16 WINAPI ExitWindows16( DWORD dwReturnCode, UINT16 wReserved )
130 {
131     return ExitWindowsEx( EWX_LOGOFF, 0xffffffff );
132 }
133
134
135 /***********************************************************************
136  *              GetTimerResolution (USER.14)
137  */
138 LONG WINAPI GetTimerResolution16(void)
139 {
140     return (1000);
141 }
142
143
144 /***********************************************************************
145  *              ClipCursor (USER.16)
146  */
147 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
148 {
149     RECT rect32;
150
151     if (!rect) return ClipCursor( NULL );
152     rect32.left   = rect->left;
153     rect32.top    = rect->top;
154     rect32.right  = rect->right;
155     rect32.bottom = rect->bottom;
156     return ClipCursor( &rect32 );
157 }
158
159
160 /***********************************************************************
161  *              GetCursorPos (USER.17)
162  */
163 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
164 {
165     POINT pos;
166     if (!pt) return 0;
167     GetCursorPos(&pos);
168     pt->x = pos.x;
169     pt->y = pos.y;
170     return 1;
171 }
172
173
174 /***********************************************************************
175  *              SetCursor (USER.69)
176  */
177 HCURSOR16 WINAPI SetCursor16(HCURSOR16 hCursor)
178 {
179   return HCURSOR_16(SetCursor(HCURSOR_32(hCursor)));
180 }
181
182
183 /***********************************************************************
184  *              SetCursorPos (USER.70)
185  */
186 void WINAPI SetCursorPos16( INT16 x, INT16 y )
187 {
188     SetCursorPos( x, y );
189 }
190
191
192 /***********************************************************************
193  *              ShowCursor (USER.71)
194  */
195 INT16 WINAPI ShowCursor16(BOOL16 bShow)
196 {
197   return ShowCursor(bShow);
198 }
199
200
201 /***********************************************************************
202  *              SetRect (USER.72)
203  */
204 void WINAPI SetRect16( LPRECT16 rect, INT16 left, INT16 top, INT16 right, INT16 bottom )
205 {
206     rect->left   = left;
207     rect->right  = right;
208     rect->top    = top;
209     rect->bottom = bottom;
210 }
211
212
213 /***********************************************************************
214  *              SetRectEmpty (USER.73)
215  */
216 void WINAPI SetRectEmpty16( LPRECT16 rect )
217 {
218     rect->left = rect->right = rect->top = rect->bottom = 0;
219 }
220
221
222 /***********************************************************************
223  *              CopyRect (USER.74)
224  */
225 BOOL16 WINAPI CopyRect16( RECT16 *dest, const RECT16 *src )
226 {
227     *dest = *src;
228     return TRUE;
229 }
230
231
232 /***********************************************************************
233  *              IsRectEmpty (USER.75)
234  *
235  * Bug compat: Windows checks for 0 or negative width/height.
236  */
237 BOOL16 WINAPI IsRectEmpty16( const RECT16 *rect )
238 {
239     return ((rect->left >= rect->right) || (rect->top >= rect->bottom));
240 }
241
242
243 /***********************************************************************
244  *              PtInRect (USER.76)
245  */
246 BOOL16 WINAPI PtInRect16( const RECT16 *rect, POINT16 pt )
247 {
248     return ((pt.x >= rect->left) && (pt.x < rect->right) &&
249             (pt.y >= rect->top) && (pt.y < rect->bottom));
250 }
251
252
253 /***********************************************************************
254  *              OffsetRect (USER.77)
255  */
256 void WINAPI OffsetRect16( LPRECT16 rect, INT16 x, INT16 y )
257 {
258     rect->left   += x;
259     rect->right  += x;
260     rect->top    += y;
261     rect->bottom += y;
262 }
263
264
265 /***********************************************************************
266  *              InflateRect (USER.78)
267  */
268 void WINAPI InflateRect16( LPRECT16 rect, INT16 x, INT16 y )
269 {
270     rect->left   -= x;
271     rect->top    -= y;
272     rect->right  += x;
273     rect->bottom += y;
274 }
275
276
277 /***********************************************************************
278  *              IntersectRect (USER.79)
279  */
280 BOOL16 WINAPI IntersectRect16( LPRECT16 dest, const RECT16 *src1,
281                                const RECT16 *src2 )
282 {
283     if (IsRectEmpty16(src1) || IsRectEmpty16(src2) ||
284         (src1->left >= src2->right) || (src2->left >= src1->right) ||
285         (src1->top >= src2->bottom) || (src2->top >= src1->bottom))
286     {
287         SetRectEmpty16( dest );
288         return FALSE;
289     }
290     dest->left   = max( src1->left, src2->left );
291     dest->right  = min( src1->right, src2->right );
292     dest->top    = max( src1->top, src2->top );
293     dest->bottom = min( src1->bottom, src2->bottom );
294     return TRUE;
295 }
296
297
298 /***********************************************************************
299  *              UnionRect (USER.80)
300  */
301 BOOL16 WINAPI UnionRect16( LPRECT16 dest, const RECT16 *src1,
302                            const RECT16 *src2 )
303 {
304     if (IsRectEmpty16(src1))
305     {
306         if (IsRectEmpty16(src2))
307         {
308             SetRectEmpty16( dest );
309             return FALSE;
310         }
311         else *dest = *src2;
312     }
313     else
314     {
315         if (IsRectEmpty16(src2)) *dest = *src1;
316         else
317         {
318             dest->left   = min( src1->left, src2->left );
319             dest->right  = max( src1->right, src2->right );
320             dest->top    = min( src1->top, src2->top );
321             dest->bottom = max( src1->bottom, src2->bottom );
322         }
323     }
324     return TRUE;
325 }
326
327
328 /***********************************************************************
329  *              FillRect (USER.81)
330  * NOTE
331  *   The Win16 variant doesn't support special color brushes like
332  *   the Win32 one, despite the fact that Win16, as well as Win32,
333  *   supports special background brushes for a window class.
334  */
335 INT16 WINAPI FillRect16( HDC16 hdc, const RECT16 *rect, HBRUSH16 hbrush )
336 {
337     HBRUSH prevBrush;
338
339     /* coordinates are logical so we cannot fast-check 'rect',
340      * it will be done later in the PatBlt().
341      */
342
343     if (!(prevBrush = SelectObject( HDC_32(hdc), HBRUSH_32(hbrush) ))) return 0;
344     PatBlt( HDC_32(hdc), rect->left, rect->top,
345               rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
346     SelectObject( HDC_32(hdc), prevBrush );
347     return 1;
348 }
349
350
351 /***********************************************************************
352  *              InvertRect (USER.82)
353  */
354 void WINAPI InvertRect16( HDC16 hdc, const RECT16 *rect )
355 {
356     PatBlt( HDC_32(hdc), rect->left, rect->top,
357               rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
358 }
359
360
361 /***********************************************************************
362  *              FrameRect (USER.83)
363  */
364 INT16 WINAPI FrameRect16( HDC16 hdc, const RECT16 *rect16, HBRUSH16 hbrush )
365 {
366     RECT rect;
367
368     rect.left   = rect16->left;
369     rect.top    = rect16->top;
370     rect.right  = rect16->right;
371     rect.bottom = rect16->bottom;
372     return FrameRect( HDC_32(hdc), &rect, HBRUSH_32(hbrush) );
373 }
374
375
376 /***********************************************************************
377  *              DrawIcon (USER.84)
378  */
379 BOOL16 WINAPI DrawIcon16(HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon)
380 {
381   return DrawIcon(HDC_32(hdc), x, y, HICON_32(hIcon));
382 }
383
384
385 /***********************************************************************
386  *           DrawText    (USER.85)
387  */
388 INT16 WINAPI DrawText16( HDC16 hdc, LPCSTR str, INT16 count, LPRECT16 rect, UINT16 flags )
389 {
390     INT16 ret;
391
392     if (rect)
393     {
394         RECT rect32;
395
396         rect32.left   = rect->left;
397         rect32.top    = rect->top;
398         rect32.right  = rect->right;
399         rect32.bottom = rect->bottom;
400         ret = DrawTextA( HDC_32(hdc), str, count, &rect32, flags );
401         rect->left   = rect32.left;
402         rect->top    = rect32.top;
403         rect->right  = rect32.right;
404         rect->bottom = rect32.bottom;
405     }
406     else ret = DrawTextA( HDC_32(hdc), str, count, NULL, flags);
407     return ret;
408 }
409
410
411 /***********************************************************************
412  *              IconSize (USER.86)
413  *
414  * See "Undocumented Windows". Used by W2.0 paint.exe.
415  */
416 DWORD WINAPI IconSize16(void)
417 {
418   return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
419 }
420
421
422 /***********************************************************************
423  *              AdjustWindowRect (USER.102)
424  */
425 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
426 {
427     return AdjustWindowRectEx16( rect, style, menu, 0 );
428 }
429
430
431 /***********************************************************************
432  *              MessageBeep (USER.104)
433  */
434 void WINAPI MessageBeep16( UINT16 i )
435 {
436     MessageBeep( i );
437 }
438
439
440 /**************************************************************************
441  *              CloseClipboard (USER.138)
442  */
443 BOOL16 WINAPI CloseClipboard16(void)
444 {
445     return CloseClipboard();
446 }
447
448
449 /**************************************************************************
450  *              EmptyClipboard (USER.139)
451  */
452 BOOL16 WINAPI EmptyClipboard16(void)
453 {
454     return EmptyClipboard();
455 }
456
457
458 /**************************************************************************
459  *              CountClipboardFormats (USER.143)
460  */
461 INT16 WINAPI CountClipboardFormats16(void)
462 {
463     return CountClipboardFormats();
464 }
465
466
467 /**************************************************************************
468  *              EnumClipboardFormats (USER.144)
469  */
470 UINT16 WINAPI EnumClipboardFormats16( UINT16 id )
471 {
472     return EnumClipboardFormats( id );
473 }
474
475
476 /**************************************************************************
477  *              RegisterClipboardFormat (USER.145)
478  */
479 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR name )
480 {
481     return RegisterClipboardFormatA( name );
482 }
483
484
485 /**************************************************************************
486  *              GetClipboardFormatName (USER.146)
487  */
488 INT16 WINAPI GetClipboardFormatName16( UINT16 id, LPSTR buffer, INT16 maxlen )
489 {
490     return GetClipboardFormatNameA( id, buffer, maxlen );
491 }
492
493
494 /**********************************************************************
495  *         CreateMenu    (USER.151)
496  */
497 HMENU16 WINAPI CreateMenu16(void)
498 {
499     return HMENU_16( CreateMenu() );
500 }
501
502
503 /**********************************************************************
504  *         DestroyMenu    (USER.152)
505  */
506 BOOL16 WINAPI DestroyMenu16( HMENU16 hMenu )
507 {
508     return DestroyMenu( HMENU_32(hMenu) );
509 }
510
511
512 /*******************************************************************
513  *         ChangeMenu    (USER.153)
514  */
515 BOOL16 WINAPI ChangeMenu16( HMENU16 hMenu, UINT16 pos, SEGPTR data,
516                             UINT16 id, UINT16 flags )
517 {
518     if (flags & MF_APPEND) return AppendMenu16( hMenu, flags & ~MF_APPEND, id, data );
519
520     /* FIXME: Word passes the item id in 'pos' and 0 or 0xffff as id */
521     /* for MF_DELETE. We should check the parameters for all others */
522     /* MF_* actions also (anybody got a doc on ChangeMenu?). */
523
524     if (flags & MF_DELETE) return DeleteMenu16(hMenu, pos, flags & ~MF_DELETE);
525     if (flags & MF_CHANGE) return ModifyMenu16(hMenu, pos, flags & ~MF_CHANGE, id, data );
526     if (flags & MF_REMOVE) return RemoveMenu16(hMenu, flags & MF_BYPOSITION ? pos : id,
527                                                flags & ~MF_REMOVE );
528     /* Default: MF_INSERT */
529     return InsertMenu16( hMenu, pos, flags, id, data );
530 }
531
532
533 /*******************************************************************
534  *         CheckMenuItem    (USER.154)
535  */
536 BOOL16 WINAPI CheckMenuItem16( HMENU16 hMenu, UINT16 id, UINT16 flags )
537 {
538     return CheckMenuItem( HMENU_32(hMenu), id, flags );
539 }
540
541
542 /**********************************************************************
543  *         EnableMenuItem    (USER.155)
544  */
545 BOOL16 WINAPI EnableMenuItem16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
546 {
547     return EnableMenuItem( HMENU_32(hMenu), wItemID, wFlags );
548 }
549
550
551 /**********************************************************************
552  *         GetSubMenu    (USER.159)
553  */
554 HMENU16 WINAPI GetSubMenu16( HMENU16 hMenu, INT16 nPos )
555 {
556     return HMENU_16( GetSubMenu( HMENU_32(hMenu), nPos ) );
557 }
558
559
560 /*******************************************************************
561  *         GetMenuString    (USER.161)
562  */
563 INT16 WINAPI GetMenuString16( HMENU16 hMenu, UINT16 wItemID,
564                               LPSTR str, INT16 nMaxSiz, UINT16 wFlags )
565 {
566     return GetMenuStringA( HMENU_32(hMenu), wItemID, str, nMaxSiz, wFlags );
567 }
568
569
570 /**********************************************************************
571  *              WinHelp (USER.171)
572  */
573 BOOL16 WINAPI WinHelp16( HWND16 hWnd, LPCSTR lpHelpFile, UINT16 wCommand,
574                          DWORD dwData )
575 {
576     BOOL ret;
577     DWORD mutex_count;
578
579     /* We might call WinExec() */
580     ReleaseThunkLock(&mutex_count);
581
582     ret = WinHelpA(WIN_Handle32(hWnd), lpHelpFile, wCommand, (DWORD)MapSL(dwData));
583
584     RestoreThunkLock(mutex_count);
585     return ret;
586 }
587
588
589 /***********************************************************************
590  *              LoadCursor (USER.173)
591  */
592 HCURSOR16 WINAPI LoadCursor16(HINSTANCE16 hInstance, LPCSTR name)
593 {
594   return HCURSOR_16(LoadCursorA(HINSTANCE_32(hInstance), name));
595 }
596
597
598 /***********************************************************************
599  *              LoadIcon (USER.174)
600  */
601 HICON16 WINAPI LoadIcon16(HINSTANCE16 hInstance, LPCSTR name)
602 {
603   return HICON_16(LoadIconA(HINSTANCE_32(hInstance), name));
604 }
605
606 /**********************************************************************
607  *              LoadBitmap (USER.175)
608  */
609 HBITMAP16 WINAPI LoadBitmap16(HINSTANCE16 hInstance, LPCSTR name)
610 {
611   return HBITMAP_16(LoadBitmapA(HINSTANCE_32(hInstance), name));
612 }
613
614
615 /***********************************************************************
616  *              GetSystemMetrics (USER.179)
617  */
618 INT16 WINAPI GetSystemMetrics16( INT16 index )
619 {
620     return GetSystemMetrics( index );
621 }
622
623
624 /*************************************************************************
625  *              GetSysColor (USER.180)
626  */
627 COLORREF WINAPI GetSysColor16( INT16 index )
628 {
629     return GetSysColor( index );
630 }
631
632
633 /*************************************************************************
634  *              SetSysColors (USER.181)
635  */
636 VOID WINAPI SetSysColors16( INT16 count, const INT16 *list16, const COLORREF *values )
637 {
638     INT i, *list;
639
640     if ((list = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*list) )))
641     {
642         for (i = 0; i < count; i++) list[i] = list16[i];
643         SetSysColors( count, list, values );
644         HeapFree( GetProcessHeap(), 0, list );
645     }
646 }
647
648
649 /***********************************************************************
650  *           GrayString   (USER.185)
651  */
652 BOOL16 WINAPI GrayString16( HDC16 hdc, HBRUSH16 hbr, GRAYSTRINGPROC16 gsprc,
653                             LPARAM lParam, INT16 cch, INT16 x, INT16 y,
654                             INT16 cx, INT16 cy )
655 {
656     BOOL ret;
657
658     if (!gsprc) return GrayStringA( HDC_32(hdc), HBRUSH_32(hbr), NULL,
659                                     (LPARAM)MapSL(lParam), cch, x, y, cx, cy );
660
661     if (cch == -1 || (cch && cx && cy))
662     {
663         /* lParam can be treated as an opaque pointer */
664         struct gray_string_info info;
665
666         info.proc  = gsprc;
667         info.param = lParam;
668         ret = GrayStringA( HDC_32(hdc), HBRUSH_32(hbr), gray_string_callback,
669                            (LPARAM)&info, cch, x, y, cx, cy );
670     }
671     else  /* here we need some string conversions */
672     {
673         char *str16 = MapSL(lParam);
674         struct gray_string_info *info;
675
676         if (!cch) cch = strlen(str16);
677         if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) + cch ))) return FALSE;
678         info->proc  = gsprc;
679         info->param = lParam;
680         memcpy( info->str, str16, cch );
681         ret = GrayStringA( HDC_32(hdc), HBRUSH_32(hbr), gray_string_callback_ptr,
682                            (LPARAM)info->str, cch, x, y, cx, cy );
683         HeapFree( GetProcessHeap(), 0, info );
684     }
685     return ret;
686 }
687
688
689 /***********************************************************************
690  *              SwapMouseButton (USER.186)
691  */
692 BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap )
693 {
694     return SwapMouseButton( fSwap );
695 }
696
697
698 /**************************************************************************
699  *              IsClipboardFormatAvailable (USER.193)
700  */
701 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
702 {
703     return IsClipboardFormatAvailable( wFormat );
704 }
705
706
707 /***********************************************************************
708  *           TabbedTextOut    (USER.196)
709  */
710 LONG WINAPI TabbedTextOut16( HDC16 hdc, INT16 x, INT16 y, LPCSTR lpstr,
711                              INT16 count, INT16 nb_tabs, const INT16 *tabs16, INT16 tab_org )
712 {
713     LONG ret;
714     INT i, *tabs = HeapAlloc( GetProcessHeap(), 0, nb_tabs * sizeof(tabs) );
715     if (!tabs) return 0;
716     for (i = 0; i < nb_tabs; i++) tabs[i] = tabs16[i];
717     ret = TabbedTextOutA( HDC_32(hdc), x, y, lpstr, count, nb_tabs, tabs, tab_org );
718     HeapFree( GetProcessHeap(), 0, tabs );
719     return ret;
720 }
721
722
723 /***********************************************************************
724  *           GetTabbedTextExtent    (USER.197)
725  */
726 DWORD WINAPI GetTabbedTextExtent16( HDC16 hdc, LPCSTR lpstr, INT16 count,
727                                     INT16 nb_tabs, const INT16 *tabs16 )
728 {
729     LONG ret;
730     INT i, *tabs = HeapAlloc( GetProcessHeap(), 0, nb_tabs * sizeof(tabs) );
731     if (!tabs) return 0;
732     for (i = 0; i < nb_tabs; i++) tabs[i] = tabs16[i];
733     ret = GetTabbedTextExtentA( HDC_32(hdc), lpstr, count, nb_tabs, tabs );
734     HeapFree( GetProcessHeap(), 0, tabs );
735     return ret;
736 }
737
738
739 /***********************************************************************
740  *              UserSeeUserDo (USER.216)
741  */
742 DWORD WINAPI UserSeeUserDo16(WORD wReqType, WORD wParam1, WORD wParam2, WORD wParam3)
743 {
744     STACK16FRAME* stack16 = MapSL((SEGPTR)NtCurrentTeb()->WOW32Reserved);
745     HANDLE16 oldDS = stack16->ds;
746     DWORD ret = (DWORD)-1;
747
748     stack16->ds = USER_HeapSel;
749     switch (wReqType)
750     {
751     case USUD_LOCALALLOC:
752         ret = LocalAlloc16(wParam1, wParam3);
753         break;
754     case USUD_LOCALFREE:
755         ret = LocalFree16(wParam1);
756         break;
757     case USUD_LOCALCOMPACT:
758         ret = LocalCompact16(wParam3);
759         break;
760     case USUD_LOCALHEAP:
761         ret = USER_HeapSel;
762         break;
763     case USUD_FIRSTCLASS:
764         FIXME("return a pointer to the first window class.\n");
765         break;
766     default:
767         WARN("wReqType %04x (unknown)\n", wReqType);
768     }
769     stack16->ds = oldDS;
770     return ret;
771 }
772
773
774 /*************************************************************************
775  *              ScrollDC (USER.221)
776  */
777 BOOL16 WINAPI ScrollDC16( HDC16 hdc, INT16 dx, INT16 dy, const RECT16 *rect,
778                           const RECT16 *cliprc, HRGN16 hrgnUpdate,
779                           LPRECT16 rcUpdate )
780 {
781     RECT rect32, clipRect32, rcUpdate32;
782     BOOL16 ret;
783
784     if (rect)
785     {
786         rect32.left   = rect->left;
787         rect32.top    = rect->top;
788         rect32.right  = rect->right;
789         rect32.bottom = rect->bottom;
790     }
791     if (cliprc)
792     {
793         clipRect32.left   = cliprc->left;
794         clipRect32.top    = cliprc->top;
795         clipRect32.right  = cliprc->right;
796         clipRect32.bottom = cliprc->bottom;
797     }
798     ret = ScrollDC( HDC_32(hdc), dx, dy, rect ? &rect32 : NULL,
799                     cliprc ? &clipRect32 : NULL, HRGN_32(hrgnUpdate),
800                     &rcUpdate32 );
801     if (rcUpdate)
802     {
803         rcUpdate->left   = rcUpdate32.left;
804         rcUpdate->top    = rcUpdate32.top;
805         rcUpdate->right  = rcUpdate32.right;
806         rcUpdate->bottom = rcUpdate32.bottom;
807     }
808     return ret;
809 }
810
811
812 /***********************************************************************
813  *              GetSystemDebugState (USER.231)
814  */
815 WORD WINAPI GetSystemDebugState16(void)
816 {
817     return 0;  /* FIXME */
818 }
819
820
821 /***********************************************************************
822  *              EqualRect (USER.244)
823  */
824 BOOL16 WINAPI EqualRect16( const RECT16* rect1, const RECT16* rect2 )
825 {
826     return ((rect1->left == rect2->left) && (rect1->right == rect2->right) &&
827             (rect1->top == rect2->top) && (rect1->bottom == rect2->bottom));
828 }
829
830
831 /***********************************************************************
832  *              ExitWindowsExec (USER.246)
833  */
834 BOOL16 WINAPI ExitWindowsExec16( LPCSTR lpszExe, LPCSTR lpszParams )
835 {
836     TRACE("Should run the following in DOS-mode: \"%s %s\"\n",
837           lpszExe, lpszParams);
838     return ExitWindowsEx( EWX_LOGOFF, 0xffffffff );
839 }
840
841
842 /***********************************************************************
843  *              GetCursor (USER.247)
844  */
845 HCURSOR16 WINAPI GetCursor16(void)
846 {
847   return HCURSOR_16(GetCursor());
848 }
849
850
851 /**********************************************************************
852  *              GetAsyncKeyState (USER.249)
853  */
854 INT16 WINAPI GetAsyncKeyState16( INT16 key )
855 {
856     return GetAsyncKeyState( key );
857 }
858
859
860 /**********************************************************************
861  *         GetMenuState    (USER.250)
862  */
863 UINT16 WINAPI GetMenuState16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
864 {
865     return GetMenuState( HMENU_32(hMenu), wItemID, wFlags );
866 }
867
868
869 /**********************************************************************
870  *         GetMenuItemCount    (USER.263)
871  */
872 INT16 WINAPI GetMenuItemCount16( HMENU16 hMenu )
873 {
874     return GetMenuItemCount( HMENU_32(hMenu) );
875 }
876
877
878 /**********************************************************************
879  *         GetMenuItemID    (USER.264)
880  */
881 UINT16 WINAPI GetMenuItemID16( HMENU16 hMenu, INT16 nPos )
882 {
883     return GetMenuItemID( HMENU_32(hMenu), nPos );
884 }
885
886
887 /***********************************************************************
888  *              GlobalAddAtom (USER.268)
889  */
890 ATOM WINAPI GlobalAddAtom16(LPCSTR lpString)
891 {
892   return GlobalAddAtomA(lpString);
893 }
894
895 /***********************************************************************
896  *              GlobalDeleteAtom (USER.269)
897  */
898 ATOM WINAPI GlobalDeleteAtom16(ATOM nAtom)
899 {
900   return GlobalDeleteAtom(nAtom);
901 }
902
903 /***********************************************************************
904  *              GlobalFindAtom (USER.270)
905  */
906 ATOM WINAPI GlobalFindAtom16(LPCSTR lpString)
907 {
908   return GlobalFindAtomA(lpString);
909 }
910
911 /***********************************************************************
912  *              GlobalGetAtomName (USER.271)
913  */
914 UINT16 WINAPI GlobalGetAtomName16(ATOM nAtom, LPSTR lpBuffer, INT16 nSize)
915 {
916   return GlobalGetAtomNameA(nAtom, lpBuffer, nSize);
917 }
918
919
920 /***********************************************************************
921  *              ControlPanelInfo (USER.273)
922  */
923 void WINAPI ControlPanelInfo16( INT16 nInfoType, WORD wData, LPSTR lpBuffer )
924 {
925     FIXME("(%d, %04x, %p): stub.\n", nInfoType, wData, lpBuffer);
926 }
927
928
929 /***********************************************************************
930  *           OldSetDeskPattern   (USER.279)
931  */
932 BOOL16 WINAPI SetDeskPattern16(void)
933 {
934     return SystemParametersInfoA( SPI_SETDESKPATTERN, -1, NULL, FALSE );
935 }
936
937
938 /***********************************************************************
939  *              GetSysColorBrush (USER.281)
940  */
941 HBRUSH16 WINAPI GetSysColorBrush16( INT16 index )
942 {
943     return HBRUSH_16( GetSysColorBrush(index) );
944 }
945
946
947 /***********************************************************************
948  *              SelectPalette (USER.282)
949  */
950 HPALETTE16 WINAPI SelectPalette16( HDC16 hdc, HPALETTE16 hpal, BOOL16 bForceBackground )
951 {
952     return HPALETTE_16( SelectPalette( HDC_32(hdc), HPALETTE_32(hpal), bForceBackground ));
953 }
954
955 /***********************************************************************
956  *              RealizePalette (USER.283)
957  */
958 UINT16 WINAPI RealizePalette16( HDC16 hdc )
959 {
960     return UserRealizePalette( HDC_32(hdc) );
961 }
962
963
964 /***********************************************************************
965  *              GetFreeSystemResources (USER.284)
966  */
967 WORD WINAPI GetFreeSystemResources16( WORD resType )
968 {
969     STACK16FRAME* stack16 = MapSL((SEGPTR)NtCurrentTeb()->WOW32Reserved);
970     HANDLE16 oldDS = stack16->ds;
971     HINSTANCE16 gdi_inst;
972     int userPercent, gdiPercent;
973
974     if ((gdi_inst = LoadLibrary16( "GDI" )) < 32) return 0;
975
976     switch(resType)
977     {
978     case GFSR_USERRESOURCES:
979         stack16->ds = USER_HeapSel;
980         userPercent = (int)LocalCountFree16() * 100 / LocalHeapSize16();
981         gdiPercent  = 100;
982         stack16->ds = oldDS;
983         break;
984
985     case GFSR_GDIRESOURCES:
986         stack16->ds = gdi_inst;
987         gdiPercent  = (int)LocalCountFree16() * 100 / LocalHeapSize16();
988         userPercent = 100;
989         stack16->ds = oldDS;
990         break;
991
992     case GFSR_SYSTEMRESOURCES:
993         stack16->ds = USER_HeapSel;
994         userPercent = (int)LocalCountFree16() * 100 / LocalHeapSize16();
995         stack16->ds = gdi_inst;
996         gdiPercent  = (int)LocalCountFree16() * 100 / LocalHeapSize16();
997         stack16->ds = oldDS;
998         break;
999
1000     default:
1001         userPercent = gdiPercent = 0;
1002         break;
1003     }
1004     FreeLibrary16( gdi_inst );
1005     TRACE("<- userPercent %d, gdiPercent %d\n", userPercent, gdiPercent);
1006     return (WORD)min( userPercent, gdiPercent );
1007 }
1008
1009
1010 /***********************************************************************
1011  *           SetDeskWallPaper   (USER.285)
1012  */
1013 BOOL16 WINAPI SetDeskWallPaper16( LPCSTR filename )
1014 {
1015     return SetDeskWallPaper( filename );
1016 }
1017
1018
1019 /***********************************************************************
1020  *              keybd_event (USER.289)
1021  */
1022 void WINAPI keybd_event16( CONTEXT86 *context )
1023 {
1024     DWORD dwFlags = 0;
1025
1026     if (HIBYTE(context->Eax) & 0x80) dwFlags |= KEYEVENTF_KEYUP;
1027     if (HIBYTE(context->Ebx) & 0x01) dwFlags |= KEYEVENTF_EXTENDEDKEY;
1028
1029     keybd_event( LOBYTE(context->Eax), LOBYTE(context->Ebx),
1030                  dwFlags, MAKELONG(LOWORD(context->Esi), LOWORD(context->Edi)) );
1031 }
1032
1033
1034 /***********************************************************************
1035  *              mouse_event (USER.299)
1036  */
1037 void WINAPI mouse_event16( CONTEXT86 *context )
1038 {
1039     mouse_event( LOWORD(context->Eax), LOWORD(context->Ebx), LOWORD(context->Ecx),
1040                  LOWORD(context->Edx), MAKELONG(context->Esi, context->Edi) );
1041 }
1042
1043
1044 /***********************************************************************
1045  *              GetClipCursor (USER.309)
1046  */
1047 void WINAPI GetClipCursor16( RECT16 *rect )
1048 {
1049     if (rect)
1050     {
1051         RECT rect32;
1052         GetClipCursor( &rect32 );
1053         rect->left   = rect32.left;
1054         rect->top    = rect32.top;
1055         rect->right  = rect32.right;
1056         rect->bottom = rect32.bottom;
1057     }
1058 }
1059
1060
1061 /***********************************************************************
1062  *              SignalProc (USER.314)
1063  */
1064 void WINAPI SignalProc16( HANDLE16 hModule, UINT16 code,
1065                           UINT16 uExitFn, HINSTANCE16 hInstance, HQUEUE16 hQueue )
1066 {
1067     if (code == USIG16_DLL_UNLOAD)
1068     {
1069         /* HOOK_FreeModuleHooks( hModule ); */
1070         CLASS_FreeModuleClasses( hModule );
1071         CURSORICON_FreeModuleIcons( hModule );
1072     }
1073 }
1074
1075
1076 /***********************************************************************
1077  *              SetEventHook (USER.321)
1078  *
1079  *      Used by Turbo Debugger for Windows
1080  */
1081 FARPROC16 WINAPI SetEventHook16(FARPROC16 lpfnEventHook)
1082 {
1083     FIXME("(lpfnEventHook=%p): stub\n", lpfnEventHook);
1084     return 0;
1085 }
1086
1087
1088 /**********************************************************************
1089  *              EnableHardwareInput (USER.331)
1090  */
1091 BOOL16 WINAPI EnableHardwareInput16(BOOL16 bEnable)
1092 {
1093     FIXME("(%d) - stub\n", bEnable);
1094     return TRUE;
1095 }
1096
1097
1098 /***********************************************************************
1099  *              GetMouseEventProc (USER.337)
1100  */
1101 FARPROC16 WINAPI GetMouseEventProc16(void)
1102 {
1103     HMODULE16 hmodule = GetModuleHandle16("USER");
1104     return GetProcAddress16( hmodule, "mouse_event" );
1105 }
1106
1107
1108 /***********************************************************************
1109  *              IsUserIdle (USER.333)
1110  */
1111 BOOL16 WINAPI IsUserIdle16(void)
1112 {
1113     if ( GetAsyncKeyState( VK_LBUTTON ) & 0x8000 )
1114         return FALSE;
1115     if ( GetAsyncKeyState( VK_RBUTTON ) & 0x8000 )
1116         return FALSE;
1117     if ( GetAsyncKeyState( VK_MBUTTON ) & 0x8000 )
1118         return FALSE;
1119     /* Should check for screen saver activation here ... */
1120     return TRUE;
1121 }
1122
1123
1124 /**********************************************************************
1125  *              LoadDIBIconHandler (USER.357)
1126  *
1127  * RT_ICON resource loader, installed by USER_SignalProc when module
1128  * is initialized.
1129  */
1130 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1131 {
1132     /* If hResource is zero we must allocate a new memory block, if it's
1133      * non-zero but GlobalLock() returns NULL then it was discarded and
1134      * we have to recommit some memory, otherwise we just need to check
1135      * the block size. See LoadProc() in 16-bit SDK for more.
1136      */
1137     FIXME( "%x %x %x: stub, not supported anymore\n", hMemObj, hModule, hRsrc );
1138     return 0;
1139 }
1140
1141 /**********************************************************************
1142  *              LoadDIBCursorHandler (USER.356)
1143  *
1144  * RT_CURSOR resource loader. Same as above.
1145  */
1146 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1147 {
1148     FIXME( "%x %x %x: stub, not supported anymore\n", hMemObj, hModule, hRsrc );
1149     return 0;
1150 }
1151
1152
1153 /**********************************************************************
1154  *              IsMenu    (USER.358)
1155  */
1156 BOOL16 WINAPI IsMenu16( HMENU16 hmenu )
1157 {
1158     return IsMenu( HMENU_32(hmenu) );
1159 }
1160
1161
1162 /***********************************************************************
1163  *              DCHook (USER.362)
1164  */
1165 BOOL16 WINAPI DCHook16( HDC16 hdc, WORD code, DWORD data, LPARAM lParam )
1166 {
1167     FIXME( "hDC = %x, %i: stub\n", hdc, code );
1168     return FALSE;
1169 }
1170
1171
1172 /***********************************************************************
1173  *              SubtractRect (USER.373)
1174  */
1175 BOOL16 WINAPI SubtractRect16( LPRECT16 dest, const RECT16 *src1,
1176                               const RECT16 *src2 )
1177 {
1178     RECT16 tmp;
1179
1180     if (IsRectEmpty16( src1 ))
1181     {
1182         SetRectEmpty16( dest );
1183         return FALSE;
1184     }
1185     *dest = *src1;
1186     if (IntersectRect16( &tmp, src1, src2 ))
1187     {
1188         if (EqualRect16( &tmp, dest ))
1189         {
1190             SetRectEmpty16( dest );
1191             return FALSE;
1192         }
1193         if ((tmp.top == dest->top) && (tmp.bottom == dest->bottom))
1194         {
1195             if (tmp.left == dest->left) dest->left = tmp.right;
1196             else if (tmp.right == dest->right) dest->right = tmp.left;
1197         }
1198         else if ((tmp.left == dest->left) && (tmp.right == dest->right))
1199         {
1200             if (tmp.top == dest->top) dest->top = tmp.bottom;
1201             else if (tmp.bottom == dest->bottom) dest->bottom = tmp.top;
1202         }
1203     }
1204     return TRUE;
1205 }
1206
1207
1208 /**********************************************************************
1209  *         SetMenuContextHelpId    (USER.384)
1210  */
1211 BOOL16 WINAPI SetMenuContextHelpId16( HMENU16 hMenu, DWORD dwContextHelpID)
1212 {
1213     return SetMenuContextHelpId( HMENU_32(hMenu), dwContextHelpID );
1214 }
1215
1216
1217 /**********************************************************************
1218  *         GetMenuContextHelpId    (USER.385)
1219  */
1220 DWORD WINAPI GetMenuContextHelpId16( HMENU16 hMenu )
1221 {
1222     return GetMenuContextHelpId( HMENU_32(hMenu) );
1223 }
1224
1225
1226 /***********************************************************************
1227  *              LoadImage (USER.389)
1228  *
1229  */
1230 HANDLE16 WINAPI LoadImage16(HINSTANCE16 hinst, LPCSTR name, UINT16 type,
1231                             INT16 desiredx, INT16 desiredy, UINT16 loadflags)
1232 {
1233   return HANDLE_16(LoadImageA(HINSTANCE_32(hinst), name, type, desiredx,
1234                               desiredy, loadflags));
1235 }
1236
1237 /******************************************************************************
1238  *              CopyImage (USER.390) Creates new image and copies attributes to it
1239  *
1240  */
1241 HICON16 WINAPI CopyImage16(HANDLE16 hnd, UINT16 type, INT16 desiredx,
1242                            INT16 desiredy, UINT16 flags)
1243 {
1244   return HICON_16(CopyImage(HANDLE_32(hnd), (UINT)type, (INT)desiredx,
1245                             (INT)desiredy, (UINT)flags));
1246 }
1247
1248 /**********************************************************************
1249  *              DrawIconEx (USER.394)
1250  */
1251 BOOL16 WINAPI DrawIconEx16(HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
1252                            INT16 cxWidth, INT16 cyWidth, UINT16 istep,
1253                            HBRUSH16 hbr, UINT16 flags)
1254 {
1255   return DrawIconEx(HDC_32(hdc), xLeft, yTop, HICON_32(hIcon), cxWidth, cyWidth,
1256                     istep, HBRUSH_32(hbr), flags);
1257 }
1258
1259 /**********************************************************************
1260  *              GetIconInfo (USER.395)
1261  */
1262 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon, LPICONINFO16 iconinfo)
1263 {
1264   ICONINFO ii32;
1265   BOOL16 ret = GetIconInfo(HICON_32(hIcon), &ii32);
1266
1267   iconinfo->fIcon = ii32.fIcon;
1268   iconinfo->xHotspot = ii32.xHotspot;
1269   iconinfo->yHotspot = ii32.yHotspot;
1270   iconinfo->hbmMask  = HBITMAP_16(ii32.hbmMask);
1271   iconinfo->hbmColor = HBITMAP_16(ii32.hbmColor);
1272   return ret;
1273 }
1274
1275
1276 /***********************************************************************
1277  *              FinalUserInit (USER.400)
1278  */
1279 void WINAPI FinalUserInit16( void )
1280 {
1281     /* FIXME: Should chain to FinalGdiInit */
1282 }
1283
1284
1285 /***********************************************************************
1286  *              CreateCursor (USER.406)
1287  */
1288 HCURSOR16 WINAPI CreateCursor16(HINSTANCE16 hInstance,
1289                                 INT16 xHotSpot, INT16 yHotSpot,
1290                                 INT16 nWidth, INT16 nHeight,
1291                                 LPCVOID lpANDbits, LPCVOID lpXORbits)
1292 {
1293   CURSORICONINFO info;
1294
1295   info.ptHotSpot.x = xHotSpot;
1296   info.ptHotSpot.y = yHotSpot;
1297   info.nWidth = nWidth;
1298   info.nHeight = nHeight;
1299   info.nWidthBytes = 0;
1300   info.bPlanes = 1;
1301   info.bBitsPerPixel = 1;
1302
1303   return CreateCursorIconIndirect16(hInstance, &info, lpANDbits, lpXORbits);
1304 }
1305
1306
1307 /***********************************************************************
1308  *              InitThreadInput   (USER.409)
1309  */
1310 HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
1311 {
1312     /* nothing to do here */
1313     return 0xbeef;
1314 }
1315
1316
1317 /*******************************************************************
1318  *         InsertMenu    (USER.410)
1319  */
1320 BOOL16 WINAPI InsertMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
1321                             UINT16 id, SEGPTR data )
1322 {
1323     UINT pos32 = (UINT)pos;
1324     if ((pos == (UINT16)-1) && (flags & MF_BYPOSITION)) pos32 = (UINT)-1;
1325     if (IS_MENU_STRING_ITEM(flags) && data)
1326         return InsertMenuA( HMENU_32(hMenu), pos32, flags, id, MapSL(data) );
1327     return InsertMenuA( HMENU_32(hMenu), pos32, flags, id, (LPSTR)data );
1328 }
1329
1330
1331 /*******************************************************************
1332  *         AppendMenu    (USER.411)
1333  */
1334 BOOL16 WINAPI AppendMenu16(HMENU16 hMenu, UINT16 flags, UINT16 id, SEGPTR data)
1335 {
1336     return InsertMenu16( hMenu, -1, flags | MF_BYPOSITION, id, data );
1337 }
1338
1339
1340 /**********************************************************************
1341  *         RemoveMenu   (USER.412)
1342  */
1343 BOOL16 WINAPI RemoveMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
1344 {
1345     return RemoveMenu( HMENU_32(hMenu), nPos, wFlags );
1346 }
1347
1348
1349 /**********************************************************************
1350  *         DeleteMenu    (USER.413)
1351  */
1352 BOOL16 WINAPI DeleteMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
1353 {
1354     return DeleteMenu( HMENU_32(hMenu), nPos, wFlags );
1355 }
1356
1357
1358 /*******************************************************************
1359  *         ModifyMenu    (USER.414)
1360  */
1361 BOOL16 WINAPI ModifyMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
1362                             UINT16 id, SEGPTR data )
1363 {
1364     if (IS_MENU_STRING_ITEM(flags))
1365         return ModifyMenuA( HMENU_32(hMenu), pos, flags, id, MapSL(data) );
1366     return ModifyMenuA( HMENU_32(hMenu), pos, flags, id, (LPSTR)data );
1367 }
1368
1369
1370 /**********************************************************************
1371  *         CreatePopupMenu    (USER.415)
1372  */
1373 HMENU16 WINAPI CreatePopupMenu16(void)
1374 {
1375     return HMENU_16( CreatePopupMenu() );
1376 }
1377
1378
1379 /**********************************************************************
1380  *         SetMenuItemBitmaps    (USER.418)
1381  */
1382 BOOL16 WINAPI SetMenuItemBitmaps16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags,
1383                                     HBITMAP16 hNewUnCheck, HBITMAP16 hNewCheck)
1384 {
1385     return SetMenuItemBitmaps( HMENU_32(hMenu), nPos, wFlags,
1386                                HBITMAP_32(hNewUnCheck), HBITMAP_32(hNewCheck) );
1387 }
1388
1389
1390 /***********************************************************************
1391  *           lstrcmp   (USER.430)
1392  */
1393 INT16 WINAPI lstrcmp16( LPCSTR str1, LPCSTR str2 )
1394 {
1395     return strcmp( str1, str2 );
1396 }
1397
1398
1399 /***********************************************************************
1400  *           AnsiUpper   (USER.431)
1401  */
1402 SEGPTR WINAPI AnsiUpper16( SEGPTR strOrChar )
1403 {
1404     /* uppercase only one char if strOrChar < 0x10000 */
1405     if (HIWORD(strOrChar))
1406     {
1407         CharUpperA( MapSL(strOrChar) );
1408         return strOrChar;
1409     }
1410     else return (SEGPTR)CharUpperA( (LPSTR)strOrChar );
1411 }
1412
1413
1414 /***********************************************************************
1415  *           AnsiLower   (USER.432)
1416  */
1417 SEGPTR WINAPI AnsiLower16( SEGPTR strOrChar )
1418 {
1419     /* lowercase only one char if strOrChar < 0x10000 */
1420     if (HIWORD(strOrChar))
1421     {
1422         CharLowerA( MapSL(strOrChar) );
1423         return strOrChar;
1424     }
1425     else return (SEGPTR)CharLowerA( (LPSTR)strOrChar );
1426 }
1427
1428
1429 /***********************************************************************
1430  *           AnsiUpperBuff   (USER.437)
1431  */
1432 UINT16 WINAPI AnsiUpperBuff16( LPSTR str, UINT16 len )
1433 {
1434     CharUpperBuffA( str, len ? len : 65536 );
1435     return len;
1436 }
1437
1438
1439 /***********************************************************************
1440  *           AnsiLowerBuff   (USER.438)
1441  */
1442 UINT16 WINAPI AnsiLowerBuff16( LPSTR str, UINT16 len )
1443 {
1444     CharLowerBuffA( str, len ? len : 65536 );
1445     return len;
1446 }
1447
1448
1449 /*******************************************************************
1450  *              InsertMenuItem   (USER.441)
1451  *
1452  * FIXME: untested
1453  */
1454 BOOL16 WINAPI InsertMenuItem16( HMENU16 hmenu, UINT16 pos, BOOL16 byposition,
1455                                 const MENUITEMINFO16 *mii )
1456 {
1457     MENUITEMINFOA miia;
1458
1459     miia.cbSize        = sizeof(miia);
1460     miia.fMask         = mii->fMask;
1461     miia.dwTypeData    = (LPSTR)mii->dwTypeData;
1462     miia.fType         = mii->fType;
1463     miia.fState        = mii->fState;
1464     miia.wID           = mii->wID;
1465     miia.hSubMenu      = HMENU_32(mii->hSubMenu);
1466     miia.hbmpChecked   = HBITMAP_32(mii->hbmpChecked);
1467     miia.hbmpUnchecked = HBITMAP_32(mii->hbmpUnchecked);
1468     miia.dwItemData    = mii->dwItemData;
1469     miia.cch           = mii->cch;
1470     if (IS_MENU_STRING_ITEM(miia.fType))
1471         miia.dwTypeData = MapSL(mii->dwTypeData);
1472     return InsertMenuItemA( HMENU_32(hmenu), pos, byposition, &miia );
1473 }
1474
1475
1476 /**********************************************************************
1477  *           DrawState    (USER.449)
1478  */
1479 BOOL16 WINAPI DrawState16( HDC16 hdc, HBRUSH16 hbr, DRAWSTATEPROC16 func, LPARAM ldata,
1480                            WPARAM16 wdata, INT16 x, INT16 y, INT16 cx, INT16 cy, UINT16 flags )
1481 {
1482     struct draw_state_info info;
1483     UINT opcode = flags & 0xf;
1484
1485     if (opcode == DST_TEXT || opcode == DST_PREFIXTEXT)
1486     {
1487         /* make sure DrawStateA doesn't try to use ldata as a pointer */
1488         if (!wdata) wdata = strlen( MapSL(ldata) );
1489         if (!cx || !cy)
1490         {
1491             SIZE s;
1492             if (!GetTextExtentPoint32A( HDC_32(hdc), MapSL(ldata), wdata, &s )) return FALSE;
1493             if (!cx) cx = s.cx;
1494             if (!cy) cy = s.cy;
1495         }
1496     }
1497     info.proc  = func;
1498     info.param = ldata;
1499     return DrawStateA( HDC_32(hdc), HBRUSH_32(hbr), draw_state_callback,
1500                        (LPARAM)&info, wdata, x, y, cx, cy, flags );
1501 }
1502
1503
1504 /**********************************************************************
1505  *              CreateIconFromResourceEx (USER.450)
1506  *
1507  * FIXME: not sure about exact parameter types
1508  */
1509 HICON16 WINAPI CreateIconFromResourceEx16(LPBYTE bits, UINT16 cbSize,
1510                                           BOOL16 bIcon, DWORD dwVersion,
1511                                           INT16 width, INT16 height,
1512                                           UINT16 cFlag)
1513 {
1514   return HICON_16(CreateIconFromResourceEx(bits, cbSize, bIcon, dwVersion,
1515                                            width, height, cFlag));
1516 }
1517
1518
1519 /***********************************************************************
1520  *              AdjustWindowRectEx (USER.454)
1521  */
1522 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style, BOOL16 menu, DWORD exStyle )
1523 {
1524     RECT rect32;
1525     BOOL ret;
1526
1527     rect32.left   = rect->left;
1528     rect32.top    = rect->top;
1529     rect32.right  = rect->right;
1530     rect32.bottom = rect->bottom;
1531     ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
1532     rect->left   = rect32.left;
1533     rect->top    = rect32.top;
1534     rect->right  = rect32.right;
1535     rect->bottom = rect32.bottom;
1536     return ret;
1537 }
1538
1539
1540 /***********************************************************************
1541  *              DestroyIcon (USER.457)
1542  */
1543 BOOL16 WINAPI DestroyIcon16(HICON16 hIcon)
1544 {
1545   return DestroyIcon32(hIcon, 0);
1546 }
1547
1548 /***********************************************************************
1549  *              DestroyCursor (USER.458)
1550  */
1551 BOOL16 WINAPI DestroyCursor16(HCURSOR16 hCursor)
1552 {
1553   return DestroyIcon32(hCursor, 0);
1554 }
1555
1556 /*******************************************************************
1557  *                      DRAG_QueryUpdate16
1558  *
1559  * Recursively find a child that contains spDragInfo->pt point
1560  * and send WM_QUERYDROPOBJECT. Helper for DragObject16.
1561  */
1562 static BOOL DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo )
1563 {
1564     BOOL bResult = 0;
1565     WPARAM wParam;
1566     POINT pt, old_pt;
1567     LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
1568     RECT tempRect;
1569     HWND child;
1570
1571     if (!IsWindowEnabled(hQueryWnd)) return FALSE;
1572
1573     old_pt.x = ptrDragInfo->pt.x;
1574     old_pt.y = ptrDragInfo->pt.y;
1575     pt = old_pt;
1576     ScreenToClient( hQueryWnd, &pt );
1577     child = ChildWindowFromPointEx( hQueryWnd, pt, CWP_SKIPINVISIBLE );
1578     if (!child) return FALSE;
1579
1580     if (child != hQueryWnd)
1581     {
1582         wParam = 0;
1583         if (DRAG_QueryUpdate16( child, spDragInfo )) return TRUE;
1584     }
1585     else
1586     {
1587         GetClientRect( hQueryWnd, &tempRect );
1588         wParam = !PtInRect( &tempRect, pt );
1589     }
1590
1591     ptrDragInfo->pt.x = pt.x;
1592     ptrDragInfo->pt.y = pt.y;
1593     ptrDragInfo->hScope = HWND_16(hQueryWnd);
1594
1595     bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, wParam, spDragInfo );
1596
1597     if (!bResult)
1598     {
1599         ptrDragInfo->pt.x = old_pt.x;
1600         ptrDragInfo->pt.y = old_pt.y;
1601     }
1602     return bResult;
1603 }
1604
1605
1606 /******************************************************************************
1607  *              DragObject (USER.464)
1608  */
1609 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
1610                            HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
1611 {
1612     MSG msg;
1613     LPDRAGINFO16 lpDragInfo;
1614     SEGPTR      spDragInfo;
1615     HCURSOR     hOldCursor=0, hBummer=0;
1616     HGLOBAL16   hDragInfo  = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
1617     HCURSOR     hCurrentCursor = 0;
1618     HWND16      hCurrentWnd = 0;
1619
1620     lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
1621     spDragInfo = WOWGlobalLock16(hDragInfo);
1622
1623     if( !lpDragInfo || !spDragInfo ) return 0L;
1624
1625     if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
1626     {
1627         GlobalFree16(hDragInfo);
1628         return 0L;
1629     }
1630
1631     if(hCursor) hOldCursor = SetCursor(HCURSOR_32(hCursor));
1632
1633     lpDragInfo->hWnd   = hWnd;
1634     lpDragInfo->hScope = 0;
1635     lpDragInfo->wFlags = wObj;
1636     lpDragInfo->hList  = szList; /* near pointer! */
1637     lpDragInfo->hOfStruct = hOfStruct;
1638     lpDragInfo->l = 0L;
1639
1640     SetCapture( HWND_32(hWnd) );
1641     ShowCursor( TRUE );
1642
1643     do
1644     {
1645         GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
1646
1647        *(lpDragInfo+1) = *lpDragInfo;
1648
1649         lpDragInfo->pt.x = msg.pt.x;
1650         lpDragInfo->pt.y = msg.pt.y;
1651
1652         /* update DRAGINFO struct */
1653         if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 )
1654             hCurrentCursor = HCURSOR_32(hCursor);
1655         else
1656         {
1657             hCurrentCursor = hBummer;
1658             lpDragInfo->hScope = 0;
1659         }
1660         if( hCurrentCursor )
1661             SetCursor(hCurrentCursor);
1662
1663         /* send WM_DRAGLOOP */
1664         SendMessage16( hWnd, WM_DRAGLOOP, (WPARAM16)(hCurrentCursor != hBummer),
1665                                           (LPARAM) spDragInfo );
1666         /* send WM_DRAGSELECT or WM_DRAGMOVE */
1667         if( hCurrentWnd != lpDragInfo->hScope )
1668         {
1669             if( hCurrentWnd )
1670                 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
1671                        (LPARAM)MAKELONG(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
1672                                         HIWORD(spDragInfo)) );
1673             hCurrentWnd = lpDragInfo->hScope;
1674             if( hCurrentWnd )
1675                 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, (LPARAM)spDragInfo);
1676         }
1677         else
1678             if( hCurrentWnd )
1679                 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, (LPARAM)spDragInfo);
1680
1681     } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
1682
1683     ReleaseCapture();
1684     ShowCursor( FALSE );
1685
1686     if( hCursor ) SetCursor(hOldCursor);
1687
1688     if( hCurrentCursor != hBummer )
1689         msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
1690                                    (WPARAM16)hWnd, (LPARAM)spDragInfo );
1691     else
1692         msg.lParam = 0;
1693     GlobalFree16(hDragInfo);
1694
1695     return (DWORD)(msg.lParam);
1696 }
1697
1698
1699 /***********************************************************************
1700  *              DrawFocusRect (USER.466)
1701  */
1702 void WINAPI DrawFocusRect16( HDC16 hdc, const RECT16* rc )
1703 {
1704     RECT rect32;
1705
1706     rect32.left   = rc->left;
1707     rect32.top    = rc->top;
1708     rect32.right  = rc->right;
1709     rect32.bottom = rc->bottom;
1710     DrawFocusRect( HDC_32(hdc), &rect32 );
1711 }
1712
1713
1714 /***********************************************************************
1715  *           AnsiNext   (USER.472)
1716  */
1717 SEGPTR WINAPI AnsiNext16(SEGPTR current)
1718 {
1719     char *ptr = MapSL(current);
1720     return current + (CharNextA(ptr) - ptr);
1721 }
1722
1723
1724 /***********************************************************************
1725  *           AnsiPrev   (USER.473)
1726  */
1727 SEGPTR WINAPI AnsiPrev16( LPCSTR start, SEGPTR current )
1728 {
1729     char *ptr = MapSL(current);
1730     return current - (ptr - CharPrevA( start, ptr ));
1731 }
1732
1733
1734 /****************************************************************************
1735  *              GetKeyboardLayoutName (USER.477)
1736  */
1737 INT16 WINAPI GetKeyboardLayoutName16( LPSTR name )
1738 {
1739     return GetKeyboardLayoutNameA( name );
1740 }
1741
1742
1743 /***********************************************************************
1744  *           FormatMessage   (USER.606)
1745  */
1746 DWORD WINAPI FormatMessage16(
1747     DWORD   dwFlags,
1748     SEGPTR lpSource,     /* [in] NOTE: not always a valid pointer */
1749     WORD   dwMessageId,
1750     WORD   dwLanguageId,
1751     LPSTR  lpBuffer,     /* [out] NOTE: *((HLOCAL16*)) for FORMAT_MESSAGE_ALLOCATE_BUFFER*/
1752     WORD   nSize,
1753     LPDWORD args )       /* [in] NOTE: va_list *args */
1754 {
1755 #ifdef __i386__
1756 /* This implementation is completely dependent on the format of the va_list on x86 CPUs */
1757     LPSTR       target,t;
1758     DWORD       talloced;
1759     LPSTR       from,f;
1760     DWORD       width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
1761     BOOL        eos = FALSE;
1762     LPSTR       allocstring = NULL;
1763
1764     TRACE("(0x%x,%x,%d,0x%x,%p,%d,%p)\n",
1765           dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
1766         if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
1767                 && (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)) return 0;
1768         if ((dwFlags & FORMAT_MESSAGE_FROM_STRING)
1769                 &&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
1770                         || (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0;
1771
1772     if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK)
1773         FIXME("line wrapping (%u) not supported.\n", width);
1774     from = NULL;
1775     if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
1776     {
1777         char *source = MapSL(lpSource);
1778         from = HeapAlloc( GetProcessHeap(), 0, strlen(source)+1 );
1779         strcpy( from, source );
1780     }
1781     else if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
1782         from = HeapAlloc( GetProcessHeap(),0,200 );
1783         sprintf(from,"Systemmessage, messageid = 0x%08x\n",dwMessageId);
1784     }
1785     else if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
1786         INT16   bufsize;
1787         HINSTANCE16 hinst16 = ((HINSTANCE16)lpSource & 0xffff);
1788
1789         dwMessageId &= 0xFFFF;
1790         bufsize=LoadString16(hinst16,dwMessageId,NULL,0);
1791         if (bufsize) {
1792             from = HeapAlloc( GetProcessHeap(), 0, bufsize +1);
1793             LoadString16(hinst16,dwMessageId,from,bufsize+1);
1794         }
1795     }
1796     target      = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
1797     t   = target;
1798     talloced= 100;
1799
1800 #define ADD_TO_T(c) \
1801         *t++=c;\
1802         if (t-target == talloced) {\
1803                 target  = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
1804                 t       = target+talloced;\
1805                 talloced*=2;\
1806         }
1807
1808     if (from) {
1809         f=from;
1810         while (*f && !eos) {
1811             if (*f=='%') {
1812                 int     insertnr;
1813                 char    *fmtstr,*x,*lastf;
1814                 DWORD   *argliststart;
1815
1816                 fmtstr = NULL;
1817                 lastf = f;
1818                 f++;
1819                 if (!*f) {
1820                     ADD_TO_T('%');
1821                     continue;
1822                 }
1823                 switch (*f) {
1824                 case '1':case '2':case '3':case '4':case '5':
1825                 case '6':case '7':case '8':case '9':
1826                     insertnr=*f-'0';
1827                     switch (f[1]) {
1828                     case '0':case '1':case '2':case '3':
1829                     case '4':case '5':case '6':case '7':
1830                     case '8':case '9':
1831                         f++;
1832                         insertnr=insertnr*10+*f-'0';
1833                         f++;
1834                         break;
1835                     default:
1836                         f++;
1837                         break;
1838                     }
1839                     if (*f=='!') {
1840                         f++;
1841                         if (NULL!=(x=strchr(f,'!'))) {
1842                             *x='\0';
1843                             fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
1844                             sprintf(fmtstr,"%%%s",f);
1845                             f=x+1;
1846                         } else {
1847                             fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
1848                             sprintf(fmtstr,"%%%s",f);
1849                             f+=strlen(f); /*at \0*/
1850                         }
1851                     }
1852                     else
1853                     {
1854                         if(!args) break;
1855                         fmtstr=HeapAlloc( GetProcessHeap(), 0, 3 );
1856                         strcpy( fmtstr, "%s" );
1857                     }
1858                     if (args) {
1859                         int     ret;
1860                         int     sz;
1861                         LPSTR   b = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz = 100);
1862
1863                         argliststart=args+insertnr-1;
1864
1865                         /* CMF - This makes a BIG assumption about va_list */
1866                         while ((ret = vsnprintf(b, sz, fmtstr, (va_list) argliststart) < 0) || (ret >= sz)) {
1867                             sz = (ret == -1 ? sz + 100 : ret + 1);
1868                             b = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, b, sz);
1869                         }
1870                         for (x=b; *x; x++) ADD_TO_T(*x);
1871                         HeapFree(GetProcessHeap(), 0, b);
1872                     } else {
1873                         /* NULL args - copy formatstr
1874                          * (probably wrong)
1875                          */
1876                         while ((lastf<f)&&(*lastf)) {
1877                             ADD_TO_T(*lastf++);
1878                         }
1879                     }
1880                     HeapFree(GetProcessHeap(),0,fmtstr);
1881                     break;
1882                 case '0': /* Just stop processing format string */
1883                     eos = TRUE;
1884                     f++;
1885                     break;
1886                 case 'n': /* 16 bit version just outputs 'n' */
1887                 default:
1888                     ADD_TO_T(*f++);
1889                     break;
1890                 }
1891             } else { /* '\n' or '\r' gets mapped to "\r\n" */
1892                 if(*f == '\n' || *f == '\r') {
1893                     if (width == 0) {
1894                         ADD_TO_T('\r');
1895                         ADD_TO_T('\n');
1896                         if(*f++ == '\r' && *f == '\n')
1897                             f++;
1898                     }
1899                 } else {
1900                     ADD_TO_T(*f++);
1901                 }
1902             }
1903         }
1904         *t='\0';
1905     }
1906     talloced = strlen(target)+1;
1907     if (nSize && talloced<nSize) {
1908         target = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
1909     }
1910     TRACE("-- %s\n",debugstr_a(target));
1911     if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
1912         /* nSize is the MINIMUM size */
1913         HLOCAL16 h = LocalAlloc16(LPTR,talloced);
1914         SEGPTR ptr = LocalLock16(h);
1915         allocstring = MapSL( ptr );
1916         memcpy( allocstring,target,talloced);
1917         LocalUnlock16( h );
1918         *((HLOCAL16*)lpBuffer) = h;
1919     } else
1920         lstrcpynA(lpBuffer,target,nSize);
1921     HeapFree(GetProcessHeap(),0,target);
1922     HeapFree(GetProcessHeap(),0,from);
1923     return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
1924         strlen(allocstring):
1925         strlen(lpBuffer);
1926 #else
1927         return 0;
1928 #endif /* __i386__ */
1929 }
1930 #undef ADD_TO_T
1931
1932
1933 /***********************************************************************
1934  *              ChangeDisplaySettings (USER.620)
1935  */
1936 LONG WINAPI ChangeDisplaySettings16( LPDEVMODEA devmode, DWORD flags )
1937 {
1938     return ChangeDisplaySettingsA( devmode, flags );
1939 }
1940
1941
1942 /***********************************************************************
1943  *              EnumDisplaySettings (USER.621)
1944  */
1945 BOOL16 WINAPI EnumDisplaySettings16( LPCSTR name, DWORD n, LPDEVMODEA devmode )
1946 {
1947     return EnumDisplaySettingsA( name, n, devmode );
1948 }
1949
1950 /**********************************************************************
1951  *          DrawFrameControl  (USER.656)
1952  */
1953 BOOL16 WINAPI DrawFrameControl16( HDC16 hdc, LPRECT16 rc, UINT16 uType, UINT16 uState )
1954 {
1955     RECT rect32;
1956     BOOL ret;
1957
1958     rect32.left   = rc->left;
1959     rect32.top    = rc->top;
1960     rect32.right  = rc->right;
1961     rect32.bottom = rc->bottom;
1962     ret = DrawFrameControl( HDC_32(hdc), &rect32, uType, uState );
1963     rc->left   = rect32.left;
1964     rc->top    = rect32.top;
1965     rc->right  = rect32.right;
1966     rc->bottom = rect32.bottom;
1967     return ret;
1968 }
1969
1970 /**********************************************************************
1971  *          DrawEdge   (USER.659)
1972  */
1973 BOOL16 WINAPI DrawEdge16( HDC16 hdc, LPRECT16 rc, UINT16 edge, UINT16 flags )
1974 {
1975     RECT rect32;
1976     BOOL ret;
1977
1978     rect32.left   = rc->left;
1979     rect32.top    = rc->top;
1980     rect32.right  = rc->right;
1981     rect32.bottom = rc->bottom;
1982     ret = DrawEdge( HDC_32(hdc), &rect32, edge, flags );
1983     rc->left   = rect32.left;
1984     rc->top    = rect32.top;
1985     rc->right  = rect32.right;
1986     rc->bottom = rect32.bottom;
1987     return ret;
1988 }
1989
1990 /**********************************************************************
1991  *              CheckMenuRadioItem (USER.666)
1992  */
1993 BOOL16 WINAPI CheckMenuRadioItem16(HMENU16 hMenu, UINT16 first, UINT16 last,
1994                                    UINT16 check, BOOL16 bypos)
1995 {
1996      return CheckMenuRadioItem( HMENU_32(hMenu), first, last, check, bypos );
1997 }