msdaps: Add server side stubs for IAccessor.
[wine] / dlls / user.exe16 / user.c
1 /*
2  * Misc 16-bit USER functions
3  *
4  * Copyright 1993, 1996 Alexandre Julliard
5  * Copyright 2002 Patrik Stridvall
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26
27 #define OEMRESOURCE
28
29 #include "wine/winuser16.h"
30 #include "windef.h"
31 #include "winbase.h"
32 #include "wownt32.h"
33 #include "user_private.h"
34 #include "wine/list.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 #define HGDIOBJ_16(h32)         (LOWORD(h32))
42
43 /* handle16 to handle conversions */
44 #define HANDLE_32(h16)          ((HANDLE)(ULONG_PTR)(h16))
45 #define HGDIOBJ_32(h16)         ((HGDIOBJ)(ULONG_PTR)(h16))
46
47 #define IS_MENU_STRING_ITEM(flags) \
48     (((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR)) == MF_STRING)
49
50 /* UserSeeUserDo parameters */
51 #define USUD_LOCALALLOC        0x0001
52 #define USUD_LOCALFREE         0x0002
53 #define USUD_LOCALCOMPACT      0x0003
54 #define USUD_LOCALHEAP         0x0004
55 #define USUD_FIRSTCLASS        0x0005
56
57 #define CID_RESOURCE  0x0001
58 #define CID_WIN32     0x0004
59 #define CID_NONSHARED 0x0008
60
61 WORD USER_HeapSel = 0;  /* USER heap selector */
62
63 struct gray_string_info
64 {
65     GRAYSTRINGPROC16 proc;
66     LPARAM           param;
67     char             str[1];
68 };
69
70 /* callback for 16-bit gray string proc with opaque pointer */
71 static BOOL CALLBACK gray_string_callback( HDC hdc, LPARAM param, INT len )
72 {
73     const struct gray_string_info *info = (struct gray_string_info *)param;
74     WORD args[4];
75     DWORD ret;
76
77     args[3] = HDC_16(hdc);
78     args[2] = HIWORD(info->param);
79     args[1] = LOWORD(info->param);
80     args[0] = len;
81     WOWCallback16Ex( (DWORD)info->proc, WCB16_PASCAL, sizeof(args), args, &ret );
82     return LOWORD(ret);
83 }
84
85 /* callback for 16-bit gray string proc with string pointer */
86 static BOOL CALLBACK gray_string_callback_ptr( HDC hdc, LPARAM param, INT len )
87 {
88     const struct gray_string_info *info;
89     char *str = (char *)param;
90
91     info = (struct gray_string_info *)(str - offsetof( struct gray_string_info, str ));
92     return gray_string_callback( hdc, (LPARAM)info, len );
93 }
94
95 struct draw_state_info
96 {
97     DRAWSTATEPROC16 proc;
98     LPARAM          param;
99 };
100
101 /* callback for 16-bit DrawState functions */
102 static BOOL CALLBACK draw_state_callback( HDC hdc, LPARAM lparam, WPARAM wparam, int cx, int cy )
103 {
104     const struct draw_state_info *info = (struct draw_state_info *)lparam;
105     WORD args[6];
106     DWORD ret;
107
108     args[5] = HDC_16(hdc);
109     args[4] = HIWORD(info->param);
110     args[3] = LOWORD(info->param);
111     args[2] = wparam;
112     args[1] = cx;
113     args[0] = cy;
114     WOWCallback16Ex( (DWORD)info->proc, WCB16_PASCAL, sizeof(args), args, &ret );
115     return LOWORD(ret);
116 }
117
118 /* This function is a copy of the one in objects/font.c */
119 static void logfont_32_to_16( const LOGFONTA* font32, LPLOGFONT16 font16 )
120 {
121     font16->lfHeight = font32->lfHeight;
122     font16->lfWidth = font32->lfWidth;
123     font16->lfEscapement = font32->lfEscapement;
124     font16->lfOrientation = font32->lfOrientation;
125     font16->lfWeight = font32->lfWeight;
126     font16->lfItalic = font32->lfItalic;
127     font16->lfUnderline = font32->lfUnderline;
128     font16->lfStrikeOut = font32->lfStrikeOut;
129     font16->lfCharSet = font32->lfCharSet;
130     font16->lfOutPrecision = font32->lfOutPrecision;
131     font16->lfClipPrecision = font32->lfClipPrecision;
132     font16->lfQuality = font32->lfQuality;
133     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
134     lstrcpynA( font16->lfFaceName, font32->lfFaceName, LF_FACESIZE );
135 }
136
137 static int get_bitmap_width_bytes( int width, int bpp )
138 {
139     switch(bpp)
140     {
141     case 1:
142         return 2 * ((width+15) / 16);
143     case 4:
144         return 2 * ((width+3) / 4);
145     case 24:
146         width *= 3;
147         /* fall through */
148     case 8:
149         return width + (width & 1);
150     case 16:
151     case 15:
152         return width * 2;
153     case 32:
154         return width * 4;
155     default:
156         WARN("Unknown depth %d, please report.\n", bpp );
157     }
158     return -1;
159 }
160
161 /***********************************************************************
162  * Helper for wsprintf16
163  */
164
165 #define WPRINTF_LEFTALIGN   0x0001  /* Align output on the left ('-' prefix) */
166 #define WPRINTF_PREFIX_HEX  0x0002  /* Prefix hex with 0x ('#' prefix) */
167 #define WPRINTF_ZEROPAD     0x0004  /* Pad with zeros ('0' prefix) */
168 #define WPRINTF_LONG        0x0008  /* Long arg ('l' prefix) */
169 #define WPRINTF_SHORT       0x0010  /* Short arg ('h' prefix) */
170 #define WPRINTF_UPPER_HEX   0x0020  /* Upper-case hex ('X' specifier) */
171
172 typedef enum
173 {
174     WPR_UNKNOWN,
175     WPR_CHAR,
176     WPR_STRING,
177     WPR_SIGNED,
178     WPR_UNSIGNED,
179     WPR_HEXA
180 } WPRINTF_TYPE;
181
182 typedef struct
183 {
184     UINT         flags;
185     UINT         width;
186     UINT         precision;
187     WPRINTF_TYPE type;
188 } WPRINTF_FORMAT;
189
190 static INT parse_format( LPCSTR format, WPRINTF_FORMAT *res )
191 {
192     LPCSTR p = format;
193
194     res->flags = 0;
195     res->width = 0;
196     res->precision = 0;
197     if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; }
198     if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; }
199     if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; }
200     while ((*p >= '0') && (*p <= '9'))  /* width field */
201     {
202         res->width = res->width * 10 + *p - '0';
203         p++;
204     }
205     if (*p == '.')  /* precision field */
206     {
207         p++;
208         while ((*p >= '0') && (*p <= '9'))
209         {
210             res->precision = res->precision * 10 + *p - '0';
211             p++;
212         }
213     }
214     if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; }
215     else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; }
216     switch(*p)
217     {
218     case 'c':
219     case 'C':  /* no Unicode in Win16 */
220         res->type = WPR_CHAR;
221         break;
222     case 's':
223     case 'S':
224         res->type = WPR_STRING;
225         break;
226     case 'd':
227     case 'i':
228         res->type = WPR_SIGNED;
229         break;
230     case 'u':
231         res->type = WPR_UNSIGNED;
232         break;
233     case 'p':
234         res->width = 8;
235         res->flags |= WPRINTF_ZEROPAD;
236         /* fall through */
237     case 'X':
238         res->flags |= WPRINTF_UPPER_HEX;
239         /* fall through */
240     case 'x':
241         res->type = WPR_HEXA;
242         break;
243     default: /* unknown format char */
244         res->type = WPR_UNKNOWN;
245         p--;  /* print format as normal char */
246         break;
247     }
248     return (INT)(p - format) + 1;
249 }
250
251
252 /**********************************************************************
253  * Management of the 16-bit cursors and icons
254  */
255
256 struct cache_entry
257 {
258     struct list entry;
259     HINSTANCE16 inst;
260     HRSRC16     rsrc;
261     HRSRC16     group;
262     HICON16     icon;
263     INT         count;
264 };
265
266 static struct list icon_cache = LIST_INIT( icon_cache );
267
268 static const WORD ICON_HOTSPOT = 0x4242;
269
270 static HICON16 alloc_icon_handle( unsigned int size )
271 {
272     HGLOBAL16 handle = GlobalAlloc16( GMEM_MOVEABLE, size );
273     FarSetOwner16( handle, 0 );
274     return handle;
275 }
276
277 static CURSORICONINFO *get_icon_ptr( HICON16 handle )
278 {
279     return GlobalLock16( handle );
280 }
281
282 static void release_icon_ptr( HICON16 handle, CURSORICONINFO *ptr )
283 {
284     GlobalUnlock16( handle );
285 }
286
287 static int free_icon_handle( HICON16 handle )
288 {
289     return GlobalFree16( handle );
290 }
291
292 HICON get_icon_32( HICON16 icon16 )
293 {
294     return (HICON)(ULONG_PTR)icon16;
295 }
296
297 HICON16 get_icon_16( HICON icon )
298 {
299     return LOWORD( icon );
300 }
301
302 static void add_shared_icon( HINSTANCE16 inst, HRSRC16 rsrc, HRSRC16 group, HICON16 icon )
303 {
304     struct cache_entry *cache = HeapAlloc( GetProcessHeap(), 0, sizeof(*cache) );
305
306     if (!cache) return;
307     cache->inst  = inst;
308     cache->rsrc  = rsrc;
309     cache->group = group;
310     cache->icon  = icon;
311     cache->count = 1;
312     list_add_tail( &icon_cache, &cache->entry );
313 }
314
315 static HICON16 find_shared_icon( HINSTANCE16 inst, HRSRC16 rsrc )
316 {
317     struct cache_entry *cache;
318
319     LIST_FOR_EACH_ENTRY( cache, &icon_cache, struct cache_entry, entry )
320     {
321         if (cache->inst != inst || cache->rsrc != rsrc) continue;
322         cache->count++;
323         return cache->icon;
324     }
325     return 0;
326 }
327
328 static int release_shared_icon( HICON16 icon )
329 {
330     struct cache_entry *cache;
331
332     LIST_FOR_EACH_ENTRY( cache, &icon_cache, struct cache_entry, entry )
333     {
334         if (cache->icon != icon) continue;
335         if (!cache->count) return 0;
336         return --cache->count;
337     }
338     return -1;
339 }
340
341 static void free_module_icons( HINSTANCE16 inst )
342 {
343     struct cache_entry *cache, *next;
344
345     LIST_FOR_EACH_ENTRY_SAFE( cache, next, &icon_cache, struct cache_entry, entry )
346     {
347         if (cache->inst != inst) continue;
348         list_remove( &cache->entry );
349         free_icon_handle( cache->icon );
350         HeapFree( GetProcessHeap(), 0, cache );
351     }
352 }
353
354 /**********************************************************************
355  * Management of the 16-bit clipboard formats
356  */
357
358 struct clipboard_format
359 {
360     struct list entry;
361     UINT        format;
362     HANDLE16    data;
363 };
364
365 static struct list clipboard_formats = LIST_INIT( clipboard_formats );
366
367 static void set_clipboard_format( UINT format, HANDLE16 data )
368 {
369     struct clipboard_format *fmt;
370
371     /* replace it if it exists already */
372     LIST_FOR_EACH_ENTRY( fmt, &clipboard_formats, struct clipboard_format, entry )
373     {
374         if (fmt->format != format) continue;
375         GlobalFree16( fmt->data );
376         fmt->data = data;
377         return;
378     }
379
380     if ((fmt = HeapAlloc( GetProcessHeap(), 0, sizeof(*fmt) )))
381     {
382         fmt->format = format;
383         fmt->data = data;
384         list_add_tail( &clipboard_formats, &fmt->entry );
385     }
386 }
387
388 static void free_clipboard_formats(void)
389 {
390     struct list *head;
391
392     while ((head = list_head( &clipboard_formats )))
393     {
394         struct clipboard_format *fmt = LIST_ENTRY( head, struct clipboard_format, entry );
395         list_remove( &fmt->entry );
396         GlobalFree16( fmt->data );
397         HeapFree( GetProcessHeap(), 0, fmt );
398     }
399 }
400
401
402 /**********************************************************************
403  *              DllMain
404  */
405 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
406 {
407     if (reason == DLL_PROCESS_ATTACH) LoadLibrary16( "user.exe" );
408     return TRUE;
409 }
410
411
412 /**********************************************************************
413  *              InitApp (USER.5)
414  */
415 INT16 WINAPI InitApp16( HINSTANCE16 hInstance )
416 {
417     /* Create task message queue */
418     return (InitThreadInput16( 0, 0 ) != 0);
419 }
420
421
422 /***********************************************************************
423  *              ExitWindows (USER.7)
424  */
425 BOOL16 WINAPI ExitWindows16( DWORD dwReturnCode, UINT16 wReserved )
426 {
427     return ExitWindowsEx( EWX_LOGOFF, 0xffffffff );
428 }
429
430
431 /***********************************************************************
432  *              GetTimerResolution (USER.14)
433  */
434 LONG WINAPI GetTimerResolution16(void)
435 {
436     return (1000);
437 }
438
439
440 /***********************************************************************
441  *              ClipCursor (USER.16)
442  */
443 BOOL16 WINAPI ClipCursor16( const RECT16 *rect )
444 {
445     RECT rect32;
446
447     if (!rect) return ClipCursor( NULL );
448     rect32.left   = rect->left;
449     rect32.top    = rect->top;
450     rect32.right  = rect->right;
451     rect32.bottom = rect->bottom;
452     return ClipCursor( &rect32 );
453 }
454
455
456 /***********************************************************************
457  *              GetCursorPos (USER.17)
458  */
459 BOOL16 WINAPI GetCursorPos16( POINT16 *pt )
460 {
461     POINT pos;
462     if (!pt) return 0;
463     GetCursorPos(&pos);
464     pt->x = pos.x;
465     pt->y = pos.y;
466     return 1;
467 }
468
469
470 /*******************************************************************
471  *              AnyPopup (USER.52)
472  */
473 BOOL16 WINAPI AnyPopup16(void)
474 {
475     return AnyPopup();
476 }
477
478
479 /***********************************************************************
480  *              SetCursor (USER.69)
481  */
482 HCURSOR16 WINAPI SetCursor16(HCURSOR16 hCursor)
483 {
484   return get_icon_16( SetCursor( get_icon_32(hCursor) ));
485 }
486
487
488 /***********************************************************************
489  *              SetCursorPos (USER.70)
490  */
491 void WINAPI SetCursorPos16( INT16 x, INT16 y )
492 {
493     SetCursorPos( x, y );
494 }
495
496
497 /***********************************************************************
498  *              ShowCursor (USER.71)
499  */
500 INT16 WINAPI ShowCursor16(BOOL16 bShow)
501 {
502   return ShowCursor(bShow);
503 }
504
505
506 /***********************************************************************
507  *              SetRect (USER.72)
508  */
509 void WINAPI SetRect16( LPRECT16 rect, INT16 left, INT16 top, INT16 right, INT16 bottom )
510 {
511     rect->left   = left;
512     rect->right  = right;
513     rect->top    = top;
514     rect->bottom = bottom;
515 }
516
517
518 /***********************************************************************
519  *              SetRectEmpty (USER.73)
520  */
521 void WINAPI SetRectEmpty16( LPRECT16 rect )
522 {
523     rect->left = rect->right = rect->top = rect->bottom = 0;
524 }
525
526
527 /***********************************************************************
528  *              CopyRect (USER.74)
529  */
530 BOOL16 WINAPI CopyRect16( RECT16 *dest, const RECT16 *src )
531 {
532     *dest = *src;
533     return TRUE;
534 }
535
536
537 /***********************************************************************
538  *              IsRectEmpty (USER.75)
539  *
540  * Bug compat: Windows checks for 0 or negative width/height.
541  */
542 BOOL16 WINAPI IsRectEmpty16( const RECT16 *rect )
543 {
544     return ((rect->left >= rect->right) || (rect->top >= rect->bottom));
545 }
546
547
548 /***********************************************************************
549  *              PtInRect (USER.76)
550  */
551 BOOL16 WINAPI PtInRect16( const RECT16 *rect, POINT16 pt )
552 {
553     return ((pt.x >= rect->left) && (pt.x < rect->right) &&
554             (pt.y >= rect->top) && (pt.y < rect->bottom));
555 }
556
557
558 /***********************************************************************
559  *              OffsetRect (USER.77)
560  */
561 void WINAPI OffsetRect16( LPRECT16 rect, INT16 x, INT16 y )
562 {
563     rect->left   += x;
564     rect->right  += x;
565     rect->top    += y;
566     rect->bottom += y;
567 }
568
569
570 /***********************************************************************
571  *              InflateRect (USER.78)
572  */
573 void WINAPI InflateRect16( LPRECT16 rect, INT16 x, INT16 y )
574 {
575     rect->left   -= x;
576     rect->top    -= y;
577     rect->right  += x;
578     rect->bottom += y;
579 }
580
581
582 /***********************************************************************
583  *              IntersectRect (USER.79)
584  */
585 BOOL16 WINAPI IntersectRect16( LPRECT16 dest, const RECT16 *src1,
586                                const RECT16 *src2 )
587 {
588     if (IsRectEmpty16(src1) || IsRectEmpty16(src2) ||
589         (src1->left >= src2->right) || (src2->left >= src1->right) ||
590         (src1->top >= src2->bottom) || (src2->top >= src1->bottom))
591     {
592         SetRectEmpty16( dest );
593         return FALSE;
594     }
595     dest->left   = max( src1->left, src2->left );
596     dest->right  = min( src1->right, src2->right );
597     dest->top    = max( src1->top, src2->top );
598     dest->bottom = min( src1->bottom, src2->bottom );
599     return TRUE;
600 }
601
602
603 /***********************************************************************
604  *              UnionRect (USER.80)
605  */
606 BOOL16 WINAPI UnionRect16( LPRECT16 dest, const RECT16 *src1,
607                            const RECT16 *src2 )
608 {
609     if (IsRectEmpty16(src1))
610     {
611         if (IsRectEmpty16(src2))
612         {
613             SetRectEmpty16( dest );
614             return FALSE;
615         }
616         else *dest = *src2;
617     }
618     else
619     {
620         if (IsRectEmpty16(src2)) *dest = *src1;
621         else
622         {
623             dest->left   = min( src1->left, src2->left );
624             dest->right  = max( src1->right, src2->right );
625             dest->top    = min( src1->top, src2->top );
626             dest->bottom = max( src1->bottom, src2->bottom );
627         }
628     }
629     return TRUE;
630 }
631
632
633 /***********************************************************************
634  *              FillRect (USER.81)
635  * NOTE
636  *   The Win16 variant doesn't support special color brushes like
637  *   the Win32 one, despite the fact that Win16, as well as Win32,
638  *   supports special background brushes for a window class.
639  */
640 INT16 WINAPI FillRect16( HDC16 hdc, const RECT16 *rect, HBRUSH16 hbrush )
641 {
642     HBRUSH prevBrush;
643
644     /* coordinates are logical so we cannot fast-check 'rect',
645      * it will be done later in the PatBlt().
646      */
647
648     if (!(prevBrush = SelectObject( HDC_32(hdc), HBRUSH_32(hbrush) ))) return 0;
649     PatBlt( HDC_32(hdc), rect->left, rect->top,
650               rect->right - rect->left, rect->bottom - rect->top, PATCOPY );
651     SelectObject( HDC_32(hdc), prevBrush );
652     return 1;
653 }
654
655
656 /***********************************************************************
657  *              InvertRect (USER.82)
658  */
659 void WINAPI InvertRect16( HDC16 hdc, const RECT16 *rect )
660 {
661     PatBlt( HDC_32(hdc), rect->left, rect->top,
662               rect->right - rect->left, rect->bottom - rect->top, DSTINVERT );
663 }
664
665
666 /***********************************************************************
667  *              FrameRect (USER.83)
668  */
669 INT16 WINAPI FrameRect16( HDC16 hdc, const RECT16 *rect16, HBRUSH16 hbrush )
670 {
671     RECT rect;
672
673     rect.left   = rect16->left;
674     rect.top    = rect16->top;
675     rect.right  = rect16->right;
676     rect.bottom = rect16->bottom;
677     return FrameRect( HDC_32(hdc), &rect, HBRUSH_32(hbrush) );
678 }
679
680
681 /***********************************************************************
682  *              DrawIcon (USER.84)
683  */
684 BOOL16 WINAPI DrawIcon16(HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon)
685 {
686   return DrawIcon(HDC_32(hdc), x, y, get_icon_32(hIcon) );
687 }
688
689
690 /***********************************************************************
691  *           DrawText    (USER.85)
692  */
693 INT16 WINAPI DrawText16( HDC16 hdc, LPCSTR str, INT16 count, LPRECT16 rect, UINT16 flags )
694 {
695     INT16 ret;
696
697     if (rect)
698     {
699         RECT rect32;
700
701         rect32.left   = rect->left;
702         rect32.top    = rect->top;
703         rect32.right  = rect->right;
704         rect32.bottom = rect->bottom;
705         ret = DrawTextA( HDC_32(hdc), str, count, &rect32, flags );
706         rect->left   = rect32.left;
707         rect->top    = rect32.top;
708         rect->right  = rect32.right;
709         rect->bottom = rect32.bottom;
710     }
711     else ret = DrawTextA( HDC_32(hdc), str, count, NULL, flags);
712     return ret;
713 }
714
715
716 /***********************************************************************
717  *              IconSize (USER.86)
718  *
719  * See "Undocumented Windows". Used by W2.0 paint.exe.
720  */
721 DWORD WINAPI IconSize16(void)
722 {
723   return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON));
724 }
725
726
727 /***********************************************************************
728  *              AdjustWindowRect (USER.102)
729  */
730 BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu )
731 {
732     return AdjustWindowRectEx16( rect, style, menu, 0 );
733 }
734
735
736 /***********************************************************************
737  *              MessageBeep (USER.104)
738  */
739 void WINAPI MessageBeep16( UINT16 i )
740 {
741     MessageBeep( i );
742 }
743
744
745 /**************************************************************************
746  *              CloseClipboard (USER.138)
747  */
748 BOOL16 WINAPI CloseClipboard16(void)
749 {
750     BOOL ret = CloseClipboard();
751     if (ret) free_clipboard_formats();
752     return ret;
753 }
754
755
756 /**************************************************************************
757  *              EmptyClipboard (USER.139)
758  */
759 BOOL16 WINAPI EmptyClipboard16(void)
760 {
761     BOOL ret = EmptyClipboard();
762     if (ret) free_clipboard_formats();
763     return ret;
764 }
765
766
767 /**************************************************************************
768  *              SetClipboardData (USER.141)
769  */
770 HANDLE16 WINAPI SetClipboardData16( UINT16 format, HANDLE16 data16 )
771 {
772     HANDLE data32 = 0;
773
774     switch (format)
775     {
776     case CF_BITMAP:
777     case CF_PALETTE:
778         data32 = HGDIOBJ_32( data16 );
779         break;
780
781     case CF_METAFILEPICT:
782     {
783         METAHEADER *header;
784         METAFILEPICT *pict32;
785         METAFILEPICT16 *pict16 = GlobalLock16( data16 );
786
787         if (pict16)
788         {
789             if (!(data32 = GlobalAlloc( GMEM_MOVEABLE, sizeof(*pict32) ))) return 0;
790             pict32 = GlobalLock( data32 );
791             pict32->mm = pict16->mm;
792             pict32->xExt = pict16->xExt;
793             pict32->yExt = pict16->yExt;
794             header = GlobalLock16( pict16->hMF );
795             pict32->hMF = SetMetaFileBitsEx( header->mtSize * 2, (BYTE *)header );
796             GlobalUnlock16( pict16->hMF );
797             GlobalUnlock( data32 );
798         }
799         set_clipboard_format( format, data16 );
800         break;
801     }
802
803     case CF_ENHMETAFILE:
804         FIXME( "enhmetafile not supported in 16-bit\n" );
805         return 0;
806
807     default:
808         if (format >= CF_GDIOBJFIRST && format <= CF_GDIOBJLAST)
809             data32 = HGDIOBJ_32( data16 );
810         else if (format >= CF_PRIVATEFIRST && format <= CF_PRIVATELAST)
811             data32 = HANDLE_32( data16 );
812         else
813         {
814             UINT size = GlobalSize16( data16 );
815             void *ptr32, *ptr16 = GlobalLock16( data16 );
816             if (ptr16)
817             {
818                 if (!(data32 = GlobalAlloc( GMEM_MOVEABLE, size ))) return 0;
819                 ptr32 = GlobalLock( data32 );
820                 memcpy( ptr32, ptr16, size );
821                 GlobalUnlock( data32 );
822             }
823             set_clipboard_format( format, data16 );
824         }
825         break;
826     }
827
828     if (!SetClipboardData( format, data32 )) return 0;
829     return data16;
830 }
831
832
833 /**************************************************************************
834  *              GetClipboardData (USER.142)
835  */
836 HANDLE16 WINAPI GetClipboardData16( UINT16 format )
837 {
838     HANDLE data32 = GetClipboardData( format );
839     HANDLE16 data16 = 0;
840     UINT size;
841     void *ptr;
842
843     if (!data32) return 0;
844
845     switch (format)
846     {
847     case CF_BITMAP:
848     case CF_PALETTE:
849         data16 = HGDIOBJ_16( data32 );
850         break;
851
852     case CF_METAFILEPICT:
853     {
854         METAFILEPICT16 *pict16;
855         METAFILEPICT *pict32 = GlobalLock( data32 );
856
857         if (pict32)
858         {
859             if (!(data16 = GlobalAlloc16( GMEM_MOVEABLE, sizeof(*pict16) ))) return 0;
860             pict16 = GlobalLock16( data16 );
861             pict16->mm   = pict32->mm;
862             pict16->xExt = pict32->xExt;
863             pict16->yExt = pict32->yExt;
864             size = GetMetaFileBitsEx( pict32->hMF, 0, NULL );
865             pict16->hMF = GlobalAlloc16( GMEM_MOVEABLE, size );
866             ptr = GlobalLock16( pict16->hMF );
867             GetMetaFileBitsEx( pict32->hMF, size, ptr );
868             GlobalUnlock16( pict16->hMF );
869             GlobalUnlock16( data16 );
870             set_clipboard_format( format, data16 );
871         }
872         break;
873     }
874
875     case CF_ENHMETAFILE:
876         FIXME( "enhmetafile not supported in 16-bit\n" );
877         return 0;
878
879     default:
880         if (format >= CF_GDIOBJFIRST && format <= CF_GDIOBJLAST)
881             data16 = HGDIOBJ_16( data32 );
882         else if (format >= CF_PRIVATEFIRST && format <= CF_PRIVATELAST)
883             data16 = HANDLE_16( data32 );
884         else
885         {
886             void *ptr16, *ptr32 = GlobalLock( data32 );
887             if (ptr32)
888             {
889                 size = GlobalSize( data32 );
890                 if (!(data16 = GlobalAlloc16( GMEM_MOVEABLE, size ))) return 0;
891                 ptr16 = GlobalLock16( data16 );
892                 memcpy( ptr16, ptr32, size );
893                 GlobalUnlock16( data16 );
894                 set_clipboard_format( format, data16 );
895             }
896         }
897         break;
898     }
899     return data16;
900 }
901
902
903 /**************************************************************************
904  *              CountClipboardFormats (USER.143)
905  */
906 INT16 WINAPI CountClipboardFormats16(void)
907 {
908     return CountClipboardFormats();
909 }
910
911
912 /**************************************************************************
913  *              EnumClipboardFormats (USER.144)
914  */
915 UINT16 WINAPI EnumClipboardFormats16( UINT16 id )
916 {
917     return EnumClipboardFormats( id );
918 }
919
920
921 /**************************************************************************
922  *              RegisterClipboardFormat (USER.145)
923  */
924 UINT16 WINAPI RegisterClipboardFormat16( LPCSTR name )
925 {
926     return RegisterClipboardFormatA( name );
927 }
928
929
930 /**************************************************************************
931  *              GetClipboardFormatName (USER.146)
932  */
933 INT16 WINAPI GetClipboardFormatName16( UINT16 id, LPSTR buffer, INT16 maxlen )
934 {
935     return GetClipboardFormatNameA( id, buffer, maxlen );
936 }
937
938
939 /**********************************************************************
940  *          LoadMenu    (USER.150)
941  */
942 HMENU16 WINAPI LoadMenu16( HINSTANCE16 instance, LPCSTR name )
943 {
944     HRSRC16 hRsrc;
945     HGLOBAL16 handle;
946     HMENU16 hMenu;
947
948     if (HIWORD(name) && name[0] == '#') name = ULongToPtr(atoi( name + 1 ));
949     if (!name) return 0;
950
951     instance = GetExePtr( instance );
952     if (!(hRsrc = FindResource16( instance, name, (LPSTR)RT_MENU ))) return 0;
953     if (!(handle = LoadResource16( instance, hRsrc ))) return 0;
954     hMenu = LoadMenuIndirect16(LockResource16(handle));
955     FreeResource16( handle );
956     return hMenu;
957 }
958
959
960 /**********************************************************************
961  *         CreateMenu    (USER.151)
962  */
963 HMENU16 WINAPI CreateMenu16(void)
964 {
965     return HMENU_16( CreateMenu() );
966 }
967
968
969 /**********************************************************************
970  *         DestroyMenu    (USER.152)
971  */
972 BOOL16 WINAPI DestroyMenu16( HMENU16 hMenu )
973 {
974     return DestroyMenu( HMENU_32(hMenu) );
975 }
976
977
978 /*******************************************************************
979  *         ChangeMenu    (USER.153)
980  */
981 BOOL16 WINAPI ChangeMenu16( HMENU16 hMenu, UINT16 pos, SEGPTR data,
982                             UINT16 id, UINT16 flags )
983 {
984     if (flags & MF_APPEND) return AppendMenu16( hMenu, flags & ~MF_APPEND, id, data );
985
986     /* FIXME: Word passes the item id in 'pos' and 0 or 0xffff as id */
987     /* for MF_DELETE. We should check the parameters for all others */
988     /* MF_* actions also (anybody got a doc on ChangeMenu?). */
989
990     if (flags & MF_DELETE) return DeleteMenu16(hMenu, pos, flags & ~MF_DELETE);
991     if (flags & MF_CHANGE) return ModifyMenu16(hMenu, pos, flags & ~MF_CHANGE, id, data );
992     if (flags & MF_REMOVE) return RemoveMenu16(hMenu, flags & MF_BYPOSITION ? pos : id,
993                                                flags & ~MF_REMOVE );
994     /* Default: MF_INSERT */
995     return InsertMenu16( hMenu, pos, flags, id, data );
996 }
997
998
999 /*******************************************************************
1000  *         CheckMenuItem    (USER.154)
1001  */
1002 BOOL16 WINAPI CheckMenuItem16( HMENU16 hMenu, UINT16 id, UINT16 flags )
1003 {
1004     return CheckMenuItem( HMENU_32(hMenu), id, flags );
1005 }
1006
1007
1008 /**********************************************************************
1009  *         EnableMenuItem    (USER.155)
1010  */
1011 BOOL16 WINAPI EnableMenuItem16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
1012 {
1013     return EnableMenuItem( HMENU_32(hMenu), wItemID, wFlags );
1014 }
1015
1016
1017 /**********************************************************************
1018  *         GetSubMenu    (USER.159)
1019  */
1020 HMENU16 WINAPI GetSubMenu16( HMENU16 hMenu, INT16 nPos )
1021 {
1022     return HMENU_16( GetSubMenu( HMENU_32(hMenu), nPos ) );
1023 }
1024
1025
1026 /*******************************************************************
1027  *         GetMenuString    (USER.161)
1028  */
1029 INT16 WINAPI GetMenuString16( HMENU16 hMenu, UINT16 wItemID,
1030                               LPSTR str, INT16 nMaxSiz, UINT16 wFlags )
1031 {
1032     return GetMenuStringA( HMENU_32(hMenu), wItemID, str, nMaxSiz, wFlags );
1033 }
1034
1035
1036 /**********************************************************************
1037  *              WinHelp (USER.171)
1038  */
1039 BOOL16 WINAPI WinHelp16( HWND16 hWnd, LPCSTR lpHelpFile, UINT16 wCommand,
1040                          DWORD dwData )
1041 {
1042     BOOL ret;
1043     DWORD mutex_count;
1044
1045     /* We might call WinExec() */
1046     ReleaseThunkLock(&mutex_count);
1047
1048     ret = WinHelpA(WIN_Handle32(hWnd), lpHelpFile, wCommand, (DWORD)MapSL(dwData));
1049
1050     RestoreThunkLock(mutex_count);
1051     return ret;
1052 }
1053
1054
1055 /***********************************************************************
1056  *              LoadCursor (USER.173)
1057  */
1058 HCURSOR16 WINAPI LoadCursor16(HINSTANCE16 hInstance, LPCSTR name)
1059 {
1060     return LoadImage16( hInstance, name, IMAGE_CURSOR, 0, 0, LR_SHARED | LR_DEFAULTSIZE );
1061 }
1062
1063
1064 /***********************************************************************
1065  *              LoadIcon (USER.174)
1066  */
1067 HICON16 WINAPI LoadIcon16(HINSTANCE16 hInstance, LPCSTR name)
1068 {
1069     return LoadImage16( hInstance, name, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE );
1070 }
1071
1072 /**********************************************************************
1073  *              LoadBitmap (USER.175)
1074  */
1075 HBITMAP16 WINAPI LoadBitmap16(HINSTANCE16 hInstance, LPCSTR name)
1076 {
1077     return LoadImage16( hInstance, name, IMAGE_BITMAP, 0, 0, 0 );
1078 }
1079
1080 /**********************************************************************
1081  *     LoadString   (USER.176)
1082  */
1083 INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id, LPSTR buffer, INT16 buflen )
1084 {
1085     HGLOBAL16 hmem;
1086     HRSRC16 hrsrc;
1087     unsigned char *p;
1088     int string_num;
1089     int ret;
1090
1091     TRACE("inst=%04x id=%04x buff=%p len=%d\n", instance, resource_id, buffer, buflen);
1092
1093     hrsrc = FindResource16( instance, MAKEINTRESOURCEA((resource_id>>4)+1), (LPSTR)RT_STRING );
1094     if (!hrsrc) return 0;
1095     hmem = LoadResource16( instance, hrsrc );
1096     if (!hmem) return 0;
1097
1098     p = LockResource16(hmem);
1099     string_num = resource_id & 0x000f;
1100     while (string_num--) p += *p + 1;
1101
1102     if (buffer == NULL) ret = *p;
1103     else
1104     {
1105         ret = min(buflen - 1, *p);
1106         if (ret > 0)
1107         {
1108             memcpy(buffer, p + 1, ret);
1109             buffer[ret] = '\0';
1110         }
1111         else if (buflen > 1)
1112         {
1113             buffer[0] = '\0';
1114             ret = 0;
1115         }
1116         TRACE( "%s loaded\n", debugstr_a(buffer));
1117     }
1118     FreeResource16( hmem );
1119     return ret;
1120 }
1121
1122 /**********************************************************************
1123  *              LoadAccelerators  (USER.177)
1124  */
1125 HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, LPCSTR lpTableName)
1126 {
1127     HRSRC16 hRsrc;
1128     HGLOBAL16 hMem;
1129     ACCEL16 *table16;
1130     HACCEL ret = 0;
1131
1132     TRACE("%04x %s\n", instance, debugstr_a(lpTableName) );
1133
1134     if (!(hRsrc = FindResource16( instance, lpTableName, (LPSTR)RT_ACCELERATOR )) ||
1135         !(hMem = LoadResource16(instance,hRsrc)))
1136     {
1137         WARN("couldn't find %04x %s\n", instance, debugstr_a(lpTableName));
1138         return 0;
1139     }
1140     if ((table16 = LockResource16( hMem )))
1141     {
1142         DWORD i, count = SizeofResource16( instance, hRsrc ) / sizeof(*table16);
1143         ACCEL *table = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*table) );
1144         if (table)
1145         {
1146             for (i = 0; i < count; i++)
1147             {
1148                 table[i].fVirt = table16[i].fVirt & 0x7f;
1149                 table[i].key   = table16[i].key;
1150                 table[i].cmd   = table16[i].cmd;
1151             }
1152             ret = CreateAcceleratorTableA( table, count );
1153             HeapFree( GetProcessHeap(), 0, table );
1154         }
1155     }
1156     FreeResource16( hMem );
1157     return HACCEL_16(ret);
1158 }
1159
1160 /***********************************************************************
1161  *              GetSystemMetrics (USER.179)
1162  */
1163 INT16 WINAPI GetSystemMetrics16( INT16 index )
1164 {
1165     return GetSystemMetrics( index );
1166 }
1167
1168
1169 /*************************************************************************
1170  *              GetSysColor (USER.180)
1171  */
1172 COLORREF WINAPI GetSysColor16( INT16 index )
1173 {
1174     return GetSysColor( index );
1175 }
1176
1177
1178 /*************************************************************************
1179  *              SetSysColors (USER.181)
1180  */
1181 VOID WINAPI SetSysColors16( INT16 count, const INT16 *list16, const COLORREF *values )
1182 {
1183     INT i, *list;
1184
1185     if ((list = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*list) )))
1186     {
1187         for (i = 0; i < count; i++) list[i] = list16[i];
1188         SetSysColors( count, list, values );
1189         HeapFree( GetProcessHeap(), 0, list );
1190     }
1191 }
1192
1193
1194 /***********************************************************************
1195  *           GrayString   (USER.185)
1196  */
1197 BOOL16 WINAPI GrayString16( HDC16 hdc, HBRUSH16 hbr, GRAYSTRINGPROC16 gsprc,
1198                             LPARAM lParam, INT16 cch, INT16 x, INT16 y,
1199                             INT16 cx, INT16 cy )
1200 {
1201     BOOL ret;
1202
1203     if (!gsprc) return GrayStringA( HDC_32(hdc), HBRUSH_32(hbr), NULL,
1204                                     (LPARAM)MapSL(lParam), cch, x, y, cx, cy );
1205
1206     if (cch == -1 || (cch && cx && cy))
1207     {
1208         /* lParam can be treated as an opaque pointer */
1209         struct gray_string_info info;
1210
1211         info.proc  = gsprc;
1212         info.param = lParam;
1213         ret = GrayStringA( HDC_32(hdc), HBRUSH_32(hbr), gray_string_callback,
1214                            (LPARAM)&info, cch, x, y, cx, cy );
1215     }
1216     else  /* here we need some string conversions */
1217     {
1218         char *str16 = MapSL(lParam);
1219         struct gray_string_info *info;
1220
1221         if (!cch) cch = strlen(str16);
1222         if (!(info = HeapAlloc( GetProcessHeap(), 0, sizeof(*info) + cch ))) return FALSE;
1223         info->proc  = gsprc;
1224         info->param = lParam;
1225         memcpy( info->str, str16, cch );
1226         ret = GrayStringA( HDC_32(hdc), HBRUSH_32(hbr), gray_string_callback_ptr,
1227                            (LPARAM)info->str, cch, x, y, cx, cy );
1228         HeapFree( GetProcessHeap(), 0, info );
1229     }
1230     return ret;
1231 }
1232
1233
1234 /***********************************************************************
1235  *              SwapMouseButton (USER.186)
1236  */
1237 BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap )
1238 {
1239     return SwapMouseButton( fSwap );
1240 }
1241
1242
1243 /**************************************************************************
1244  *              IsClipboardFormatAvailable (USER.193)
1245  */
1246 BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat )
1247 {
1248     return IsClipboardFormatAvailable( wFormat );
1249 }
1250
1251
1252 /***********************************************************************
1253  *           TabbedTextOut    (USER.196)
1254  */
1255 LONG WINAPI TabbedTextOut16( HDC16 hdc, INT16 x, INT16 y, LPCSTR lpstr,
1256                              INT16 count, INT16 nb_tabs, const INT16 *tabs16, INT16 tab_org )
1257 {
1258     LONG ret;
1259     INT i, *tabs = HeapAlloc( GetProcessHeap(), 0, nb_tabs * sizeof(tabs) );
1260     if (!tabs) return 0;
1261     for (i = 0; i < nb_tabs; i++) tabs[i] = tabs16[i];
1262     ret = TabbedTextOutA( HDC_32(hdc), x, y, lpstr, count, nb_tabs, tabs, tab_org );
1263     HeapFree( GetProcessHeap(), 0, tabs );
1264     return ret;
1265 }
1266
1267
1268 /***********************************************************************
1269  *           GetTabbedTextExtent    (USER.197)
1270  */
1271 DWORD WINAPI GetTabbedTextExtent16( HDC16 hdc, LPCSTR lpstr, INT16 count,
1272                                     INT16 nb_tabs, const INT16 *tabs16 )
1273 {
1274     LONG ret;
1275     INT i, *tabs = HeapAlloc( GetProcessHeap(), 0, nb_tabs * sizeof(tabs) );
1276     if (!tabs) return 0;
1277     for (i = 0; i < nb_tabs; i++) tabs[i] = tabs16[i];
1278     ret = GetTabbedTextExtentA( HDC_32(hdc), lpstr, count, nb_tabs, tabs );
1279     HeapFree( GetProcessHeap(), 0, tabs );
1280     return ret;
1281 }
1282
1283
1284 /***********************************************************************
1285  *              UserSeeUserDo (USER.216)
1286  */
1287 DWORD WINAPI UserSeeUserDo16(WORD wReqType, WORD wParam1, WORD wParam2, WORD wParam3)
1288 {
1289     STACK16FRAME* stack16 = MapSL((SEGPTR)NtCurrentTeb()->WOW32Reserved);
1290     HANDLE16 oldDS = stack16->ds;
1291     DWORD ret = (DWORD)-1;
1292
1293     stack16->ds = USER_HeapSel;
1294     switch (wReqType)
1295     {
1296     case USUD_LOCALALLOC:
1297         ret = LocalAlloc16(wParam1, wParam3);
1298         break;
1299     case USUD_LOCALFREE:
1300         ret = LocalFree16(wParam1);
1301         break;
1302     case USUD_LOCALCOMPACT:
1303         ret = LocalCompact16(wParam3);
1304         break;
1305     case USUD_LOCALHEAP:
1306         ret = USER_HeapSel;
1307         break;
1308     case USUD_FIRSTCLASS:
1309         FIXME("return a pointer to the first window class.\n");
1310         break;
1311     default:
1312         WARN("wReqType %04x (unknown)\n", wReqType);
1313     }
1314     stack16->ds = oldDS;
1315     return ret;
1316 }
1317
1318
1319 /***********************************************************************
1320  *           LookupMenuHandle   (USER.217)
1321  */
1322 HMENU16 WINAPI LookupMenuHandle16( HMENU16 hmenu, INT16 id )
1323 {
1324     FIXME( "%04x %04x: stub\n", hmenu, id );
1325     return hmenu;
1326 }
1327
1328
1329 static LPCSTR parse_menu_resource( LPCSTR res, HMENU hMenu )
1330 {
1331     WORD flags, id = 0;
1332     LPCSTR str;
1333     BOOL end_flag;
1334
1335     do
1336     {
1337         flags = GET_WORD(res);
1338         end_flag = flags & MF_END;
1339         /* Remove MF_END because it has the same value as MF_HILITE */
1340         flags &= ~MF_END;
1341         res += sizeof(WORD);
1342         if (!(flags & MF_POPUP))
1343         {
1344             id = GET_WORD(res);
1345             res += sizeof(WORD);
1346         }
1347         str = res;
1348         res += strlen(str) + 1;
1349         if (flags & MF_POPUP)
1350         {
1351             HMENU hSubMenu = CreatePopupMenu();
1352             if (!hSubMenu) return NULL;
1353             if (!(res = parse_menu_resource( res, hSubMenu ))) return NULL;
1354             AppendMenuA( hMenu, flags, (UINT_PTR)hSubMenu, str );
1355         }
1356         else  /* Not a popup */
1357         {
1358             AppendMenuA( hMenu, flags, id, *str ? str : NULL );
1359         }
1360     } while (!end_flag);
1361     return res;
1362 }
1363
1364 /**********************************************************************
1365  *          LoadMenuIndirect    (USER.220)
1366  */
1367 HMENU16 WINAPI LoadMenuIndirect16( LPCVOID template )
1368 {
1369     HMENU hMenu;
1370     WORD version, offset;
1371     LPCSTR p = template;
1372
1373     TRACE("(%p)\n", template );
1374     version = GET_WORD(p);
1375     p += sizeof(WORD);
1376     if (version)
1377     {
1378         WARN("version must be 0 for Win16\n" );
1379         return 0;
1380     }
1381     offset = GET_WORD(p);
1382     p += sizeof(WORD) + offset;
1383     if (!(hMenu = CreateMenu())) return 0;
1384     if (!parse_menu_resource( p, hMenu ))
1385     {
1386         DestroyMenu( hMenu );
1387         return 0;
1388     }
1389     return HMENU_16(hMenu);
1390 }
1391
1392
1393 /*************************************************************************
1394  *              ScrollDC (USER.221)
1395  */
1396 BOOL16 WINAPI ScrollDC16( HDC16 hdc, INT16 dx, INT16 dy, const RECT16 *rect,
1397                           const RECT16 *cliprc, HRGN16 hrgnUpdate,
1398                           LPRECT16 rcUpdate )
1399 {
1400     RECT rect32, clipRect32, rcUpdate32;
1401     BOOL16 ret;
1402
1403     if (rect)
1404     {
1405         rect32.left   = rect->left;
1406         rect32.top    = rect->top;
1407         rect32.right  = rect->right;
1408         rect32.bottom = rect->bottom;
1409     }
1410     if (cliprc)
1411     {
1412         clipRect32.left   = cliprc->left;
1413         clipRect32.top    = cliprc->top;
1414         clipRect32.right  = cliprc->right;
1415         clipRect32.bottom = cliprc->bottom;
1416     }
1417     ret = ScrollDC( HDC_32(hdc), dx, dy, rect ? &rect32 : NULL,
1418                     cliprc ? &clipRect32 : NULL, HRGN_32(hrgnUpdate),
1419                     &rcUpdate32 );
1420     if (rcUpdate)
1421     {
1422         rcUpdate->left   = rcUpdate32.left;
1423         rcUpdate->top    = rcUpdate32.top;
1424         rcUpdate->right  = rcUpdate32.right;
1425         rcUpdate->bottom = rcUpdate32.bottom;
1426     }
1427     return ret;
1428 }
1429
1430
1431 /***********************************************************************
1432  *              GetSystemDebugState (USER.231)
1433  */
1434 WORD WINAPI GetSystemDebugState16(void)
1435 {
1436     return 0;  /* FIXME */
1437 }
1438
1439
1440 /***********************************************************************
1441  *              EqualRect (USER.244)
1442  */
1443 BOOL16 WINAPI EqualRect16( const RECT16* rect1, const RECT16* rect2 )
1444 {
1445     return ((rect1->left == rect2->left) && (rect1->right == rect2->right) &&
1446             (rect1->top == rect2->top) && (rect1->bottom == rect2->bottom));
1447 }
1448
1449
1450 /***********************************************************************
1451  *              ExitWindowsExec (USER.246)
1452  */
1453 BOOL16 WINAPI ExitWindowsExec16( LPCSTR lpszExe, LPCSTR lpszParams )
1454 {
1455     TRACE("Should run the following in DOS-mode: \"%s %s\"\n",
1456           lpszExe, lpszParams);
1457     return ExitWindowsEx( EWX_LOGOFF, 0xffffffff );
1458 }
1459
1460
1461 /***********************************************************************
1462  *              GetCursor (USER.247)
1463  */
1464 HCURSOR16 WINAPI GetCursor16(void)
1465 {
1466   return get_icon_16( GetCursor() );
1467 }
1468
1469
1470 /**********************************************************************
1471  *              GetAsyncKeyState (USER.249)
1472  */
1473 INT16 WINAPI GetAsyncKeyState16( INT16 key )
1474 {
1475     return GetAsyncKeyState( key );
1476 }
1477
1478
1479 /**********************************************************************
1480  *         GetMenuState    (USER.250)
1481  */
1482 UINT16 WINAPI GetMenuState16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags )
1483 {
1484     return GetMenuState( HMENU_32(hMenu), wItemID, wFlags );
1485 }
1486
1487
1488 /**************************************************************************
1489  *              SendDriverMessage (USER.251)
1490  */
1491 LRESULT WINAPI SendDriverMessage16(HDRVR16 hDriver, UINT16 msg, LPARAM lParam1,
1492                                    LPARAM lParam2)
1493 {
1494     FIXME("(%04x, %04x, %08lx, %08lx): stub\n", hDriver, msg, lParam1, lParam2);
1495     return 0;
1496 }
1497
1498
1499 /**************************************************************************
1500  *              OpenDriver (USER.252)
1501  */
1502 HDRVR16 WINAPI OpenDriver16(LPCSTR lpDriverName, LPCSTR lpSectionName, LPARAM lParam2)
1503 {
1504     FIXME( "(%s, %s, %08lx): stub\n", debugstr_a(lpDriverName), debugstr_a(lpSectionName), lParam2);
1505     return 0;
1506 }
1507
1508
1509 /**************************************************************************
1510  *              CloseDriver (USER.253)
1511  */
1512 LRESULT WINAPI CloseDriver16(HDRVR16 hDrvr, LPARAM lParam1, LPARAM lParam2)
1513 {
1514     FIXME( "(%04x, %08lx, %08lx): stub\n", hDrvr, lParam1, lParam2);
1515     return FALSE;
1516 }
1517
1518
1519 /**************************************************************************
1520  *              GetDriverModuleHandle (USER.254)
1521  */
1522 HMODULE16 WINAPI GetDriverModuleHandle16(HDRVR16 hDrvr)
1523 {
1524     FIXME("(%04x): stub\n", hDrvr);
1525     return 0;
1526 }
1527
1528
1529 /**************************************************************************
1530  *              DefDriverProc (USER.255)
1531  */
1532 LRESULT WINAPI DefDriverProc16(DWORD dwDevID, HDRVR16 hDriv, UINT16 wMsg,
1533                                LPARAM lParam1, LPARAM lParam2)
1534 {
1535     FIXME( "devID=0x%08x hDrv=0x%04x wMsg=%04x lP1=0x%08lx lP2=0x%08lx: stub\n",
1536           dwDevID, hDriv, wMsg, lParam1, lParam2);
1537     return 0;
1538 }
1539
1540
1541 /**************************************************************************
1542  *              GetDriverInfo (USER.256)
1543  */
1544 struct DRIVERINFOSTRUCT16;
1545 BOOL16 WINAPI GetDriverInfo16(HDRVR16 hDrvr, struct DRIVERINFOSTRUCT16 *lpDrvInfo)
1546 {
1547     FIXME( "(%04x, %p): stub\n", hDrvr, lpDrvInfo);
1548     return FALSE;
1549 }
1550
1551
1552 /**************************************************************************
1553  *              GetNextDriver (USER.257)
1554  */
1555 HDRVR16 WINAPI GetNextDriver16(HDRVR16 hDrvr, DWORD dwFlags)
1556 {
1557     FIXME( "(%04x, %08x): stub\n", hDrvr, dwFlags);
1558     return 0;
1559 }
1560
1561
1562 /**********************************************************************
1563  *         GetMenuItemCount    (USER.263)
1564  */
1565 INT16 WINAPI GetMenuItemCount16( HMENU16 hMenu )
1566 {
1567     return GetMenuItemCount( HMENU_32(hMenu) );
1568 }
1569
1570
1571 /**********************************************************************
1572  *         GetMenuItemID    (USER.264)
1573  */
1574 UINT16 WINAPI GetMenuItemID16( HMENU16 hMenu, INT16 nPos )
1575 {
1576     return GetMenuItemID( HMENU_32(hMenu), nPos );
1577 }
1578
1579
1580 /***********************************************************************
1581  *              GlobalAddAtom (USER.268)
1582  */
1583 ATOM WINAPI GlobalAddAtom16(LPCSTR lpString)
1584 {
1585   return GlobalAddAtomA(lpString);
1586 }
1587
1588 /***********************************************************************
1589  *              GlobalDeleteAtom (USER.269)
1590  */
1591 ATOM WINAPI GlobalDeleteAtom16(ATOM nAtom)
1592 {
1593   return GlobalDeleteAtom(nAtom);
1594 }
1595
1596 /***********************************************************************
1597  *              GlobalFindAtom (USER.270)
1598  */
1599 ATOM WINAPI GlobalFindAtom16(LPCSTR lpString)
1600 {
1601   return GlobalFindAtomA(lpString);
1602 }
1603
1604 /***********************************************************************
1605  *              GlobalGetAtomName (USER.271)
1606  */
1607 UINT16 WINAPI GlobalGetAtomName16(ATOM nAtom, LPSTR lpBuffer, INT16 nSize)
1608 {
1609   return GlobalGetAtomNameA(nAtom, lpBuffer, nSize);
1610 }
1611
1612
1613 /***********************************************************************
1614  *              ControlPanelInfo (USER.273)
1615  */
1616 void WINAPI ControlPanelInfo16( INT16 nInfoType, WORD wData, LPSTR lpBuffer )
1617 {
1618     FIXME("(%d, %04x, %p): stub.\n", nInfoType, wData, lpBuffer);
1619 }
1620
1621
1622 /***********************************************************************
1623  *           OldSetDeskPattern   (USER.279)
1624  */
1625 BOOL16 WINAPI SetDeskPattern16(void)
1626 {
1627     return SystemParametersInfoA( SPI_SETDESKPATTERN, -1, NULL, FALSE );
1628 }
1629
1630
1631 /***********************************************************************
1632  *              GetSysColorBrush (USER.281)
1633  */
1634 HBRUSH16 WINAPI GetSysColorBrush16( INT16 index )
1635 {
1636     return HBRUSH_16( GetSysColorBrush(index) );
1637 }
1638
1639
1640 /***********************************************************************
1641  *              SelectPalette (USER.282)
1642  */
1643 HPALETTE16 WINAPI SelectPalette16( HDC16 hdc, HPALETTE16 hpal, BOOL16 bForceBackground )
1644 {
1645     return HPALETTE_16( SelectPalette( HDC_32(hdc), HPALETTE_32(hpal), bForceBackground ));
1646 }
1647
1648 /***********************************************************************
1649  *              RealizePalette (USER.283)
1650  */
1651 UINT16 WINAPI RealizePalette16( HDC16 hdc )
1652 {
1653     return UserRealizePalette( HDC_32(hdc) );
1654 }
1655
1656
1657 /***********************************************************************
1658  *              GetFreeSystemResources (USER.284)
1659  */
1660 WORD WINAPI GetFreeSystemResources16( WORD resType )
1661 {
1662     STACK16FRAME* stack16 = MapSL((SEGPTR)NtCurrentTeb()->WOW32Reserved);
1663     HANDLE16 oldDS = stack16->ds;
1664     HINSTANCE16 gdi_inst;
1665     int userPercent, gdiPercent;
1666
1667     if ((gdi_inst = LoadLibrary16( "GDI" )) < 32) return 0;
1668
1669     switch(resType)
1670     {
1671     case GFSR_USERRESOURCES:
1672         stack16->ds = USER_HeapSel;
1673         userPercent = (int)LocalCountFree16() * 100 / LocalHeapSize16();
1674         gdiPercent  = 100;
1675         stack16->ds = oldDS;
1676         break;
1677
1678     case GFSR_GDIRESOURCES:
1679         stack16->ds = gdi_inst;
1680         gdiPercent  = (int)LocalCountFree16() * 100 / LocalHeapSize16();
1681         userPercent = 100;
1682         stack16->ds = oldDS;
1683         break;
1684
1685     case GFSR_SYSTEMRESOURCES:
1686         stack16->ds = USER_HeapSel;
1687         userPercent = (int)LocalCountFree16() * 100 / LocalHeapSize16();
1688         stack16->ds = gdi_inst;
1689         gdiPercent  = (int)LocalCountFree16() * 100 / LocalHeapSize16();
1690         stack16->ds = oldDS;
1691         break;
1692
1693     default:
1694         userPercent = gdiPercent = 0;
1695         break;
1696     }
1697     FreeLibrary16( gdi_inst );
1698     TRACE("<- userPercent %d, gdiPercent %d\n", userPercent, gdiPercent);
1699     return (WORD)min( userPercent, gdiPercent );
1700 }
1701
1702
1703 /***********************************************************************
1704  *           SetDeskWallPaper   (USER.285)
1705  */
1706 BOOL16 WINAPI SetDeskWallPaper16( LPCSTR filename )
1707 {
1708     return SetDeskWallPaper( filename );
1709 }
1710
1711
1712 /***********************************************************************
1713  *              keybd_event (USER.289)
1714  */
1715 void WINAPI keybd_event16( CONTEXT86 *context )
1716 {
1717     DWORD dwFlags = 0;
1718
1719     if (HIBYTE(context->Eax) & 0x80) dwFlags |= KEYEVENTF_KEYUP;
1720     if (HIBYTE(context->Ebx) & 0x01) dwFlags |= KEYEVENTF_EXTENDEDKEY;
1721
1722     keybd_event( LOBYTE(context->Eax), LOBYTE(context->Ebx),
1723                  dwFlags, MAKELONG(LOWORD(context->Esi), LOWORD(context->Edi)) );
1724 }
1725
1726
1727 /***********************************************************************
1728  *              mouse_event (USER.299)
1729  */
1730 void WINAPI mouse_event16( CONTEXT86 *context )
1731 {
1732     mouse_event( LOWORD(context->Eax), LOWORD(context->Ebx), LOWORD(context->Ecx),
1733                  LOWORD(context->Edx), MAKELONG(context->Esi, context->Edi) );
1734 }
1735
1736
1737 /***********************************************************************
1738  *              GetClipCursor (USER.309)
1739  */
1740 void WINAPI GetClipCursor16( RECT16 *rect )
1741 {
1742     if (rect)
1743     {
1744         RECT rect32;
1745         GetClipCursor( &rect32 );
1746         rect->left   = rect32.left;
1747         rect->top    = rect32.top;
1748         rect->right  = rect32.right;
1749         rect->bottom = rect32.bottom;
1750     }
1751 }
1752
1753
1754 /***********************************************************************
1755  *              SignalProc (USER.314)
1756  */
1757 void WINAPI SignalProc16( HANDLE16 hModule, UINT16 code,
1758                           UINT16 uExitFn, HINSTANCE16 hInstance, HQUEUE16 hQueue )
1759 {
1760     if (code == USIG16_DLL_UNLOAD)
1761     {
1762         hModule = GetExePtr(hModule);
1763         /* HOOK_FreeModuleHooks( hModule ); */
1764         free_module_classes( hModule );
1765         free_module_icons( hModule );
1766     }
1767 }
1768
1769
1770 /***********************************************************************
1771  *              SetEventHook (USER.321)
1772  *
1773  *      Used by Turbo Debugger for Windows
1774  */
1775 FARPROC16 WINAPI SetEventHook16(FARPROC16 lpfnEventHook)
1776 {
1777     FIXME("(lpfnEventHook=%p): stub\n", lpfnEventHook);
1778     return 0;
1779 }
1780
1781
1782 /**********************************************************************
1783  *              EnableHardwareInput (USER.331)
1784  */
1785 BOOL16 WINAPI EnableHardwareInput16(BOOL16 bEnable)
1786 {
1787     FIXME("(%d) - stub\n", bEnable);
1788     return TRUE;
1789 }
1790
1791
1792 /**********************************************************************
1793  *              LoadCursorIconHandler (USER.336)
1794  *
1795  * Supposed to load resources of Windows 2.x applications.
1796  */
1797 HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc )
1798 {
1799     FIXME("(%04x,%04x,%04x): old 2.x resources are not supported!\n", hResource, hModule, hRsrc);
1800     return 0;
1801 }
1802
1803
1804 /***********************************************************************
1805  *              GetMouseEventProc (USER.337)
1806  */
1807 FARPROC16 WINAPI GetMouseEventProc16(void)
1808 {
1809     HMODULE16 hmodule = GetModuleHandle16("USER");
1810     return GetProcAddress16( hmodule, "mouse_event" );
1811 }
1812
1813
1814 /***********************************************************************
1815  *              IsUserIdle (USER.333)
1816  */
1817 BOOL16 WINAPI IsUserIdle16(void)
1818 {
1819     if ( GetAsyncKeyState( VK_LBUTTON ) & 0x8000 )
1820         return FALSE;
1821     if ( GetAsyncKeyState( VK_RBUTTON ) & 0x8000 )
1822         return FALSE;
1823     if ( GetAsyncKeyState( VK_MBUTTON ) & 0x8000 )
1824         return FALSE;
1825     /* Should check for screen saver activation here ... */
1826     return TRUE;
1827 }
1828
1829
1830 /**********************************************************************
1831  *              LoadDIBIconHandler (USER.357)
1832  *
1833  * RT_ICON resource loader, installed by USER_SignalProc when module
1834  * is initialized.
1835  */
1836 HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1837 {
1838     /* If hResource is zero we must allocate a new memory block, if it's
1839      * non-zero but GlobalLock() returns NULL then it was discarded and
1840      * we have to recommit some memory, otherwise we just need to check
1841      * the block size. See LoadProc() in 16-bit SDK for more.
1842      */
1843     FIXME( "%x %x %x: stub, not supported anymore\n", hMemObj, hModule, hRsrc );
1844     return 0;
1845 }
1846
1847 /**********************************************************************
1848  *              LoadDIBCursorHandler (USER.356)
1849  *
1850  * RT_CURSOR resource loader. Same as above.
1851  */
1852 HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc )
1853 {
1854     FIXME( "%x %x %x: stub, not supported anymore\n", hMemObj, hModule, hRsrc );
1855     return 0;
1856 }
1857
1858
1859 /**********************************************************************
1860  *              IsMenu    (USER.358)
1861  */
1862 BOOL16 WINAPI IsMenu16( HMENU16 hmenu )
1863 {
1864     return IsMenu( HMENU_32(hmenu) );
1865 }
1866
1867
1868 /***********************************************************************
1869  *              DCHook (USER.362)
1870  */
1871 BOOL16 WINAPI DCHook16( HDC16 hdc, WORD code, DWORD data, LPARAM lParam )
1872 {
1873     FIXME( "hDC = %x, %i: stub\n", hdc, code );
1874     return FALSE;
1875 }
1876
1877
1878 /**********************************************************************
1879  *              LookupIconIdFromDirectoryEx (USER.364)
1880  *
1881  * FIXME: exact parameter sizes
1882  */
1883 INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE dir, BOOL16 bIcon,
1884                                             INT16 width, INT16 height, UINT16 cFlag )
1885 {
1886     return LookupIconIdFromDirectoryEx( dir, bIcon, width, height, cFlag );
1887 }
1888
1889
1890 /***********************************************************************
1891  *              CopyIcon (USER.368)
1892  */
1893 HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon )
1894 {
1895     CURSORICONINFO *info = get_icon_ptr( hIcon );
1896     void *and_bits = info + 1;
1897     void *xor_bits = (BYTE *)and_bits + info->nHeight * get_bitmap_width_bytes( info->nWidth, 1 );
1898     HGLOBAL16 ret = CreateCursorIconIndirect16( hInstance, info, and_bits, xor_bits );
1899     release_icon_ptr( hIcon, info );
1900     return ret;
1901 }
1902
1903
1904 /***********************************************************************
1905  *              CopyCursor (USER.369)
1906  */
1907 HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor )
1908 {
1909     CURSORICONINFO *info = get_icon_ptr( hCursor );
1910     void *and_bits = info + 1;
1911     void *xor_bits = (BYTE *)and_bits + info->nHeight * get_bitmap_width_bytes( info->nWidth, 1 );
1912     HGLOBAL16 ret = CreateCursorIconIndirect16( hInstance, info, and_bits, xor_bits );
1913     release_icon_ptr( hCursor, info );
1914     return ret;
1915 }
1916
1917
1918 /***********************************************************************
1919  *              SubtractRect (USER.373)
1920  */
1921 BOOL16 WINAPI SubtractRect16( LPRECT16 dest, const RECT16 *src1,
1922                               const RECT16 *src2 )
1923 {
1924     RECT16 tmp;
1925
1926     if (IsRectEmpty16( src1 ))
1927     {
1928         SetRectEmpty16( dest );
1929         return FALSE;
1930     }
1931     *dest = *src1;
1932     if (IntersectRect16( &tmp, src1, src2 ))
1933     {
1934         if (EqualRect16( &tmp, dest ))
1935         {
1936             SetRectEmpty16( dest );
1937             return FALSE;
1938         }
1939         if ((tmp.top == dest->top) && (tmp.bottom == dest->bottom))
1940         {
1941             if (tmp.left == dest->left) dest->left = tmp.right;
1942             else if (tmp.right == dest->right) dest->right = tmp.left;
1943         }
1944         else if ((tmp.left == dest->left) && (tmp.right == dest->right))
1945         {
1946             if (tmp.top == dest->top) dest->top = tmp.bottom;
1947             else if (tmp.bottom == dest->bottom) dest->bottom = tmp.top;
1948         }
1949     }
1950     return TRUE;
1951 }
1952
1953
1954 /**********************************************************************
1955  *              DllEntryPoint (USER.374)
1956  */
1957 BOOL WINAPI DllEntryPoint( DWORD reason, HINSTANCE16 inst, WORD ds,
1958                            WORD heap, DWORD reserved1, WORD reserved2 )
1959 {
1960     if (reason != DLL_PROCESS_ATTACH) return TRUE;
1961     if (USER_HeapSel) return TRUE;  /* already called */
1962
1963     USER_HeapSel = ds;
1964     register_wow_handlers();
1965     LoadLibrary16( "display.drv" );
1966     LoadLibrary16( "keyboard.drv" );
1967     LoadLibrary16( "mouse.drv" );
1968     return TRUE;
1969 }
1970
1971
1972 /**********************************************************************
1973  *         SetMenuContextHelpId    (USER.384)
1974  */
1975 BOOL16 WINAPI SetMenuContextHelpId16( HMENU16 hMenu, DWORD dwContextHelpID)
1976 {
1977     return SetMenuContextHelpId( HMENU_32(hMenu), dwContextHelpID );
1978 }
1979
1980
1981 /**********************************************************************
1982  *         GetMenuContextHelpId    (USER.385)
1983  */
1984 DWORD WINAPI GetMenuContextHelpId16( HMENU16 hMenu )
1985 {
1986     return GetMenuContextHelpId( HMENU_32(hMenu) );
1987 }
1988
1989
1990 /***********************************************************************
1991  *              LoadImage (USER.389)
1992  */
1993 HANDLE16 WINAPI LoadImage16(HINSTANCE16 hinst, LPCSTR name, UINT16 type, INT16 cx, INT16 cy, UINT16 flags)
1994 {
1995     HGLOBAL16 handle;
1996     HRSRC16 hRsrc, hGroupRsrc;
1997
1998     if (!hinst || (flags & LR_LOADFROMFILE))
1999     {
2000         if (type == IMAGE_BITMAP)
2001             return HBITMAP_16( LoadImageA( 0, name, type, cx, cy, flags ));
2002         else
2003             return get_icon_16( LoadImageA( 0, name, type, cx, cy, flags ));
2004     }
2005
2006     hinst = GetExePtr( hinst );
2007
2008     if (flags & LR_DEFAULTSIZE)
2009     {
2010         if (type == IMAGE_ICON)
2011         {
2012             if (!cx) cx = GetSystemMetrics(SM_CXICON);
2013             if (!cy) cy = GetSystemMetrics(SM_CYICON);
2014         }
2015         else if (type == IMAGE_CURSOR)
2016         {
2017             if (!cx) cx = GetSystemMetrics(SM_CXCURSOR);
2018             if (!cy) cy = GetSystemMetrics(SM_CYCURSOR);
2019         }
2020     }
2021
2022     switch (type)
2023     {
2024     case IMAGE_BITMAP:
2025     {
2026         HBITMAP ret = 0;
2027         char *ptr;
2028         static const WCHAR prefixW[] = {'b','m','p',0};
2029         BITMAPFILEHEADER header;
2030         WCHAR path[MAX_PATH], filename[MAX_PATH];
2031         HANDLE file;
2032         DWORD size;
2033
2034         filename[0] = 0;
2035         if (!(hRsrc = FindResource16( hinst, name, (LPCSTR)RT_BITMAP ))) return 0;
2036         if (!(handle = LoadResource16( hinst, hRsrc ))) return 0;
2037         if (!(ptr = LockResource16( handle ))) goto done;
2038         size = SizeofResource16( hinst, hRsrc );
2039
2040         header.bfType = 0x4d42; /* 'BM' */
2041         header.bfReserved1 = 0;
2042         header.bfReserved2 = 0;
2043         header.bfSize = sizeof(header) + size;
2044         header.bfOffBits = 0;  /* not used by the 32-bit loading code */
2045
2046         if (!GetTempPathW( MAX_PATH, path )) goto done;
2047         if (!GetTempFileNameW( path, prefixW, 0, filename )) goto done;
2048
2049         file = CreateFileW( filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 );
2050         if (file != INVALID_HANDLE_VALUE)
2051         {
2052             DWORD written;
2053             BOOL ok;
2054             ok = WriteFile( file, &header, sizeof(header), &written, NULL ) && (written == sizeof(header));
2055             if (ok) ok = WriteFile( file, ptr, size, &written, NULL ) && (written == size);
2056             CloseHandle( file );
2057             if (ok) ret = LoadImageW( 0, filename, IMAGE_BITMAP, cx, cy, flags | LR_LOADFROMFILE );
2058         }
2059     done:
2060         if (filename[0]) DeleteFileW( filename );
2061         FreeResource16( handle );
2062         return HBITMAP_16( ret );
2063     }
2064
2065     case IMAGE_ICON:
2066     case IMAGE_CURSOR:
2067     {
2068         HICON16 hIcon = 0;
2069         BYTE *dir, *bits;
2070         INT id = 0;
2071
2072         if (!(hRsrc = FindResource16( hinst, name,
2073                                       (LPCSTR)(type == IMAGE_ICON ? RT_GROUP_ICON : RT_GROUP_CURSOR ))))
2074             return 0;
2075         hGroupRsrc = hRsrc;
2076
2077         if (!(handle = LoadResource16( hinst, hRsrc ))) return 0;
2078         if ((dir = LockResource16( handle ))) id = LookupIconIdFromDirectory( dir, type == IMAGE_ICON );
2079         FreeResource16( handle );
2080         if (!id) return 0;
2081
2082         if (!(hRsrc = FindResource16( hinst, MAKEINTRESOURCEA(id),
2083                                       (LPCSTR)(type == IMAGE_ICON ? RT_ICON : RT_CURSOR) ))) return 0;
2084
2085         if ((flags & LR_SHARED) && (hIcon = find_shared_icon( hinst, hRsrc ) ) != 0) return hIcon;
2086
2087         if (!(handle = LoadResource16( hinst, hRsrc ))) return 0;
2088         bits = LockResource16( handle );
2089         hIcon = CreateIconFromResourceEx16( bits, 0, type == IMAGE_ICON, 0x00030000, cx, cy, flags );
2090         FreeResource16( handle );
2091
2092         if (hIcon && (flags & LR_SHARED)) add_shared_icon( hinst, hRsrc, hGroupRsrc, hIcon );
2093         return hIcon;
2094     }
2095     default:
2096         return 0;
2097     }
2098 }
2099
2100 /******************************************************************************
2101  *              CopyImage (USER.390) Creates new image and copies attributes to it
2102  *
2103  */
2104 HICON16 WINAPI CopyImage16(HANDLE16 hnd, UINT16 type, INT16 desiredx,
2105                            INT16 desiredy, UINT16 flags)
2106 {
2107     if (flags & LR_COPYFROMRESOURCE) FIXME( "LR_COPYFROMRESOURCE not supported\n" );
2108
2109     switch (type)
2110     {
2111     case IMAGE_BITMAP:
2112         return HBITMAP_16( CopyImage( HBITMAP_32(hnd), type, desiredx, desiredy, flags ));
2113     case IMAGE_ICON:
2114     case IMAGE_CURSOR:
2115         return CopyIcon16( FarGetOwner16(hnd), hnd );
2116     default:
2117         return 0;
2118     }
2119 }
2120
2121 /**********************************************************************
2122  *              DrawIconEx (USER.394)
2123  */
2124 BOOL16 WINAPI DrawIconEx16(HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon,
2125                            INT16 cxWidth, INT16 cyWidth, UINT16 istep,
2126                            HBRUSH16 hbr, UINT16 flags)
2127 {
2128   return DrawIconEx(HDC_32(hdc), xLeft, yTop, get_icon_32(hIcon), cxWidth, cyWidth,
2129                     istep, HBRUSH_32(hbr), flags);
2130 }
2131
2132 /**********************************************************************
2133  *              GetIconInfo (USER.395)
2134  */
2135 BOOL16 WINAPI GetIconInfo16(HICON16 hIcon, LPICONINFO16 iconinfo)
2136 {
2137     CURSORICONINFO *info = get_icon_ptr( hIcon );
2138     INT height;
2139
2140     if (!info) return FALSE;
2141
2142     if ((info->ptHotSpot.x == ICON_HOTSPOT) && (info->ptHotSpot.y == ICON_HOTSPOT))
2143     {
2144         iconinfo->fIcon    = TRUE;
2145         iconinfo->xHotspot = info->nWidth / 2;
2146         iconinfo->yHotspot = info->nHeight / 2;
2147     }
2148     else
2149     {
2150         iconinfo->fIcon    = FALSE;
2151         iconinfo->xHotspot = info->ptHotSpot.x;
2152         iconinfo->yHotspot = info->ptHotSpot.y;
2153     }
2154
2155     height = info->nHeight;
2156
2157     if (info->bBitsPerPixel > 1)
2158     {
2159         iconinfo->hbmColor = HBITMAP_16( CreateBitmap( info->nWidth, info->nHeight,
2160                                                        info->bPlanes, info->bBitsPerPixel,
2161                                                        (char *)(info + 1)
2162                                                        + info->nHeight *
2163                                                        get_bitmap_width_bytes(info->nWidth,1) ));
2164     }
2165     else
2166     {
2167         iconinfo->hbmColor = 0;
2168         height *= 2;
2169     }
2170
2171     iconinfo->hbmMask = HBITMAP_16( CreateBitmap( info->nWidth, height, 1, 1, info + 1 ));
2172     release_icon_ptr( hIcon, info );
2173     return TRUE;
2174 }
2175
2176
2177 /***********************************************************************
2178  *              FinalUserInit (USER.400)
2179  */
2180 void WINAPI FinalUserInit16( void )
2181 {
2182     /* FIXME: Should chain to FinalGdiInit */
2183 }
2184
2185
2186 /***********************************************************************
2187  *              CreateCursor (USER.406)
2188  */
2189 HCURSOR16 WINAPI CreateCursor16(HINSTANCE16 hInstance,
2190                                 INT16 xHotSpot, INT16 yHotSpot,
2191                                 INT16 nWidth, INT16 nHeight,
2192                                 LPCVOID lpANDbits, LPCVOID lpXORbits)
2193 {
2194   CURSORICONINFO info;
2195
2196   info.ptHotSpot.x = xHotSpot;
2197   info.ptHotSpot.y = yHotSpot;
2198   info.nWidth = nWidth;
2199   info.nHeight = nHeight;
2200   info.nWidthBytes = 0;
2201   info.bPlanes = 1;
2202   info.bBitsPerPixel = 1;
2203
2204   return CreateCursorIconIndirect16(hInstance, &info, lpANDbits, lpXORbits);
2205 }
2206
2207
2208 /***********************************************************************
2209  *              CreateIcon (USER.407)
2210  */
2211 HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth,
2212                              INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel,
2213                              LPCVOID lpANDbits, LPCVOID lpXORbits )
2214 {
2215     CURSORICONINFO info;
2216
2217     info.ptHotSpot.x = ICON_HOTSPOT;
2218     info.ptHotSpot.y = ICON_HOTSPOT;
2219     info.nWidth = nWidth;
2220     info.nHeight = nHeight;
2221     info.nWidthBytes = 0;
2222     info.bPlanes = bPlanes;
2223     info.bBitsPerPixel = bBitsPixel;
2224
2225     return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits );
2226 }
2227
2228
2229 /***********************************************************************
2230  *              CreateCursorIconIndirect (USER.408)
2231  */
2232 HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance,
2233                                            CURSORICONINFO *info,
2234                                            LPCVOID lpANDbits,
2235                                            LPCVOID lpXORbits )
2236 {
2237     HICON16 handle;
2238     CURSORICONINFO *ptr;
2239     int sizeAnd, sizeXor;
2240
2241     hInstance = GetExePtr( hInstance );  /* Make it a module handle */
2242     if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0;
2243     info->nWidthBytes = get_bitmap_width_bytes(info->nWidth,info->bBitsPerPixel);
2244     sizeXor = info->nHeight * info->nWidthBytes;
2245     sizeAnd = info->nHeight * get_bitmap_width_bytes( info->nWidth, 1 );
2246     if (!(handle = alloc_icon_handle( sizeof(CURSORICONINFO) + sizeXor + sizeAnd )))
2247         return 0;
2248     FarSetOwner16( handle, hInstance );
2249     ptr = get_icon_ptr( handle );
2250     memcpy( ptr, info, sizeof(*info) );
2251     memcpy( ptr + 1, lpANDbits, sizeAnd );
2252     memcpy( (char *)(ptr + 1) + sizeAnd, lpXORbits, sizeXor );
2253     release_icon_ptr( handle, ptr );
2254     return handle;
2255 }
2256
2257
2258 /***********************************************************************
2259  *              InitThreadInput   (USER.409)
2260  */
2261 HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
2262 {
2263     /* nothing to do here */
2264     return 0xbeef;
2265 }
2266
2267
2268 /*******************************************************************
2269  *         InsertMenu    (USER.410)
2270  */
2271 BOOL16 WINAPI InsertMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
2272                             UINT16 id, SEGPTR data )
2273 {
2274     UINT pos32 = (UINT)pos;
2275     if ((pos == (UINT16)-1) && (flags & MF_BYPOSITION)) pos32 = (UINT)-1;
2276     if (IS_MENU_STRING_ITEM(flags) && data)
2277         return InsertMenuA( HMENU_32(hMenu), pos32, flags, id, MapSL(data) );
2278     return InsertMenuA( HMENU_32(hMenu), pos32, flags, id, (LPSTR)data );
2279 }
2280
2281
2282 /*******************************************************************
2283  *         AppendMenu    (USER.411)
2284  */
2285 BOOL16 WINAPI AppendMenu16(HMENU16 hMenu, UINT16 flags, UINT16 id, SEGPTR data)
2286 {
2287     return InsertMenu16( hMenu, -1, flags | MF_BYPOSITION, id, data );
2288 }
2289
2290
2291 /**********************************************************************
2292  *         RemoveMenu   (USER.412)
2293  */
2294 BOOL16 WINAPI RemoveMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
2295 {
2296     return RemoveMenu( HMENU_32(hMenu), nPos, wFlags );
2297 }
2298
2299
2300 /**********************************************************************
2301  *         DeleteMenu    (USER.413)
2302  */
2303 BOOL16 WINAPI DeleteMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags )
2304 {
2305     return DeleteMenu( HMENU_32(hMenu), nPos, wFlags );
2306 }
2307
2308
2309 /*******************************************************************
2310  *         ModifyMenu    (USER.414)
2311  */
2312 BOOL16 WINAPI ModifyMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags,
2313                             UINT16 id, SEGPTR data )
2314 {
2315     if (IS_MENU_STRING_ITEM(flags))
2316         return ModifyMenuA( HMENU_32(hMenu), pos, flags, id, MapSL(data) );
2317     return ModifyMenuA( HMENU_32(hMenu), pos, flags, id, (LPSTR)data );
2318 }
2319
2320
2321 /**********************************************************************
2322  *         CreatePopupMenu    (USER.415)
2323  */
2324 HMENU16 WINAPI CreatePopupMenu16(void)
2325 {
2326     return HMENU_16( CreatePopupMenu() );
2327 }
2328
2329
2330 /**********************************************************************
2331  *         SetMenuItemBitmaps    (USER.418)
2332  */
2333 BOOL16 WINAPI SetMenuItemBitmaps16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags,
2334                                     HBITMAP16 hNewUnCheck, HBITMAP16 hNewCheck)
2335 {
2336     return SetMenuItemBitmaps( HMENU_32(hMenu), nPos, wFlags,
2337                                HBITMAP_32(hNewUnCheck), HBITMAP_32(hNewCheck) );
2338 }
2339
2340
2341 /***********************************************************************
2342  *           wvsprintf   (USER.421)
2343  */
2344 INT16 WINAPI wvsprintf16( LPSTR buffer, LPCSTR spec, VA_LIST16 args )
2345 {
2346     WPRINTF_FORMAT format;
2347     LPSTR p = buffer;
2348     UINT i, len, sign;
2349     CHAR number[20];
2350     CHAR char_view = 0;
2351     LPCSTR lpcstr_view = NULL;
2352     INT int_view;
2353     SEGPTR seg_str;
2354
2355     while (*spec)
2356     {
2357         if (*spec != '%') { *p++ = *spec++; continue; }
2358         spec++;
2359         if (*spec == '%') { *p++ = *spec++; continue; }
2360         spec += parse_format( spec, &format );
2361         switch(format.type)
2362         {
2363         case WPR_CHAR:
2364             char_view = VA_ARG16( args, CHAR );
2365             len = format.precision = 1;
2366             break;
2367         case WPR_STRING:
2368             seg_str = VA_ARG16( args, SEGPTR );
2369             if (IsBadReadPtr16( seg_str, 1 )) lpcstr_view = "";
2370             else lpcstr_view = MapSL( seg_str );
2371             if (!lpcstr_view) lpcstr_view = "(null)";
2372             for (len = 0; !format.precision || (len < format.precision); len++)
2373                 if (!lpcstr_view[len]) break;
2374             format.precision = len;
2375             break;
2376         case WPR_SIGNED:
2377             if (format.flags & WPRINTF_LONG) int_view = VA_ARG16( args, INT );
2378             else int_view = VA_ARG16( args, INT16 );
2379             len = sprintf( number, "%d", int_view );
2380             break;
2381         case WPR_UNSIGNED:
2382             if (format.flags & WPRINTF_LONG) int_view = VA_ARG16( args, UINT );
2383             else int_view = VA_ARG16( args, UINT16 );
2384             len = sprintf( number, "%u", int_view );
2385             break;
2386         case WPR_HEXA:
2387             if (format.flags & WPRINTF_LONG) int_view = VA_ARG16( args, UINT );
2388             else int_view = VA_ARG16( args, UINT16 );
2389             len = sprintf( number, (format.flags & WPRINTF_UPPER_HEX) ? "%X" : "%x", int_view);
2390             break;
2391         case WPR_UNKNOWN:
2392             continue;
2393         }
2394         if (format.precision < len) format.precision = len;
2395         if (format.flags & WPRINTF_LEFTALIGN) format.flags &= ~WPRINTF_ZEROPAD;
2396         if ((format.flags & WPRINTF_ZEROPAD) && (format.width > format.precision))
2397             format.precision = format.width;
2398         if (format.flags & WPRINTF_PREFIX_HEX) len += 2;
2399
2400         sign = 0;
2401         if (!(format.flags & WPRINTF_LEFTALIGN))
2402             for (i = format.precision; i < format.width; i++) *p++ = ' ';
2403         switch(format.type)
2404         {
2405         case WPR_CHAR:
2406             *p = char_view;
2407             /* wsprintf16 ignores null characters */
2408             if (*p != '\0') p++;
2409             else if (format.width > 1) *p++ = ' ';
2410             else len = 0;
2411             break;
2412         case WPR_STRING:
2413             if (len) memcpy( p, lpcstr_view, len );
2414             p += len;
2415             break;
2416         case WPR_HEXA:
2417             if (format.flags & WPRINTF_PREFIX_HEX)
2418             {
2419                 *p++ = '0';
2420                 *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x';
2421                 len -= 2;
2422             }
2423             /* fall through */
2424         case WPR_SIGNED:
2425             /* Transfer the sign now, just in case it will be zero-padded*/
2426             if (number[0] == '-')
2427             {
2428                 *p++ = '-';
2429                 sign = 1;
2430             }
2431             /* fall through */
2432         case WPR_UNSIGNED:
2433             for (i = len; i < format.precision; i++) *p++ = '0';
2434             if (len > sign) memcpy( p, number + sign, len - sign );
2435             p += len-sign;
2436             break;
2437         case WPR_UNKNOWN:
2438             continue;
2439         }
2440         if (format.flags & WPRINTF_LEFTALIGN)
2441             for (i = format.precision; i < format.width; i++) *p++ = ' ';
2442     }
2443     *p = 0;
2444     return p - buffer;
2445 }
2446
2447
2448 /***********************************************************************
2449  *           _wsprintf   (USER.420)
2450  */
2451 INT16 WINAPIV wsprintf16( LPSTR buffer, LPCSTR spec, VA_LIST16 valist )
2452 {
2453     return wvsprintf16( buffer, spec, valist );
2454 }
2455
2456
2457 /***********************************************************************
2458  *           lstrcmp   (USER.430)
2459  */
2460 INT16 WINAPI lstrcmp16( LPCSTR str1, LPCSTR str2 )
2461 {
2462     return strcmp( str1, str2 );
2463 }
2464
2465
2466 /***********************************************************************
2467  *           AnsiUpper   (USER.431)
2468  */
2469 SEGPTR WINAPI AnsiUpper16( SEGPTR strOrChar )
2470 {
2471     /* uppercase only one char if strOrChar < 0x10000 */
2472     if (HIWORD(strOrChar))
2473     {
2474         CharUpperA( MapSL(strOrChar) );
2475         return strOrChar;
2476     }
2477     else return (SEGPTR)CharUpperA( (LPSTR)strOrChar );
2478 }
2479
2480
2481 /***********************************************************************
2482  *           AnsiLower   (USER.432)
2483  */
2484 SEGPTR WINAPI AnsiLower16( SEGPTR strOrChar )
2485 {
2486     /* lowercase only one char if strOrChar < 0x10000 */
2487     if (HIWORD(strOrChar))
2488     {
2489         CharLowerA( MapSL(strOrChar) );
2490         return strOrChar;
2491     }
2492     else return (SEGPTR)CharLowerA( (LPSTR)strOrChar );
2493 }
2494
2495
2496 /***********************************************************************
2497  *           AnsiUpperBuff   (USER.437)
2498  */
2499 UINT16 WINAPI AnsiUpperBuff16( LPSTR str, UINT16 len )
2500 {
2501     CharUpperBuffA( str, len ? len : 65536 );
2502     return len;
2503 }
2504
2505
2506 /***********************************************************************
2507  *           AnsiLowerBuff   (USER.438)
2508  */
2509 UINT16 WINAPI AnsiLowerBuff16( LPSTR str, UINT16 len )
2510 {
2511     CharLowerBuffA( str, len ? len : 65536 );
2512     return len;
2513 }
2514
2515
2516 /*******************************************************************
2517  *              InsertMenuItem   (USER.441)
2518  *
2519  * FIXME: untested
2520  */
2521 BOOL16 WINAPI InsertMenuItem16( HMENU16 hmenu, UINT16 pos, BOOL16 byposition,
2522                                 const MENUITEMINFO16 *mii )
2523 {
2524     MENUITEMINFOA miia;
2525
2526     miia.cbSize        = sizeof(miia);
2527     miia.fMask         = mii->fMask;
2528     miia.dwTypeData    = (LPSTR)mii->dwTypeData;
2529     miia.fType         = mii->fType;
2530     miia.fState        = mii->fState;
2531     miia.wID           = mii->wID;
2532     miia.hSubMenu      = HMENU_32(mii->hSubMenu);
2533     miia.hbmpChecked   = HBITMAP_32(mii->hbmpChecked);
2534     miia.hbmpUnchecked = HBITMAP_32(mii->hbmpUnchecked);
2535     miia.dwItemData    = mii->dwItemData;
2536     miia.cch           = mii->cch;
2537     if (IS_MENU_STRING_ITEM(miia.fType))
2538         miia.dwTypeData = MapSL(mii->dwTypeData);
2539     return InsertMenuItemA( HMENU_32(hmenu), pos, byposition, &miia );
2540 }
2541
2542
2543 /**********************************************************************
2544  *           DrawState    (USER.449)
2545  */
2546 BOOL16 WINAPI DrawState16( HDC16 hdc, HBRUSH16 hbr, DRAWSTATEPROC16 func, LPARAM ldata,
2547                            WPARAM16 wdata, INT16 x, INT16 y, INT16 cx, INT16 cy, UINT16 flags )
2548 {
2549     struct draw_state_info info;
2550     UINT opcode = flags & 0xf;
2551
2552     if (opcode == DST_TEXT || opcode == DST_PREFIXTEXT)
2553     {
2554         /* make sure DrawStateA doesn't try to use ldata as a pointer */
2555         if (!wdata) wdata = strlen( MapSL(ldata) );
2556         if (!cx || !cy)
2557         {
2558             SIZE s;
2559             if (!GetTextExtentPoint32A( HDC_32(hdc), MapSL(ldata), wdata, &s )) return FALSE;
2560             if (!cx) cx = s.cx;
2561             if (!cy) cy = s.cy;
2562         }
2563     }
2564     info.proc  = func;
2565     info.param = ldata;
2566     return DrawStateA( HDC_32(hdc), HBRUSH_32(hbr), draw_state_callback,
2567                        (LPARAM)&info, wdata, x, y, cx, cy, flags );
2568 }
2569
2570
2571 /**********************************************************************
2572  *              CreateIconFromResourceEx (USER.450)
2573  *
2574  * FIXME: not sure about exact parameter types
2575  */
2576 HICON16 WINAPI CreateIconFromResourceEx16(LPBYTE bits, UINT16 cbSize,
2577                                           BOOL16 bIcon, DWORD dwVersion,
2578                                           INT16 width, INT16 height,
2579                                           UINT16 cFlag)
2580 {
2581     return get_icon_16( CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, width, height, cFlag ));
2582 }
2583
2584
2585 /***********************************************************************
2586  *              AdjustWindowRectEx (USER.454)
2587  */
2588 BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style, BOOL16 menu, DWORD exStyle )
2589 {
2590     RECT rect32;
2591     BOOL ret;
2592
2593     rect32.left   = rect->left;
2594     rect32.top    = rect->top;
2595     rect32.right  = rect->right;
2596     rect32.bottom = rect->bottom;
2597     ret = AdjustWindowRectEx( &rect32, style, menu, exStyle );
2598     rect->left   = rect32.left;
2599     rect->top    = rect32.top;
2600     rect->right  = rect32.right;
2601     rect->bottom = rect32.bottom;
2602     return ret;
2603 }
2604
2605
2606 /**********************************************************************
2607  *              GetIconID (USER.455)
2608  */
2609 WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType )
2610 {
2611     BYTE *dir = GlobalLock16(hResource);
2612
2613     switch (resType)
2614     {
2615     case RT_CURSOR:
2616         return LookupIconIdFromDirectoryEx16( dir, FALSE, GetSystemMetrics(SM_CXCURSOR),
2617                                               GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME );
2618     case RT_ICON:
2619         return LookupIconIdFromDirectoryEx16( dir, TRUE, GetSystemMetrics(SM_CXICON),
2620                                               GetSystemMetrics(SM_CYICON), 0 );
2621     }
2622     return 0;
2623 }
2624
2625
2626 /**********************************************************************
2627  *              LoadIconHandler (USER.456)
2628  */
2629 HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew )
2630 {
2631     return CreateIconFromResourceEx16( LockResource16( hResource ), 0, TRUE,
2632                                        bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR );
2633 }
2634
2635
2636 /***********************************************************************
2637  *              DestroyIcon (USER.457)
2638  */
2639 BOOL16 WINAPI DestroyIcon16(HICON16 hIcon)
2640 {
2641     int count;
2642
2643     TRACE("%04x\n", hIcon );
2644
2645     count = release_shared_icon( hIcon );
2646     if (count != -1) return !count;
2647     /* assume non-shared */
2648     free_icon_handle( hIcon );
2649     return TRUE;
2650 }
2651
2652 /***********************************************************************
2653  *              DestroyCursor (USER.458)
2654  */
2655 BOOL16 WINAPI DestroyCursor16(HCURSOR16 hCursor)
2656 {
2657     return DestroyIcon16( hCursor );
2658 }
2659
2660
2661 /***********************************************************************
2662  *              DumpIcon (USER.459)
2663  */
2664 DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen,
2665                        SEGPTR *lpXorBits, SEGPTR *lpAndBits )
2666 {
2667     CURSORICONINFO *info = MapSL( pInfo );
2668     int sizeAnd, sizeXor;
2669
2670     if (!info) return 0;
2671     sizeXor = info->nHeight * info->nWidthBytes;
2672     sizeAnd = info->nHeight * get_bitmap_width_bytes( info->nWidth, 1 );
2673     if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO);
2674     if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd;
2675     if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor;
2676     return MAKELONG( sizeXor, sizeXor );
2677 }
2678
2679
2680 /*******************************************************************
2681  *                      DRAG_QueryUpdate16
2682  *
2683  * Recursively find a child that contains spDragInfo->pt point
2684  * and send WM_QUERYDROPOBJECT. Helper for DragObject16.
2685  */
2686 static BOOL DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo )
2687 {
2688     BOOL bResult = 0;
2689     WPARAM wParam;
2690     POINT pt, old_pt;
2691     LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo);
2692     RECT tempRect;
2693     HWND child;
2694
2695     if (!IsWindowEnabled(hQueryWnd)) return FALSE;
2696
2697     old_pt.x = ptrDragInfo->pt.x;
2698     old_pt.y = ptrDragInfo->pt.y;
2699     pt = old_pt;
2700     ScreenToClient( hQueryWnd, &pt );
2701     child = ChildWindowFromPointEx( hQueryWnd, pt, CWP_SKIPINVISIBLE );
2702     if (!child) return FALSE;
2703
2704     if (child != hQueryWnd)
2705     {
2706         wParam = 0;
2707         if (DRAG_QueryUpdate16( child, spDragInfo )) return TRUE;
2708     }
2709     else
2710     {
2711         GetClientRect( hQueryWnd, &tempRect );
2712         wParam = !PtInRect( &tempRect, pt );
2713     }
2714
2715     ptrDragInfo->pt.x = pt.x;
2716     ptrDragInfo->pt.y = pt.y;
2717     ptrDragInfo->hScope = HWND_16(hQueryWnd);
2718
2719     bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, wParam, spDragInfo );
2720
2721     if (!bResult)
2722     {
2723         ptrDragInfo->pt.x = old_pt.x;
2724         ptrDragInfo->pt.y = old_pt.y;
2725     }
2726     return bResult;
2727 }
2728
2729
2730 /******************************************************************************
2731  *              DragObject (USER.464)
2732  */
2733 DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj,
2734                            HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor )
2735 {
2736     MSG msg;
2737     LPDRAGINFO16 lpDragInfo;
2738     SEGPTR      spDragInfo;
2739     HCURSOR     hOldCursor=0, hBummer=0, hCursor32;
2740     HGLOBAL16   hDragInfo  = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16));
2741     HCURSOR     hCurrentCursor = 0;
2742     HWND16      hCurrentWnd = 0;
2743
2744     lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo);
2745     spDragInfo = WOWGlobalLock16(hDragInfo);
2746
2747     if( !lpDragInfo || !spDragInfo ) return 0L;
2748
2749     if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO))))
2750     {
2751         GlobalFree16(hDragInfo);
2752         return 0L;
2753     }
2754
2755     if ((hCursor32 = get_icon_32( hCursor ))) SetCursor( hCursor32 );
2756
2757     lpDragInfo->hWnd   = hWnd;
2758     lpDragInfo->hScope = 0;
2759     lpDragInfo->wFlags = wObj;
2760     lpDragInfo->hList  = szList; /* near pointer! */
2761     lpDragInfo->hOfStruct = hOfStruct;
2762     lpDragInfo->l = 0L;
2763
2764     SetCapture( HWND_32(hWnd) );
2765     ShowCursor( TRUE );
2766
2767     do
2768     {
2769         GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST );
2770
2771        *(lpDragInfo+1) = *lpDragInfo;
2772
2773         lpDragInfo->pt.x = msg.pt.x;
2774         lpDragInfo->pt.y = msg.pt.y;
2775
2776         /* update DRAGINFO struct */
2777         if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 )
2778             hCurrentCursor = hCursor32;
2779         else
2780         {
2781             hCurrentCursor = hBummer;
2782             lpDragInfo->hScope = 0;
2783         }
2784         if( hCurrentCursor )
2785             SetCursor(hCurrentCursor);
2786
2787         /* send WM_DRAGLOOP */
2788         SendMessage16( hWnd, WM_DRAGLOOP, hCurrentCursor != hBummer, spDragInfo );
2789         /* send WM_DRAGSELECT or WM_DRAGMOVE */
2790         if( hCurrentWnd != lpDragInfo->hScope )
2791         {
2792             if( hCurrentWnd )
2793                 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0,
2794                         MAKELPARAM(LOWORD(spDragInfo)+sizeof(DRAGINFO16),
2795                                    HIWORD(spDragInfo)) );
2796             hCurrentWnd = lpDragInfo->hScope;
2797             if( hCurrentWnd )
2798                 SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, spDragInfo);
2799         }
2800         else
2801             if( hCurrentWnd )
2802                 SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, spDragInfo);
2803
2804     } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP );
2805
2806     ReleaseCapture();
2807     ShowCursor( FALSE );
2808
2809     if( hCursor ) SetCursor(hOldCursor);
2810
2811     if( hCurrentCursor != hBummer )
2812         msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT,
2813                                     hWnd, spDragInfo );
2814     else
2815         msg.lParam = 0;
2816     GlobalFree16(hDragInfo);
2817
2818     return (DWORD)(msg.lParam);
2819 }
2820
2821
2822 /***********************************************************************
2823  *              DrawFocusRect (USER.466)
2824  */
2825 void WINAPI DrawFocusRect16( HDC16 hdc, const RECT16* rc )
2826 {
2827     RECT rect32;
2828
2829     rect32.left   = rc->left;
2830     rect32.top    = rc->top;
2831     rect32.right  = rc->right;
2832     rect32.bottom = rc->bottom;
2833     DrawFocusRect( HDC_32(hdc), &rect32 );
2834 }
2835
2836
2837 /***********************************************************************
2838  *           AnsiNext   (USER.472)
2839  */
2840 SEGPTR WINAPI AnsiNext16(SEGPTR current)
2841 {
2842     char *ptr = MapSL(current);
2843     return current + (CharNextA(ptr) - ptr);
2844 }
2845
2846
2847 /***********************************************************************
2848  *           AnsiPrev   (USER.473)
2849  */
2850 SEGPTR WINAPI AnsiPrev16( LPCSTR start, SEGPTR current )
2851 {
2852     char *ptr = MapSL(current);
2853     return current - (ptr - CharPrevA( start, ptr ));
2854 }
2855
2856
2857 /****************************************************************************
2858  *              GetKeyboardLayoutName (USER.477)
2859  */
2860 INT16 WINAPI GetKeyboardLayoutName16( LPSTR name )
2861 {
2862     return GetKeyboardLayoutNameA( name );
2863 }
2864
2865
2866 /***********************************************************************
2867  *              SystemParametersInfo (USER.483)
2868  */
2869 BOOL16 WINAPI SystemParametersInfo16( UINT16 uAction, UINT16 uParam,
2870                                       LPVOID lpvParam, UINT16 fuWinIni )
2871 {
2872     BOOL16 ret;
2873
2874     TRACE("(%u, %u, %p, %u)\n", uAction, uParam, lpvParam, fuWinIni);
2875
2876     switch (uAction)
2877     {
2878     case SPI_GETBEEP:
2879     case SPI_GETSCREENSAVEACTIVE:
2880     case SPI_GETICONTITLEWRAP:
2881     case SPI_GETMENUDROPALIGNMENT:
2882     case SPI_GETFASTTASKSWITCH:
2883     case SPI_GETDRAGFULLWINDOWS:
2884     {
2885         BOOL tmp;
2886         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
2887         if (ret && lpvParam) *(BOOL16 *)lpvParam = tmp;
2888         break;
2889     }
2890
2891     case SPI_GETBORDER:
2892     case SPI_ICONHORIZONTALSPACING:
2893     case SPI_GETSCREENSAVETIMEOUT:
2894     case SPI_GETGRIDGRANULARITY:
2895     case SPI_GETKEYBOARDDELAY:
2896     case SPI_ICONVERTICALSPACING:
2897     {
2898         INT tmp;
2899         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
2900         if (ret && lpvParam) *(INT16 *)lpvParam = tmp;
2901         break;
2902     }
2903
2904     case SPI_GETKEYBOARDSPEED:
2905     case SPI_GETMOUSEHOVERWIDTH:
2906     case SPI_GETMOUSEHOVERHEIGHT:
2907     case SPI_GETMOUSEHOVERTIME:
2908     {
2909         DWORD tmp;
2910         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
2911         if (ret && lpvParam) *(WORD *)lpvParam = tmp;
2912         break;
2913     }
2914
2915     case SPI_GETICONTITLELOGFONT:
2916     {
2917         LOGFONTA tmp;
2918         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
2919         if (ret && lpvParam) logfont_32_to_16( &tmp, (LPLOGFONT16)lpvParam );
2920         break;
2921     }
2922
2923     case SPI_GETNONCLIENTMETRICS:
2924     {
2925         NONCLIENTMETRICSA tmp;
2926         LPNONCLIENTMETRICS16 lpnm16 = (LPNONCLIENTMETRICS16)lpvParam;
2927         if (lpnm16 && lpnm16->cbSize == sizeof(NONCLIENTMETRICS16))
2928         {
2929             tmp.cbSize = sizeof(NONCLIENTMETRICSA);
2930             ret = SystemParametersInfoA( uAction, uParam, &tmp, fuWinIni );
2931             if (ret)
2932             {
2933                 lpnm16->iBorderWidth     = tmp.iBorderWidth;
2934                 lpnm16->iScrollWidth     = tmp.iScrollWidth;
2935                 lpnm16->iScrollHeight    = tmp.iScrollHeight;
2936                 lpnm16->iCaptionWidth    = tmp.iCaptionWidth;
2937                 lpnm16->iCaptionHeight   = tmp.iCaptionHeight;
2938                 lpnm16->iSmCaptionWidth  = tmp.iSmCaptionWidth;
2939                 lpnm16->iSmCaptionHeight = tmp.iSmCaptionHeight;
2940                 lpnm16->iMenuWidth       = tmp.iMenuWidth;
2941                 lpnm16->iMenuHeight      = tmp.iMenuHeight;
2942                 logfont_32_to_16( &tmp.lfCaptionFont,   &lpnm16->lfCaptionFont );
2943                 logfont_32_to_16( &tmp.lfSmCaptionFont, &lpnm16->lfSmCaptionFont );
2944                 logfont_32_to_16( &tmp.lfMenuFont,      &lpnm16->lfMenuFont );
2945                 logfont_32_to_16( &tmp.lfStatusFont,    &lpnm16->lfStatusFont );
2946                 logfont_32_to_16( &tmp.lfMessageFont,   &lpnm16->lfMessageFont );
2947             }
2948         }
2949         else /* winfile 95 sets cbSize to 340 */
2950             ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
2951         break;
2952     }
2953
2954     case SPI_GETWORKAREA:
2955     {
2956         RECT tmp;
2957         ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni );
2958         if (ret && lpvParam)
2959         {
2960             RECT16 *r16 = lpvParam;
2961             r16->left   = tmp.left;
2962             r16->top    = tmp.top;
2963             r16->right  = tmp.right;
2964             r16->bottom = tmp.bottom;
2965         }
2966         break;
2967     }
2968
2969     default:
2970         ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni );
2971         break;
2972     }
2973
2974     return ret;
2975 }
2976
2977
2978 /***********************************************************************
2979  *              USER_489 (USER.489)
2980  */
2981 LONG WINAPI stub_USER_489(void)
2982 {
2983     FIXME("stub\n");
2984     return 0;
2985 }
2986
2987
2988 /***********************************************************************
2989  *              USER_490 (USER.490)
2990  */
2991 LONG WINAPI stub_USER_490(void)
2992 {
2993     FIXME("stub\n");
2994     return 0;
2995 }
2996
2997
2998 /***********************************************************************
2999  *              USER_492 (USER.492)
3000  */
3001 LONG WINAPI stub_USER_492(void)
3002 {
3003     FIXME("stub\n");
3004     return 0;
3005 }
3006
3007
3008 /***********************************************************************
3009  *              USER_496 (USER.496)
3010  */
3011 LONG WINAPI stub_USER_496(void)
3012 {
3013     FIXME("stub\n");
3014     return 0;
3015 }
3016
3017
3018 /***********************************************************************
3019  *           FormatMessage   (USER.606)
3020  */
3021 DWORD WINAPI FormatMessage16(
3022     DWORD   dwFlags,
3023     SEGPTR lpSource,     /* [in] NOTE: not always a valid pointer */
3024     WORD   dwMessageId,
3025     WORD   dwLanguageId,
3026     LPSTR  lpBuffer,     /* [out] NOTE: *((HLOCAL16*)) for FORMAT_MESSAGE_ALLOCATE_BUFFER*/
3027     WORD   nSize,
3028     LPDWORD args )       /* [in] NOTE: va_list *args */
3029 {
3030 /* This implementation is completely dependent on the format of the va_list on x86 CPUs */
3031     LPSTR       target,t;
3032     DWORD       talloced;
3033     LPSTR       from,f;
3034     DWORD       width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
3035     BOOL        eos = FALSE;
3036     LPSTR       allocstring = NULL;
3037
3038     TRACE("(0x%x,%x,%d,0x%x,%p,%d,%p)\n",
3039           dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
3040         if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
3041                 && (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)) return 0;
3042         if ((dwFlags & FORMAT_MESSAGE_FROM_STRING)
3043                 &&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
3044                         || (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0;
3045
3046     if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK)
3047         FIXME("line wrapping (%u) not supported.\n", width);
3048     from = NULL;
3049     if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
3050     {
3051         char *source = MapSL(lpSource);
3052         from = HeapAlloc( GetProcessHeap(), 0, strlen(source)+1 );
3053         strcpy( from, source );
3054     }
3055     else if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
3056         from = HeapAlloc( GetProcessHeap(),0,200 );
3057         sprintf(from,"Systemmessage, messageid = 0x%08x\n",dwMessageId);
3058     }
3059     else if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
3060         INT16   bufsize;
3061         HINSTANCE16 hinst16 = ((HINSTANCE16)lpSource & 0xffff);
3062
3063         dwMessageId &= 0xFFFF;
3064         bufsize=LoadString16(hinst16,dwMessageId,NULL,0);
3065         if (bufsize) {
3066             from = HeapAlloc( GetProcessHeap(), 0, bufsize +1);
3067             LoadString16(hinst16,dwMessageId,from,bufsize+1);
3068         }
3069     }
3070     target      = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
3071     t   = target;
3072     talloced= 100;
3073
3074 #define ADD_TO_T(c) \
3075         *t++=c;\
3076         if (t-target == talloced) {\
3077                 target  = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
3078                 t       = target+talloced;\
3079                 talloced*=2;\
3080         }
3081
3082     if (from) {
3083         f=from;
3084         while (*f && !eos) {
3085             if (*f=='%') {
3086                 int     insertnr;
3087                 char    *fmtstr,*x,*lastf;
3088                 DWORD   *argliststart;
3089
3090                 fmtstr = NULL;
3091                 lastf = f;
3092                 f++;
3093                 if (!*f) {
3094                     ADD_TO_T('%');
3095                     continue;
3096                 }
3097                 switch (*f) {
3098                 case '1':case '2':case '3':case '4':case '5':
3099                 case '6':case '7':case '8':case '9':
3100                     insertnr=*f-'0';
3101                     switch (f[1]) {
3102                     case '0':case '1':case '2':case '3':
3103                     case '4':case '5':case '6':case '7':
3104                     case '8':case '9':
3105                         f++;
3106                         insertnr=insertnr*10+*f-'0';
3107                         f++;
3108                         break;
3109                     default:
3110                         f++;
3111                         break;
3112                     }
3113                     if (*f=='!') {
3114                         f++;
3115                         if (NULL!=(x=strchr(f,'!'))) {
3116                             *x='\0';
3117                             fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
3118                             sprintf(fmtstr,"%%%s",f);
3119                             f=x+1;
3120                         } else {
3121                             fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
3122                             sprintf(fmtstr,"%%%s",f);
3123                             f+=strlen(f); /*at \0*/
3124                         }
3125                     }
3126                     else
3127                     {
3128                         if(!args) break;
3129                         fmtstr=HeapAlloc( GetProcessHeap(), 0, 3 );
3130                         strcpy( fmtstr, "%s" );
3131                     }
3132                     if (args) {
3133                         int     ret;
3134                         int     sz;
3135                         LPSTR   b = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz = 100);
3136
3137                         argliststart=args+insertnr-1;
3138
3139                         /* CMF - This makes a BIG assumption about va_list */
3140                         while ((ret = vsnprintf(b, sz, fmtstr, (va_list) argliststart) < 0) || (ret >= sz)) {
3141                             sz = (ret == -1 ? sz + 100 : ret + 1);
3142                             b = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, b, sz);
3143                         }
3144                         for (x=b; *x; x++) ADD_TO_T(*x);
3145                         HeapFree(GetProcessHeap(), 0, b);
3146                     } else {
3147                         /* NULL args - copy formatstr
3148                          * (probably wrong)
3149                          */
3150                         while ((lastf<f)&&(*lastf)) {
3151                             ADD_TO_T(*lastf++);
3152                         }
3153                     }
3154                     HeapFree(GetProcessHeap(),0,fmtstr);
3155                     break;
3156                 case '0': /* Just stop processing format string */
3157                     eos = TRUE;
3158                     f++;
3159                     break;
3160                 case 'n': /* 16 bit version just outputs 'n' */
3161                 default:
3162                     ADD_TO_T(*f++);
3163                     break;
3164                 }
3165             } else { /* '\n' or '\r' gets mapped to "\r\n" */
3166                 if(*f == '\n' || *f == '\r') {
3167                     if (width == 0) {
3168                         ADD_TO_T('\r');
3169                         ADD_TO_T('\n');
3170                         if(*f++ == '\r' && *f == '\n')
3171                             f++;
3172                     }
3173                 } else {
3174                     ADD_TO_T(*f++);
3175                 }
3176             }
3177         }
3178         *t='\0';
3179     }
3180     talloced = strlen(target)+1;
3181     if (nSize && talloced<nSize) {
3182         target = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
3183     }
3184     TRACE("-- %s\n",debugstr_a(target));
3185     if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
3186         /* nSize is the MINIMUM size */
3187         HLOCAL16 h = LocalAlloc16(LPTR,talloced);
3188         SEGPTR ptr = LocalLock16(h);
3189         allocstring = MapSL( ptr );
3190         memcpy( allocstring,target,talloced);
3191         LocalUnlock16( h );
3192         *((HLOCAL16*)lpBuffer) = h;
3193     } else
3194         lstrcpynA(lpBuffer,target,nSize);
3195     HeapFree(GetProcessHeap(),0,target);
3196     HeapFree(GetProcessHeap(),0,from);
3197     return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
3198         strlen(allocstring):
3199         strlen(lpBuffer);
3200 }
3201 #undef ADD_TO_T
3202
3203
3204 /**********************************************************************
3205  *              DestroyIcon32 (USER.610)
3206  *
3207  * This routine is actually exported from Win95 USER under the name
3208  * DestroyIcon32 ...  The behaviour implemented here should mimic
3209  * the Win95 one exactly, especially the return values, which
3210  * depend on the setting of various flags.
3211  */
3212 WORD WINAPI DestroyIcon32( HGLOBAL16 handle, UINT16 flags )
3213 {
3214     WORD retv;
3215
3216     /* Check whether destroying active cursor */
3217
3218     if (GetCursor16() == handle)
3219     {
3220         WARN("Destroying active cursor!\n" );
3221         return FALSE;
3222     }
3223
3224     /* Try shared cursor/icon first */
3225
3226     if (!(flags & CID_NONSHARED))
3227     {
3228         INT count = release_shared_icon( handle );
3229         if (count != -1)
3230             return (flags & CID_WIN32) ? TRUE : (count == 0);
3231     }
3232
3233     /* Now assume non-shared cursor/icon */
3234
3235     retv = free_icon_handle( handle );
3236     return (flags & CID_RESOURCE)? retv : TRUE;
3237 }
3238
3239
3240 /***********************************************************************
3241  *              ChangeDisplaySettings (USER.620)
3242  */
3243 LONG WINAPI ChangeDisplaySettings16( LPDEVMODEA devmode, DWORD flags )
3244 {
3245     return ChangeDisplaySettingsA( devmode, flags );
3246 }
3247
3248
3249 /***********************************************************************
3250  *              EnumDisplaySettings (USER.621)
3251  */
3252 BOOL16 WINAPI EnumDisplaySettings16( LPCSTR name, DWORD n, LPDEVMODEA devmode )
3253 {
3254     return EnumDisplaySettingsA( name, n, devmode );
3255 }
3256
3257 /**********************************************************************
3258  *          DrawFrameControl  (USER.656)
3259  */
3260 BOOL16 WINAPI DrawFrameControl16( HDC16 hdc, LPRECT16 rc, UINT16 uType, UINT16 uState )
3261 {
3262     RECT rect32;
3263     BOOL ret;
3264
3265     rect32.left   = rc->left;
3266     rect32.top    = rc->top;
3267     rect32.right  = rc->right;
3268     rect32.bottom = rc->bottom;
3269     ret = DrawFrameControl( HDC_32(hdc), &rect32, uType, uState );
3270     rc->left   = rect32.left;
3271     rc->top    = rect32.top;
3272     rc->right  = rect32.right;
3273     rc->bottom = rect32.bottom;
3274     return ret;
3275 }
3276
3277 /**********************************************************************
3278  *          DrawEdge   (USER.659)
3279  */
3280 BOOL16 WINAPI DrawEdge16( HDC16 hdc, LPRECT16 rc, UINT16 edge, UINT16 flags )
3281 {
3282     RECT rect32;
3283     BOOL ret;
3284
3285     rect32.left   = rc->left;
3286     rect32.top    = rc->top;
3287     rect32.right  = rc->right;
3288     rect32.bottom = rc->bottom;
3289     ret = DrawEdge( HDC_32(hdc), &rect32, edge, flags );
3290     rc->left   = rect32.left;
3291     rc->top    = rect32.top;
3292     rc->right  = rect32.right;
3293     rc->bottom = rect32.bottom;
3294     return ret;
3295 }
3296
3297 /**********************************************************************
3298  *              CheckMenuRadioItem (USER.666)
3299  */
3300 BOOL16 WINAPI CheckMenuRadioItem16(HMENU16 hMenu, UINT16 first, UINT16 last,
3301                                    UINT16 check, BOOL16 bypos)
3302 {
3303      return CheckMenuRadioItem( HMENU_32(hMenu), first, last, check, bypos );
3304 }