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