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