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