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