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