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