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