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