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