/* * Misc 16-bit USER functions * * Copyright 1993, 1996 Alexandre Julliard * Copyright 2002 Patrik Stridvall * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include #define OEMRESOURCE #include "wine/winuser16.h" #include "windef.h" #include "winbase.h" #include "wownt32.h" #include "user_private.h" #include "wine/list.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(user); /* handle to handle 16 conversions */ #define HANDLE_16(h32) (LOWORD(h32)) #define HGDIOBJ_16(h32) (LOWORD(h32)) /* handle16 to handle conversions */ #define HANDLE_32(h16) ((HANDLE)(ULONG_PTR)(h16)) #define HGDIOBJ_32(h16) ((HGDIOBJ)(ULONG_PTR)(h16)) #define IS_MENU_STRING_ITEM(flags) \ (((flags) & (MF_STRING | MF_BITMAP | MF_OWNERDRAW | MF_SEPARATOR)) == MF_STRING) /* UserSeeUserDo parameters */ #define USUD_LOCALALLOC 0x0001 #define USUD_LOCALFREE 0x0002 #define USUD_LOCALCOMPACT 0x0003 #define USUD_LOCALHEAP 0x0004 #define USUD_FIRSTCLASS 0x0005 #define CID_RESOURCE 0x0001 #define CID_WIN32 0x0004 #define CID_NONSHARED 0x0008 WORD USER_HeapSel = 0; /* USER heap selector */ static HINSTANCE16 gdi_inst; struct gray_string_info { GRAYSTRINGPROC16 proc; LPARAM param; char str[1]; }; /* callback for 16-bit gray string proc with opaque pointer */ static BOOL CALLBACK gray_string_callback( HDC hdc, LPARAM param, INT len ) { const struct gray_string_info *info = (struct gray_string_info *)param; WORD args[4]; DWORD ret; args[3] = HDC_16(hdc); args[2] = HIWORD(info->param); args[1] = LOWORD(info->param); args[0] = len; WOWCallback16Ex( (DWORD)info->proc, WCB16_PASCAL, sizeof(args), args, &ret ); return LOWORD(ret); } /* callback for 16-bit gray string proc with string pointer */ static BOOL CALLBACK gray_string_callback_ptr( HDC hdc, LPARAM param, INT len ) { const struct gray_string_info *info; char *str = (char *)param; info = (struct gray_string_info *)(str - offsetof( struct gray_string_info, str )); return gray_string_callback( hdc, (LPARAM)info, len ); } struct draw_state_info { DRAWSTATEPROC16 proc; LPARAM param; }; /* callback for 16-bit DrawState functions */ static BOOL CALLBACK draw_state_callback( HDC hdc, LPARAM lparam, WPARAM wparam, int cx, int cy ) { const struct draw_state_info *info = (struct draw_state_info *)lparam; WORD args[6]; DWORD ret; args[5] = HDC_16(hdc); args[4] = HIWORD(info->param); args[3] = LOWORD(info->param); args[2] = wparam; args[1] = cx; args[0] = cy; WOWCallback16Ex( (DWORD)info->proc, WCB16_PASCAL, sizeof(args), args, &ret ); return LOWORD(ret); } /* This function is a copy of the one in objects/font.c */ static void logfont_32_to_16( const LOGFONTA* font32, LPLOGFONT16 font16 ) { font16->lfHeight = font32->lfHeight; font16->lfWidth = font32->lfWidth; font16->lfEscapement = font32->lfEscapement; font16->lfOrientation = font32->lfOrientation; font16->lfWeight = font32->lfWeight; font16->lfItalic = font32->lfItalic; font16->lfUnderline = font32->lfUnderline; font16->lfStrikeOut = font32->lfStrikeOut; font16->lfCharSet = font32->lfCharSet; font16->lfOutPrecision = font32->lfOutPrecision; font16->lfClipPrecision = font32->lfClipPrecision; font16->lfQuality = font32->lfQuality; font16->lfPitchAndFamily = font32->lfPitchAndFamily; lstrcpynA( font16->lfFaceName, font32->lfFaceName, LF_FACESIZE ); } static int get_bitmap_width_bytes( int width, int bpp ) { switch(bpp) { case 1: return 2 * ((width+15) / 16); case 4: return 2 * ((width+3) / 4); case 24: width *= 3; /* fall through */ case 8: return width + (width & 1); case 16: case 15: return width * 2; case 32: return width * 4; default: WARN("Unknown depth %d, please report.\n", bpp ); } return -1; } /*********************************************************************** * Helper for wsprintf16 */ #define WPRINTF_LEFTALIGN 0x0001 /* Align output on the left ('-' prefix) */ #define WPRINTF_PREFIX_HEX 0x0002 /* Prefix hex with 0x ('#' prefix) */ #define WPRINTF_ZEROPAD 0x0004 /* Pad with zeros ('0' prefix) */ #define WPRINTF_LONG 0x0008 /* Long arg ('l' prefix) */ #define WPRINTF_SHORT 0x0010 /* Short arg ('h' prefix) */ #define WPRINTF_UPPER_HEX 0x0020 /* Upper-case hex ('X' specifier) */ typedef enum { WPR_UNKNOWN, WPR_CHAR, WPR_STRING, WPR_SIGNED, WPR_UNSIGNED, WPR_HEXA } WPRINTF_TYPE; typedef struct { UINT flags; UINT width; UINT precision; WPRINTF_TYPE type; } WPRINTF_FORMAT; static INT parse_format( LPCSTR format, WPRINTF_FORMAT *res ) { LPCSTR p = format; res->flags = 0; res->width = 0; res->precision = 0; if (*p == '-') { res->flags |= WPRINTF_LEFTALIGN; p++; } if (*p == '#') { res->flags |= WPRINTF_PREFIX_HEX; p++; } if (*p == '0') { res->flags |= WPRINTF_ZEROPAD; p++; } while ((*p >= '0') && (*p <= '9')) /* width field */ { res->width = res->width * 10 + *p - '0'; p++; } if (*p == '.') /* precision field */ { p++; while ((*p >= '0') && (*p <= '9')) { res->precision = res->precision * 10 + *p - '0'; p++; } } if (*p == 'l') { res->flags |= WPRINTF_LONG; p++; } else if (*p == 'h') { res->flags |= WPRINTF_SHORT; p++; } switch(*p) { case 'c': case 'C': /* no Unicode in Win16 */ res->type = WPR_CHAR; break; case 's': case 'S': res->type = WPR_STRING; break; case 'd': case 'i': res->type = WPR_SIGNED; break; case 'u': res->type = WPR_UNSIGNED; break; case 'p': res->width = 8; res->flags |= WPRINTF_ZEROPAD; /* fall through */ case 'X': res->flags |= WPRINTF_UPPER_HEX; /* fall through */ case 'x': res->type = WPR_HEXA; break; default: /* unknown format char */ res->type = WPR_UNKNOWN; p--; /* print format as normal char */ break; } return (INT)(p - format) + 1; } /********************************************************************** * Management of the 16-bit cursors and icons */ struct cache_entry { struct list entry; HINSTANCE16 inst; HRSRC16 rsrc; HRSRC16 group; HICON16 icon; INT count; }; static struct list icon_cache = LIST_INIT( icon_cache ); static const WORD ICON_HOTSPOT = 0x4242; static HICON16 alloc_icon_handle( unsigned int size ) { HGLOBAL16 handle = GlobalAlloc16( GMEM_MOVEABLE, size + sizeof(ULONG_PTR) ); char *ptr = GlobalLock16( handle ); memset( ptr + size, 0, sizeof(ULONG_PTR) ); GlobalUnlock16( handle ); FarSetOwner16( handle, 0 ); return handle; } static CURSORICONINFO *get_icon_ptr( HICON16 handle ) { return GlobalLock16( handle ); } static void release_icon_ptr( HICON16 handle, CURSORICONINFO *ptr ) { GlobalUnlock16( handle ); } static HICON store_icon_32( HICON16 icon16, HICON icon ) { HICON ret = 0; CURSORICONINFO *ptr = get_icon_ptr( icon16 ); if (ptr) { unsigned int and_size = ptr->nHeight * get_bitmap_width_bytes( ptr->nWidth, 1 ); unsigned int xor_size = ptr->nHeight * get_bitmap_width_bytes( ptr->nWidth, ptr->bBitsPerPixel ); if (GlobalSize16( icon16 ) >= sizeof(*ptr) + sizeof(ULONG_PTR) + and_size + xor_size ) { memcpy( &ret, (char *)(ptr + 1) + and_size + xor_size, sizeof(ret) ); memcpy( (char *)(ptr + 1) + and_size + xor_size, &icon, sizeof(icon) ); wow_handlers32.set_icon_param( icon, icon16 ); } release_icon_ptr( icon16, ptr ); } return ret; } static int free_icon_handle( HICON16 handle ) { HICON icon32; if ((icon32 = store_icon_32( handle, 0 ))) DestroyIcon( icon32 ); return GlobalFree16( handle ); } /* retrieve the 32-bit counterpart of a 16-bit icon, creating it if needed */ HICON get_icon_32( HICON16 icon16 ) { HICON ret = 0; CURSORICONINFO *ptr = get_icon_ptr( icon16 ); if (ptr) { unsigned int and_size = ptr->nHeight * get_bitmap_width_bytes( ptr->nWidth, 1 ); unsigned int xor_size = ptr->nHeight * get_bitmap_width_bytes( ptr->nWidth, ptr->bBitsPerPixel ); if (GlobalSize16( icon16 ) >= sizeof(*ptr) + sizeof(ULONG_PTR) + xor_size + and_size ) { memcpy( &ret, (char *)(ptr + 1) + xor_size + and_size, sizeof(ret) ); if (!ret) { ICONINFO iinfo; iinfo.fIcon = (ptr->ptHotSpot.x == ICON_HOTSPOT) && (ptr->ptHotSpot.y == ICON_HOTSPOT); iinfo.xHotspot = ptr->ptHotSpot.x; iinfo.yHotspot = ptr->ptHotSpot.y; iinfo.hbmMask = CreateBitmap( ptr->nWidth, ptr->nHeight, 1, 1, ptr + 1 ); iinfo.hbmColor = CreateBitmap( ptr->nWidth, ptr->nHeight, ptr->bPlanes, ptr->bBitsPerPixel, (char *)(ptr + 1) + and_size ); ret = CreateIconIndirect( &iinfo ); DeleteObject( iinfo.hbmMask ); DeleteObject( iinfo.hbmColor ); memcpy( (char *)(ptr + 1) + xor_size + and_size, &ret, sizeof(ret) ); wow_handlers32.set_icon_param( ret, icon16 ); } } release_icon_ptr( icon16, ptr ); } return ret; } /* retrieve the 16-bit counterpart of a 32-bit icon, creating it if needed */ HICON16 get_icon_16( HICON icon ) { HICON16 ret = wow_handlers32.get_icon_param( icon ); if (!ret) { ICONINFO info; BITMAP bm; UINT and_size, xor_size; void *xor_bits = NULL, *and_bits; CURSORICONINFO cinfo; if (!(GetIconInfo( icon, &info ))) return 0; GetObjectW( info.hbmMask, sizeof(bm), &bm ); and_size = bm.bmHeight * bm.bmWidthBytes; if (!(and_bits = HeapAlloc( GetProcessHeap(), 0, and_size ))) goto done; GetBitmapBits( info.hbmMask, and_size, and_bits ); if (info.hbmColor) { GetObjectW( info.hbmColor, sizeof(bm), &bm ); xor_size = bm.bmHeight * bm.bmWidthBytes; if (!(xor_bits = HeapAlloc( GetProcessHeap(), 0, xor_size ))) goto done; GetBitmapBits( info.hbmColor, xor_size, xor_bits ); } else { bm.bmHeight /= 2; xor_bits = (char *)and_bits + and_size / 2; } if (!info.fIcon) { cinfo.ptHotSpot.x = info.xHotspot; cinfo.ptHotSpot.y = info.yHotspot; } else cinfo.ptHotSpot.x = cinfo.ptHotSpot.y = ICON_HOTSPOT; cinfo.nWidth = bm.bmWidth; cinfo.nHeight = bm.bmHeight; cinfo.nWidthBytes = bm.bmWidthBytes; cinfo.bPlanes = bm.bmPlanes; cinfo.bBitsPerPixel = bm.bmBitsPixel; if ((ret = CreateCursorIconIndirect16( 0, &cinfo, and_bits, xor_bits ))) store_icon_32( ret, icon ); done: if (info.hbmColor) { HeapFree( GetProcessHeap(), 0, xor_bits ); DeleteObject( info.hbmColor ); } HeapFree( GetProcessHeap(), 0, and_bits ); DeleteObject( info.hbmMask ); } return ret; } static void add_shared_icon( HINSTANCE16 inst, HRSRC16 rsrc, HRSRC16 group, HICON16 icon ) { struct cache_entry *cache = HeapAlloc( GetProcessHeap(), 0, sizeof(*cache) ); if (!cache) return; cache->inst = inst; cache->rsrc = rsrc; cache->group = group; cache->icon = icon; cache->count = 1; list_add_tail( &icon_cache, &cache->entry ); } static HICON16 find_shared_icon( HINSTANCE16 inst, HRSRC16 rsrc ) { struct cache_entry *cache; LIST_FOR_EACH_ENTRY( cache, &icon_cache, struct cache_entry, entry ) { if (cache->inst != inst || cache->rsrc != rsrc) continue; cache->count++; return cache->icon; } return 0; } static int release_shared_icon( HICON16 icon ) { struct cache_entry *cache; LIST_FOR_EACH_ENTRY( cache, &icon_cache, struct cache_entry, entry ) { if (cache->icon != icon) continue; if (!cache->count) return 0; return --cache->count; } return -1; } static void free_module_icons( HINSTANCE16 inst ) { struct cache_entry *cache, *next; LIST_FOR_EACH_ENTRY_SAFE( cache, next, &icon_cache, struct cache_entry, entry ) { if (cache->inst != inst) continue; list_remove( &cache->entry ); free_icon_handle( cache->icon ); HeapFree( GetProcessHeap(), 0, cache ); } } /********************************************************************** * Management of the 16-bit clipboard formats */ struct clipboard_format { struct list entry; UINT format; HANDLE16 data; }; static struct list clipboard_formats = LIST_INIT( clipboard_formats ); static void set_clipboard_format( UINT format, HANDLE16 data ) { struct clipboard_format *fmt; /* replace it if it exists already */ LIST_FOR_EACH_ENTRY( fmt, &clipboard_formats, struct clipboard_format, entry ) { if (fmt->format != format) continue; GlobalFree16( fmt->data ); fmt->data = data; return; } if ((fmt = HeapAlloc( GetProcessHeap(), 0, sizeof(*fmt) ))) { fmt->format = format; fmt->data = data; list_add_tail( &clipboard_formats, &fmt->entry ); } } static void free_clipboard_formats(void) { struct list *head; while ((head = list_head( &clipboard_formats ))) { struct clipboard_format *fmt = LIST_ENTRY( head, struct clipboard_format, entry ); list_remove( &fmt->entry ); GlobalFree16( fmt->data ); HeapFree( GetProcessHeap(), 0, fmt ); } } /********************************************************************** * InitApp (USER.5) */ INT16 WINAPI InitApp16( HINSTANCE16 hInstance ) { /* Create task message queue */ return (InitThreadInput16( 0, 0 ) != 0); } /*********************************************************************** * ExitWindows (USER.7) */ BOOL16 WINAPI ExitWindows16( DWORD dwReturnCode, UINT16 wReserved ) { return ExitWindowsEx( EWX_LOGOFF, 0xffffffff ); } /*********************************************************************** * GetTimerResolution (USER.14) */ LONG WINAPI GetTimerResolution16(void) { return (1000); } /*********************************************************************** * ClipCursor (USER.16) */ BOOL16 WINAPI ClipCursor16( const RECT16 *rect ) { RECT rect32; if (!rect) return ClipCursor( NULL ); rect32.left = rect->left; rect32.top = rect->top; rect32.right = rect->right; rect32.bottom = rect->bottom; return ClipCursor( &rect32 ); } /*********************************************************************** * GetCursorPos (USER.17) */ BOOL16 WINAPI GetCursorPos16( POINT16 *pt ) { POINT pos; if (!pt) return FALSE; GetCursorPos(&pos); pt->x = pos.x; pt->y = pos.y; return TRUE; } /******************************************************************* * AnyPopup (USER.52) */ BOOL16 WINAPI AnyPopup16(void) { return AnyPopup(); } /*********************************************************************** * SetCursor (USER.69) */ HCURSOR16 WINAPI SetCursor16(HCURSOR16 hCursor) { return get_icon_16( SetCursor( get_icon_32(hCursor) )); } /*********************************************************************** * SetCursorPos (USER.70) */ void WINAPI SetCursorPos16( INT16 x, INT16 y ) { SetCursorPos( x, y ); } /*********************************************************************** * ShowCursor (USER.71) */ INT16 WINAPI ShowCursor16(BOOL16 bShow) { return ShowCursor(bShow); } /*********************************************************************** * SetRect (USER.72) */ void WINAPI SetRect16( LPRECT16 rect, INT16 left, INT16 top, INT16 right, INT16 bottom ) { rect->left = left; rect->right = right; rect->top = top; rect->bottom = bottom; } /*********************************************************************** * SetRectEmpty (USER.73) */ void WINAPI SetRectEmpty16( LPRECT16 rect ) { rect->left = rect->right = rect->top = rect->bottom = 0; } /*********************************************************************** * CopyRect (USER.74) */ BOOL16 WINAPI CopyRect16( RECT16 *dest, const RECT16 *src ) { *dest = *src; return TRUE; } /*********************************************************************** * IsRectEmpty (USER.75) * * Bug compat: Windows checks for 0 or negative width/height. */ BOOL16 WINAPI IsRectEmpty16( const RECT16 *rect ) { return ((rect->left >= rect->right) || (rect->top >= rect->bottom)); } /*********************************************************************** * PtInRect (USER.76) */ BOOL16 WINAPI PtInRect16( const RECT16 *rect, POINT16 pt ) { return ((pt.x >= rect->left) && (pt.x < rect->right) && (pt.y >= rect->top) && (pt.y < rect->bottom)); } /*********************************************************************** * OffsetRect (USER.77) */ void WINAPI OffsetRect16( LPRECT16 rect, INT16 x, INT16 y ) { rect->left += x; rect->right += x; rect->top += y; rect->bottom += y; } /*********************************************************************** * InflateRect (USER.78) */ void WINAPI InflateRect16( LPRECT16 rect, INT16 x, INT16 y ) { rect->left -= x; rect->top -= y; rect->right += x; rect->bottom += y; } /*********************************************************************** * IntersectRect (USER.79) */ BOOL16 WINAPI IntersectRect16( LPRECT16 dest, const RECT16 *src1, const RECT16 *src2 ) { if (IsRectEmpty16(src1) || IsRectEmpty16(src2) || (src1->left >= src2->right) || (src2->left >= src1->right) || (src1->top >= src2->bottom) || (src2->top >= src1->bottom)) { SetRectEmpty16( dest ); return FALSE; } dest->left = max( src1->left, src2->left ); dest->right = min( src1->right, src2->right ); dest->top = max( src1->top, src2->top ); dest->bottom = min( src1->bottom, src2->bottom ); return TRUE; } /*********************************************************************** * UnionRect (USER.80) */ BOOL16 WINAPI UnionRect16( LPRECT16 dest, const RECT16 *src1, const RECT16 *src2 ) { if (IsRectEmpty16(src1)) { if (IsRectEmpty16(src2)) { SetRectEmpty16( dest ); return FALSE; } else *dest = *src2; } else { if (IsRectEmpty16(src2)) *dest = *src1; else { dest->left = min( src1->left, src2->left ); dest->right = max( src1->right, src2->right ); dest->top = min( src1->top, src2->top ); dest->bottom = max( src1->bottom, src2->bottom ); } } return TRUE; } /*********************************************************************** * FillRect (USER.81) * NOTE * The Win16 variant doesn't support special color brushes like * the Win32 one, despite the fact that Win16, as well as Win32, * supports special background brushes for a window class. */ INT16 WINAPI FillRect16( HDC16 hdc, const RECT16 *rect, HBRUSH16 hbrush ) { HBRUSH prevBrush; /* coordinates are logical so we cannot fast-check 'rect', * it will be done later in the PatBlt(). */ if (!(prevBrush = SelectObject( HDC_32(hdc), HBRUSH_32(hbrush) ))) return 0; PatBlt( HDC_32(hdc), rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top, PATCOPY ); SelectObject( HDC_32(hdc), prevBrush ); return 1; } /*********************************************************************** * InvertRect (USER.82) */ void WINAPI InvertRect16( HDC16 hdc, const RECT16 *rect ) { PatBlt( HDC_32(hdc), rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top, DSTINVERT ); } /*********************************************************************** * FrameRect (USER.83) */ INT16 WINAPI FrameRect16( HDC16 hdc, const RECT16 *rect16, HBRUSH16 hbrush ) { RECT rect; rect.left = rect16->left; rect.top = rect16->top; rect.right = rect16->right; rect.bottom = rect16->bottom; return FrameRect( HDC_32(hdc), &rect, HBRUSH_32(hbrush) ); } /*********************************************************************** * DrawIcon (USER.84) */ BOOL16 WINAPI DrawIcon16(HDC16 hdc, INT16 x, INT16 y, HICON16 hIcon) { return DrawIcon(HDC_32(hdc), x, y, get_icon_32(hIcon) ); } /*********************************************************************** * DrawText (USER.85) */ INT16 WINAPI DrawText16( HDC16 hdc, LPCSTR str, INT16 count, LPRECT16 rect, UINT16 flags ) { INT16 ret; if (rect) { RECT rect32; rect32.left = rect->left; rect32.top = rect->top; rect32.right = rect->right; rect32.bottom = rect->bottom; ret = DrawTextA( HDC_32(hdc), str, count, &rect32, flags ); rect->left = rect32.left; rect->top = rect32.top; rect->right = rect32.right; rect->bottom = rect32.bottom; } else ret = DrawTextA( HDC_32(hdc), str, count, NULL, flags); return ret; } /*********************************************************************** * IconSize (USER.86) * * See "Undocumented Windows". Used by W2.0 paint.exe. */ DWORD WINAPI IconSize16(void) { return MAKELONG(GetSystemMetrics(SM_CYICON), GetSystemMetrics(SM_CXICON)); } /*********************************************************************** * AdjustWindowRect (USER.102) */ BOOL16 WINAPI AdjustWindowRect16( LPRECT16 rect, DWORD style, BOOL16 menu ) { return AdjustWindowRectEx16( rect, style, menu, 0 ); } /*********************************************************************** * MessageBeep (USER.104) */ void WINAPI MessageBeep16( UINT16 i ) { MessageBeep( i ); } /************************************************************************** * CloseClipboard (USER.138) */ BOOL16 WINAPI CloseClipboard16(void) { BOOL ret = CloseClipboard(); if (ret) free_clipboard_formats(); return ret; } /************************************************************************** * EmptyClipboard (USER.139) */ BOOL16 WINAPI EmptyClipboard16(void) { BOOL ret = EmptyClipboard(); if (ret) free_clipboard_formats(); return ret; } /************************************************************************** * SetClipboardData (USER.141) */ HANDLE16 WINAPI SetClipboardData16( UINT16 format, HANDLE16 data16 ) { HANDLE data32 = 0; switch (format) { case CF_BITMAP: case CF_PALETTE: data32 = HGDIOBJ_32( data16 ); break; case CF_METAFILEPICT: { METAHEADER *header; METAFILEPICT *pict32; METAFILEPICT16 *pict16 = GlobalLock16( data16 ); if (pict16) { if (!(data32 = GlobalAlloc( GMEM_MOVEABLE, sizeof(*pict32) ))) return 0; pict32 = GlobalLock( data32 ); pict32->mm = pict16->mm; pict32->xExt = pict16->xExt; pict32->yExt = pict16->yExt; header = GlobalLock16( pict16->hMF ); pict32->hMF = SetMetaFileBitsEx( header->mtSize * 2, (BYTE *)header ); GlobalUnlock16( pict16->hMF ); GlobalUnlock( data32 ); } set_clipboard_format( format, data16 ); break; } case CF_ENHMETAFILE: FIXME( "enhmetafile not supported in 16-bit\n" ); return 0; default: if (format >= CF_GDIOBJFIRST && format <= CF_GDIOBJLAST) data32 = HGDIOBJ_32( data16 ); else if (format >= CF_PRIVATEFIRST && format <= CF_PRIVATELAST) data32 = HANDLE_32( data16 ); else { UINT size = GlobalSize16( data16 ); void *ptr32, *ptr16 = GlobalLock16( data16 ); if (ptr16) { if (!(data32 = GlobalAlloc( GMEM_MOVEABLE, size ))) return 0; ptr32 = GlobalLock( data32 ); memcpy( ptr32, ptr16, size ); GlobalUnlock( data32 ); } set_clipboard_format( format, data16 ); } break; } if (!SetClipboardData( format, data32 )) return 0; return data16; } /************************************************************************** * GetClipboardData (USER.142) */ HANDLE16 WINAPI GetClipboardData16( UINT16 format ) { HANDLE data32 = GetClipboardData( format ); HANDLE16 data16 = 0; UINT size; void *ptr; if (!data32) return 0; switch (format) { case CF_BITMAP: case CF_PALETTE: data16 = HGDIOBJ_16( data32 ); break; case CF_METAFILEPICT: { METAFILEPICT16 *pict16; METAFILEPICT *pict32 = GlobalLock( data32 ); if (pict32) { if (!(data16 = GlobalAlloc16( GMEM_MOVEABLE, sizeof(*pict16) ))) return 0; pict16 = GlobalLock16( data16 ); pict16->mm = pict32->mm; pict16->xExt = pict32->xExt; pict16->yExt = pict32->yExt; size = GetMetaFileBitsEx( pict32->hMF, 0, NULL ); pict16->hMF = GlobalAlloc16( GMEM_MOVEABLE, size ); ptr = GlobalLock16( pict16->hMF ); GetMetaFileBitsEx( pict32->hMF, size, ptr ); GlobalUnlock16( pict16->hMF ); GlobalUnlock16( data16 ); set_clipboard_format( format, data16 ); } break; } case CF_ENHMETAFILE: FIXME( "enhmetafile not supported in 16-bit\n" ); return 0; default: if (format >= CF_GDIOBJFIRST && format <= CF_GDIOBJLAST) data16 = HGDIOBJ_16( data32 ); else if (format >= CF_PRIVATEFIRST && format <= CF_PRIVATELAST) data16 = HANDLE_16( data32 ); else { void *ptr16, *ptr32 = GlobalLock( data32 ); if (ptr32) { size = GlobalSize( data32 ); if (!(data16 = GlobalAlloc16( GMEM_MOVEABLE, size ))) return 0; ptr16 = GlobalLock16( data16 ); memcpy( ptr16, ptr32, size ); GlobalUnlock16( data16 ); set_clipboard_format( format, data16 ); } } break; } return data16; } /************************************************************************** * CountClipboardFormats (USER.143) */ INT16 WINAPI CountClipboardFormats16(void) { return CountClipboardFormats(); } /************************************************************************** * EnumClipboardFormats (USER.144) */ UINT16 WINAPI EnumClipboardFormats16( UINT16 id ) { return EnumClipboardFormats( id ); } /************************************************************************** * RegisterClipboardFormat (USER.145) */ UINT16 WINAPI RegisterClipboardFormat16( LPCSTR name ) { return RegisterClipboardFormatA( name ); } /************************************************************************** * GetClipboardFormatName (USER.146) */ INT16 WINAPI GetClipboardFormatName16( UINT16 id, LPSTR buffer, INT16 maxlen ) { return GetClipboardFormatNameA( id, buffer, maxlen ); } /********************************************************************** * LoadMenu (USER.150) */ HMENU16 WINAPI LoadMenu16( HINSTANCE16 instance, LPCSTR name ) { HRSRC16 hRsrc; HGLOBAL16 handle; HMENU16 hMenu; if (HIWORD(name) && name[0] == '#') name = ULongToPtr(atoi( name + 1 )); if (!name) return 0; instance = GetExePtr( instance ); if (!(hRsrc = FindResource16( instance, name, (LPSTR)RT_MENU ))) return 0; if (!(handle = LoadResource16( instance, hRsrc ))) return 0; hMenu = LoadMenuIndirect16(LockResource16(handle)); FreeResource16( handle ); return hMenu; } /********************************************************************** * CreateMenu (USER.151) */ HMENU16 WINAPI CreateMenu16(void) { return HMENU_16( CreateMenu() ); } /********************************************************************** * DestroyMenu (USER.152) */ BOOL16 WINAPI DestroyMenu16( HMENU16 hMenu ) { return DestroyMenu( HMENU_32(hMenu) ); } /******************************************************************* * ChangeMenu (USER.153) */ BOOL16 WINAPI ChangeMenu16( HMENU16 hMenu, UINT16 pos, SEGPTR data, UINT16 id, UINT16 flags ) { if (flags & MF_APPEND) return AppendMenu16( hMenu, flags & ~MF_APPEND, id, data ); /* FIXME: Word passes the item id in 'pos' and 0 or 0xffff as id */ /* for MF_DELETE. We should check the parameters for all others */ /* MF_* actions also (anybody got a doc on ChangeMenu?). */ if (flags & MF_DELETE) return DeleteMenu16(hMenu, pos, flags & ~MF_DELETE); if (flags & MF_CHANGE) return ModifyMenu16(hMenu, pos, flags & ~MF_CHANGE, id, data ); if (flags & MF_REMOVE) return RemoveMenu16(hMenu, flags & MF_BYPOSITION ? pos : id, flags & ~MF_REMOVE ); /* Default: MF_INSERT */ return InsertMenu16( hMenu, pos, flags, id, data ); } /******************************************************************* * CheckMenuItem (USER.154) */ BOOL16 WINAPI CheckMenuItem16( HMENU16 hMenu, UINT16 id, UINT16 flags ) { return CheckMenuItem( HMENU_32(hMenu), id, flags ); } /********************************************************************** * EnableMenuItem (USER.155) */ BOOL16 WINAPI EnableMenuItem16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags ) { return EnableMenuItem( HMENU_32(hMenu), wItemID, wFlags ); } /********************************************************************** * GetSubMenu (USER.159) */ HMENU16 WINAPI GetSubMenu16( HMENU16 hMenu, INT16 nPos ) { return HMENU_16( GetSubMenu( HMENU_32(hMenu), nPos ) ); } /******************************************************************* * GetMenuString (USER.161) */ INT16 WINAPI GetMenuString16( HMENU16 hMenu, UINT16 wItemID, LPSTR str, INT16 nMaxSiz, UINT16 wFlags ) { return GetMenuStringA( HMENU_32(hMenu), wItemID, str, nMaxSiz, wFlags ); } /********************************************************************** * WinHelp (USER.171) */ BOOL16 WINAPI WinHelp16( HWND16 hWnd, LPCSTR lpHelpFile, UINT16 wCommand, DWORD dwData ) { BOOL ret; DWORD mutex_count; /* We might call WinExec() */ ReleaseThunkLock(&mutex_count); ret = WinHelpA(WIN_Handle32(hWnd), lpHelpFile, wCommand, (DWORD)MapSL(dwData)); RestoreThunkLock(mutex_count); return ret; } /*********************************************************************** * LoadCursor (USER.173) */ HCURSOR16 WINAPI LoadCursor16(HINSTANCE16 hInstance, LPCSTR name) { return LoadImage16( hInstance, name, IMAGE_CURSOR, 0, 0, LR_SHARED | LR_DEFAULTSIZE ); } /*********************************************************************** * LoadIcon (USER.174) */ HICON16 WINAPI LoadIcon16(HINSTANCE16 hInstance, LPCSTR name) { return LoadImage16( hInstance, name, IMAGE_ICON, 0, 0, LR_SHARED | LR_DEFAULTSIZE ); } /********************************************************************** * LoadBitmap (USER.175) */ HBITMAP16 WINAPI LoadBitmap16(HINSTANCE16 hInstance, LPCSTR name) { return LoadImage16( hInstance, name, IMAGE_BITMAP, 0, 0, 0 ); } /********************************************************************** * LoadString (USER.176) */ INT16 WINAPI LoadString16( HINSTANCE16 instance, UINT16 resource_id, LPSTR buffer, INT16 buflen ) { HGLOBAL16 hmem; HRSRC16 hrsrc; unsigned char *p; int string_num; int ret; TRACE("inst=%04x id=%04x buff=%p len=%d\n", instance, resource_id, buffer, buflen); hrsrc = FindResource16( instance, MAKEINTRESOURCEA((resource_id>>4)+1), (LPSTR)RT_STRING ); if (!hrsrc) return 0; hmem = LoadResource16( instance, hrsrc ); if (!hmem) return 0; p = LockResource16(hmem); string_num = resource_id & 0x000f; while (string_num--) p += *p + 1; if (buffer == NULL) ret = *p; else { ret = min(buflen - 1, *p); if (ret > 0) { memcpy(buffer, p + 1, ret); buffer[ret] = '\0'; } else if (buflen > 1) { buffer[0] = '\0'; ret = 0; } TRACE( "%s loaded\n", debugstr_a(buffer)); } FreeResource16( hmem ); return ret; } /********************************************************************** * LoadAccelerators (USER.177) */ HACCEL16 WINAPI LoadAccelerators16(HINSTANCE16 instance, LPCSTR lpTableName) { HRSRC16 hRsrc; HGLOBAL16 hMem; ACCEL16 *table16; HACCEL ret = 0; TRACE("%04x %s\n", instance, debugstr_a(lpTableName) ); if (!(hRsrc = FindResource16( instance, lpTableName, (LPSTR)RT_ACCELERATOR )) || !(hMem = LoadResource16(instance,hRsrc))) { WARN("couldn't find %04x %s\n", instance, debugstr_a(lpTableName)); return 0; } if ((table16 = LockResource16( hMem ))) { DWORD i, count = SizeofResource16( instance, hRsrc ) / sizeof(*table16); ACCEL *table = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*table) ); if (table) { for (i = 0; i < count; i++) { table[i].fVirt = table16[i].fVirt & 0x7f; table[i].key = table16[i].key; table[i].cmd = table16[i].cmd; } ret = CreateAcceleratorTableA( table, count ); HeapFree( GetProcessHeap(), 0, table ); } } FreeResource16( hMem ); return HACCEL_16(ret); } /*********************************************************************** * GetSystemMetrics (USER.179) */ INT16 WINAPI GetSystemMetrics16( INT16 index ) { return GetSystemMetrics( index ); } /************************************************************************* * GetSysColor (USER.180) */ COLORREF WINAPI GetSysColor16( INT16 index ) { return GetSysColor( index ); } /************************************************************************* * SetSysColors (USER.181) */ VOID WINAPI SetSysColors16( INT16 count, const INT16 *list16, const COLORREF *values ) { INT i, *list; if ((list = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*list) ))) { for (i = 0; i < count; i++) list[i] = list16[i]; SetSysColors( count, list, values ); HeapFree( GetProcessHeap(), 0, list ); } } /*********************************************************************** * GrayString (USER.185) */ BOOL16 WINAPI GrayString16( HDC16 hdc, HBRUSH16 hbr, GRAYSTRINGPROC16 gsprc, LPARAM lParam, INT16 cch, INT16 x, INT16 y, INT16 cx, INT16 cy ) { BOOL ret; if (!gsprc) return GrayStringA( HDC_32(hdc), HBRUSH_32(hbr), NULL, (LPARAM)MapSL(lParam), cch, x, y, cx, cy ); if (cch == -1 || (cch && cx && cy)) { /* lParam can be treated as an opaque pointer */ struct gray_string_info info; info.proc = gsprc; info.param = lParam; ret = GrayStringA( HDC_32(hdc), HBRUSH_32(hbr), gray_string_callback, (LPARAM)&info, cch, x, y, cx, cy ); } else /* here we need some string conversions */ { char *str16 = MapSL(lParam); struct gray_string_info *info; if (!cch) cch = strlen(str16); info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( struct gray_string_info, str[cch] )); if (!info) return FALSE; info->proc = gsprc; info->param = lParam; memcpy( info->str, str16, cch ); ret = GrayStringA( HDC_32(hdc), HBRUSH_32(hbr), gray_string_callback_ptr, (LPARAM)info->str, cch, x, y, cx, cy ); HeapFree( GetProcessHeap(), 0, info ); } return ret; } /*********************************************************************** * SwapMouseButton (USER.186) */ BOOL16 WINAPI SwapMouseButton16( BOOL16 fSwap ) { return SwapMouseButton( fSwap ); } /************************************************************************** * IsClipboardFormatAvailable (USER.193) */ BOOL16 WINAPI IsClipboardFormatAvailable16( UINT16 wFormat ) { return IsClipboardFormatAvailable( wFormat ); } /*********************************************************************** * TabbedTextOut (USER.196) */ LONG WINAPI TabbedTextOut16( HDC16 hdc, INT16 x, INT16 y, LPCSTR lpstr, INT16 count, INT16 nb_tabs, const INT16 *tabs16, INT16 tab_org ) { LONG ret; INT i, *tabs = HeapAlloc( GetProcessHeap(), 0, nb_tabs * sizeof(*tabs) ); if (!tabs) return 0; for (i = 0; i < nb_tabs; i++) tabs[i] = tabs16[i]; ret = TabbedTextOutA( HDC_32(hdc), x, y, lpstr, count, nb_tabs, tabs, tab_org ); HeapFree( GetProcessHeap(), 0, tabs ); return ret; } /*********************************************************************** * GetTabbedTextExtent (USER.197) */ DWORD WINAPI GetTabbedTextExtent16( HDC16 hdc, LPCSTR lpstr, INT16 count, INT16 nb_tabs, const INT16 *tabs16 ) { LONG ret; INT i, *tabs = HeapAlloc( GetProcessHeap(), 0, nb_tabs * sizeof(*tabs) ); if (!tabs) return 0; for (i = 0; i < nb_tabs; i++) tabs[i] = tabs16[i]; ret = GetTabbedTextExtentA( HDC_32(hdc), lpstr, count, nb_tabs, tabs ); HeapFree( GetProcessHeap(), 0, tabs ); return ret; } /*********************************************************************** * UserSeeUserDo (USER.216) */ DWORD WINAPI UserSeeUserDo16(WORD wReqType, WORD wParam1, WORD wParam2, WORD wParam3) { STACK16FRAME* stack16 = MapSL((SEGPTR)NtCurrentTeb()->WOW32Reserved); HANDLE16 oldDS = stack16->ds; DWORD ret = (DWORD)-1; stack16->ds = USER_HeapSel; switch (wReqType) { case USUD_LOCALALLOC: ret = LocalAlloc16(wParam1, wParam3); break; case USUD_LOCALFREE: ret = LocalFree16(wParam1); break; case USUD_LOCALCOMPACT: ret = LocalCompact16(wParam3); break; case USUD_LOCALHEAP: ret = USER_HeapSel; break; case USUD_FIRSTCLASS: FIXME("return a pointer to the first window class.\n"); break; default: WARN("wReqType %04x (unknown)\n", wReqType); } stack16->ds = oldDS; return ret; } /*********************************************************************** * LookupMenuHandle (USER.217) */ HMENU16 WINAPI LookupMenuHandle16( HMENU16 hmenu, INT16 id ) { FIXME( "%04x %04x: stub\n", hmenu, id ); return hmenu; } static LPCSTR parse_menu_resource( LPCSTR res, HMENU hMenu, BOOL oldFormat ) { WORD flags, id = 0; LPCSTR str; BOOL end_flag; do { /* Windows 3.00 and later use a WORD for the flags, whereas 1.x and 2.x use a BYTE. */ if (oldFormat) { flags = GET_BYTE(res); res += sizeof(BYTE); } else { flags = GET_WORD(res); res += sizeof(WORD); } end_flag = flags & MF_END; /* Remove MF_END because it has the same value as MF_HILITE */ flags &= ~MF_END; if (!(flags & MF_POPUP)) { id = GET_WORD(res); res += sizeof(WORD); } str = res; res += strlen(str) + 1; if (flags & MF_POPUP) { HMENU hSubMenu = CreatePopupMenu(); if (!hSubMenu) return NULL; if (!(res = parse_menu_resource( res, hSubMenu, oldFormat ))) return NULL; AppendMenuA( hMenu, flags, (UINT_PTR)hSubMenu, str ); } else /* Not a popup */ { AppendMenuA( hMenu, flags, id, *str ? str : NULL ); } } while (!end_flag); return res; } /********************************************************************** * LoadMenuIndirect (USER.220) */ HMENU16 WINAPI LoadMenuIndirect16( LPCVOID template ) { BOOL oldFormat; HMENU hMenu; WORD version, offset; LPCSTR p = template; TRACE("(%p)\n", template ); /* Windows 1.x and 2.x menus have a slightly different menu format from 3.x menus */ oldFormat = (GetExeVersion16() < 0x0300); /* Windows 3.00 and later menu items are preceded by a MENUITEMTEMPLATEHEADER structure */ if (!oldFormat) { version = GET_WORD(p); p += sizeof(WORD); if (version) { WARN("version must be 0 for Win16 >= 3.00 applications\n" ); return 0; } offset = GET_WORD(p); p += sizeof(WORD) + offset; } if (!(hMenu = CreateMenu())) return 0; if (!parse_menu_resource( p, hMenu, oldFormat )) { DestroyMenu( hMenu ); return 0; } return HMENU_16(hMenu); } /************************************************************************* * ScrollDC (USER.221) */ BOOL16 WINAPI ScrollDC16( HDC16 hdc, INT16 dx, INT16 dy, const RECT16 *rect, const RECT16 *cliprc, HRGN16 hrgnUpdate, LPRECT16 rcUpdate ) { RECT rect32, clipRect32, rcUpdate32; BOOL16 ret; if (rect) { rect32.left = rect->left; rect32.top = rect->top; rect32.right = rect->right; rect32.bottom = rect->bottom; } if (cliprc) { clipRect32.left = cliprc->left; clipRect32.top = cliprc->top; clipRect32.right = cliprc->right; clipRect32.bottom = cliprc->bottom; } ret = ScrollDC( HDC_32(hdc), dx, dy, rect ? &rect32 : NULL, cliprc ? &clipRect32 : NULL, HRGN_32(hrgnUpdate), &rcUpdate32 ); if (rcUpdate) { rcUpdate->left = rcUpdate32.left; rcUpdate->top = rcUpdate32.top; rcUpdate->right = rcUpdate32.right; rcUpdate->bottom = rcUpdate32.bottom; } return ret; } /*********************************************************************** * GetSystemDebugState (USER.231) */ WORD WINAPI GetSystemDebugState16(void) { return 0; /* FIXME */ } /*********************************************************************** * EqualRect (USER.244) */ BOOL16 WINAPI EqualRect16( const RECT16* rect1, const RECT16* rect2 ) { return ((rect1->left == rect2->left) && (rect1->right == rect2->right) && (rect1->top == rect2->top) && (rect1->bottom == rect2->bottom)); } /*********************************************************************** * ExitWindowsExec (USER.246) */ BOOL16 WINAPI ExitWindowsExec16( LPCSTR lpszExe, LPCSTR lpszParams ) { TRACE("Should run the following in DOS-mode: \"%s %s\"\n", lpszExe, lpszParams); return ExitWindowsEx( EWX_LOGOFF, 0xffffffff ); } /*********************************************************************** * GetCursor (USER.247) */ HCURSOR16 WINAPI GetCursor16(void) { return get_icon_16( GetCursor() ); } /********************************************************************** * GetAsyncKeyState (USER.249) */ INT16 WINAPI GetAsyncKeyState16( INT16 key ) { return GetAsyncKeyState( key ); } /********************************************************************** * GetMenuState (USER.250) */ UINT16 WINAPI GetMenuState16( HMENU16 hMenu, UINT16 wItemID, UINT16 wFlags ) { return GetMenuState( HMENU_32(hMenu), wItemID, wFlags ); } /************************************************************************** * SendDriverMessage (USER.251) */ LRESULT WINAPI SendDriverMessage16(HDRVR16 hDriver, UINT16 msg, LPARAM lParam1, LPARAM lParam2) { FIXME("(%04x, %04x, %08lx, %08lx): stub\n", hDriver, msg, lParam1, lParam2); return 0; } /************************************************************************** * OpenDriver (USER.252) */ HDRVR16 WINAPI OpenDriver16(LPCSTR lpDriverName, LPCSTR lpSectionName, LPARAM lParam2) { FIXME( "(%s, %s, %08lx): stub\n", debugstr_a(lpDriverName), debugstr_a(lpSectionName), lParam2); return 0; } /************************************************************************** * CloseDriver (USER.253) */ LRESULT WINAPI CloseDriver16(HDRVR16 hDrvr, LPARAM lParam1, LPARAM lParam2) { FIXME( "(%04x, %08lx, %08lx): stub\n", hDrvr, lParam1, lParam2); return FALSE; } /************************************************************************** * GetDriverModuleHandle (USER.254) */ HMODULE16 WINAPI GetDriverModuleHandle16(HDRVR16 hDrvr) { FIXME("(%04x): stub\n", hDrvr); return 0; } /************************************************************************** * DefDriverProc (USER.255) */ LRESULT WINAPI DefDriverProc16(DWORD dwDevID, HDRVR16 hDriv, UINT16 wMsg, LPARAM lParam1, LPARAM lParam2) { FIXME( "devID=0x%08x hDrv=0x%04x wMsg=%04x lP1=0x%08lx lP2=0x%08lx: stub\n", dwDevID, hDriv, wMsg, lParam1, lParam2); return 0; } /************************************************************************** * GetDriverInfo (USER.256) */ struct DRIVERINFOSTRUCT16; BOOL16 WINAPI GetDriverInfo16(HDRVR16 hDrvr, struct DRIVERINFOSTRUCT16 *lpDrvInfo) { FIXME( "(%04x, %p): stub\n", hDrvr, lpDrvInfo); return FALSE; } /************************************************************************** * GetNextDriver (USER.257) */ HDRVR16 WINAPI GetNextDriver16(HDRVR16 hDrvr, DWORD dwFlags) { FIXME( "(%04x, %08x): stub\n", hDrvr, dwFlags); return 0; } /********************************************************************** * GetMenuItemCount (USER.263) */ INT16 WINAPI GetMenuItemCount16( HMENU16 hMenu ) { return GetMenuItemCount( HMENU_32(hMenu) ); } /********************************************************************** * GetMenuItemID (USER.264) */ UINT16 WINAPI GetMenuItemID16( HMENU16 hMenu, INT16 nPos ) { return GetMenuItemID( HMENU_32(hMenu), nPos ); } /*********************************************************************** * GlobalAddAtom (USER.268) */ ATOM WINAPI GlobalAddAtom16(LPCSTR lpString) { return GlobalAddAtomA(lpString); } /*********************************************************************** * GlobalDeleteAtom (USER.269) */ ATOM WINAPI GlobalDeleteAtom16(ATOM nAtom) { return GlobalDeleteAtom(nAtom); } /*********************************************************************** * GlobalFindAtom (USER.270) */ ATOM WINAPI GlobalFindAtom16(LPCSTR lpString) { return GlobalFindAtomA(lpString); } /*********************************************************************** * GlobalGetAtomName (USER.271) */ UINT16 WINAPI GlobalGetAtomName16(ATOM nAtom, LPSTR lpBuffer, INT16 nSize) { return GlobalGetAtomNameA(nAtom, lpBuffer, nSize); } /*********************************************************************** * ControlPanelInfo (USER.273) */ void WINAPI ControlPanelInfo16( INT16 nInfoType, WORD wData, LPSTR lpBuffer ) { FIXME("(%d, %04x, %p): stub.\n", nInfoType, wData, lpBuffer); } /*********************************************************************** * OldSetDeskPattern (USER.279) */ BOOL16 WINAPI SetDeskPattern16(void) { return SystemParametersInfoA( SPI_SETDESKPATTERN, -1, NULL, FALSE ); } /*********************************************************************** * GetSysColorBrush (USER.281) */ HBRUSH16 WINAPI GetSysColorBrush16( INT16 index ) { return HBRUSH_16( GetSysColorBrush(index) ); } /*********************************************************************** * SelectPalette (USER.282) */ HPALETTE16 WINAPI SelectPalette16( HDC16 hdc, HPALETTE16 hpal, BOOL16 bForceBackground ) { return HPALETTE_16( SelectPalette( HDC_32(hdc), HPALETTE_32(hpal), bForceBackground )); } /*********************************************************************** * RealizePalette (USER.283) */ UINT16 WINAPI RealizePalette16( HDC16 hdc ) { return UserRealizePalette( HDC_32(hdc) ); } /*********************************************************************** * GetFreeSystemResources (USER.284) */ WORD WINAPI GetFreeSystemResources16( WORD resType ) { STACK16FRAME* stack16 = MapSL((SEGPTR)NtCurrentTeb()->WOW32Reserved); HANDLE16 oldDS = stack16->ds; int userPercent, gdiPercent; switch(resType) { case GFSR_USERRESOURCES: stack16->ds = USER_HeapSel; userPercent = (int)LocalCountFree16() * 100 / LocalHeapSize16(); gdiPercent = 100; stack16->ds = oldDS; break; case GFSR_GDIRESOURCES: stack16->ds = gdi_inst; gdiPercent = (int)LocalCountFree16() * 100 / LocalHeapSize16(); userPercent = 100; stack16->ds = oldDS; break; case GFSR_SYSTEMRESOURCES: stack16->ds = USER_HeapSel; userPercent = (int)LocalCountFree16() * 100 / LocalHeapSize16(); stack16->ds = gdi_inst; gdiPercent = (int)LocalCountFree16() * 100 / LocalHeapSize16(); stack16->ds = oldDS; break; default: userPercent = gdiPercent = 0; break; } TRACE("<- userPercent %d, gdiPercent %d\n", userPercent, gdiPercent); return (WORD)min( userPercent, gdiPercent ); } /*********************************************************************** * SetDeskWallPaper (USER.285) */ BOOL16 WINAPI SetDeskWallPaper16( LPCSTR filename ) { return SetDeskWallPaper( filename ); } /*********************************************************************** * keybd_event (USER.289) */ void WINAPI keybd_event16( CONTEXT *context ) { DWORD dwFlags = 0; if (HIBYTE(context->Eax) & 0x80) dwFlags |= KEYEVENTF_KEYUP; if (HIBYTE(context->Ebx) & 0x01) dwFlags |= KEYEVENTF_EXTENDEDKEY; keybd_event( LOBYTE(context->Eax), LOBYTE(context->Ebx), dwFlags, MAKELONG(LOWORD(context->Esi), LOWORD(context->Edi)) ); } /*********************************************************************** * mouse_event (USER.299) */ void WINAPI mouse_event16( CONTEXT *context ) { mouse_event( LOWORD(context->Eax), LOWORD(context->Ebx), LOWORD(context->Ecx), LOWORD(context->Edx), MAKELONG(context->Esi, context->Edi) ); } /*********************************************************************** * GetClipCursor (USER.309) */ void WINAPI GetClipCursor16( RECT16 *rect ) { if (rect) { RECT rect32; GetClipCursor( &rect32 ); rect->left = rect32.left; rect->top = rect32.top; rect->right = rect32.right; rect->bottom = rect32.bottom; } } /*********************************************************************** * SignalProc (USER.314) */ void WINAPI SignalProc16( HANDLE16 hModule, UINT16 code, UINT16 uExitFn, HINSTANCE16 hInstance, HQUEUE16 hQueue ) { if (code == USIG16_DLL_UNLOAD) { hModule = GetExePtr(hModule); /* HOOK_FreeModuleHooks( hModule ); */ free_module_classes( hModule ); free_module_icons( hModule ); } } /*********************************************************************** * SetEventHook (USER.321) * * Used by Turbo Debugger for Windows */ FARPROC16 WINAPI SetEventHook16(FARPROC16 lpfnEventHook) { FIXME("(lpfnEventHook=%p): stub\n", lpfnEventHook); return 0; } /********************************************************************** * EnableHardwareInput (USER.331) */ BOOL16 WINAPI EnableHardwareInput16(BOOL16 bEnable) { FIXME("(%d) - stub\n", bEnable); return TRUE; } /********************************************************************** * LoadCursorIconHandler (USER.336) * * Supposed to load resources of Windows 2.x applications. */ HGLOBAL16 WINAPI LoadCursorIconHandler16( HGLOBAL16 hResource, HMODULE16 hModule, HRSRC16 hRsrc ) { FIXME("(%04x,%04x,%04x): old 2.x resources are not supported!\n", hResource, hModule, hRsrc); return 0; } /*********************************************************************** * GetMouseEventProc (USER.337) */ FARPROC16 WINAPI GetMouseEventProc16(void) { HMODULE16 hmodule = GetModuleHandle16("USER"); return GetProcAddress16( hmodule, "mouse_event" ); } /*********************************************************************** * IsUserIdle (USER.333) */ BOOL16 WINAPI IsUserIdle16(void) { if ( GetAsyncKeyState( VK_LBUTTON ) & 0x8000 ) return FALSE; if ( GetAsyncKeyState( VK_RBUTTON ) & 0x8000 ) return FALSE; if ( GetAsyncKeyState( VK_MBUTTON ) & 0x8000 ) return FALSE; /* Should check for screen saver activation here ... */ return TRUE; } /********************************************************************** * LoadDIBIconHandler (USER.357) * * RT_ICON resource loader, installed by USER_SignalProc when module * is initialized. */ HGLOBAL16 WINAPI LoadDIBIconHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc ) { /* If hResource is zero we must allocate a new memory block, if it's * non-zero but GlobalLock() returns NULL then it was discarded and * we have to recommit some memory, otherwise we just need to check * the block size. See LoadProc() in 16-bit SDK for more. */ FIXME( "%x %x %x: stub, not supported anymore\n", hMemObj, hModule, hRsrc ); return 0; } /********************************************************************** * LoadDIBCursorHandler (USER.356) * * RT_CURSOR resource loader. Same as above. */ HGLOBAL16 WINAPI LoadDIBCursorHandler16( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc ) { FIXME( "%x %x %x: stub, not supported anymore\n", hMemObj, hModule, hRsrc ); return 0; } /********************************************************************** * IsMenu (USER.358) */ BOOL16 WINAPI IsMenu16( HMENU16 hmenu ) { return IsMenu( HMENU_32(hmenu) ); } /*********************************************************************** * DCHook (USER.362) */ BOOL16 WINAPI DCHook16( HDC16 hdc, WORD code, DWORD data, LPARAM lParam ) { FIXME( "hDC = %x, %i: stub\n", hdc, code ); return FALSE; } /********************************************************************** * LookupIconIdFromDirectoryEx (USER.364) * * FIXME: exact parameter sizes */ INT16 WINAPI LookupIconIdFromDirectoryEx16( LPBYTE dir, BOOL16 bIcon, INT16 width, INT16 height, UINT16 cFlag ) { return LookupIconIdFromDirectoryEx( dir, bIcon, width, height, cFlag ); } /*********************************************************************** * CopyIcon (USER.368) */ HICON16 WINAPI CopyIcon16( HINSTANCE16 hInstance, HICON16 hIcon ) { CURSORICONINFO *info = get_icon_ptr( hIcon ); void *and_bits = info + 1; void *xor_bits = (BYTE *)and_bits + info->nHeight * get_bitmap_width_bytes( info->nWidth, 1 ); HGLOBAL16 ret = CreateCursorIconIndirect16( hInstance, info, and_bits, xor_bits ); release_icon_ptr( hIcon, info ); return ret; } /*********************************************************************** * CopyCursor (USER.369) */ HCURSOR16 WINAPI CopyCursor16( HINSTANCE16 hInstance, HCURSOR16 hCursor ) { CURSORICONINFO *info = get_icon_ptr( hCursor ); void *and_bits = info + 1; void *xor_bits = (BYTE *)and_bits + info->nHeight * get_bitmap_width_bytes( info->nWidth, 1 ); HGLOBAL16 ret = CreateCursorIconIndirect16( hInstance, info, and_bits, xor_bits ); release_icon_ptr( hCursor, info ); return ret; } /*********************************************************************** * SubtractRect (USER.373) */ BOOL16 WINAPI SubtractRect16( LPRECT16 dest, const RECT16 *src1, const RECT16 *src2 ) { RECT16 tmp; if (IsRectEmpty16( src1 )) { SetRectEmpty16( dest ); return FALSE; } *dest = *src1; if (IntersectRect16( &tmp, src1, src2 )) { if (EqualRect16( &tmp, dest )) { SetRectEmpty16( dest ); return FALSE; } if ((tmp.top == dest->top) && (tmp.bottom == dest->bottom)) { if (tmp.left == dest->left) dest->left = tmp.right; else if (tmp.right == dest->right) dest->right = tmp.left; } else if ((tmp.left == dest->left) && (tmp.right == dest->right)) { if (tmp.top == dest->top) dest->top = tmp.bottom; else if (tmp.bottom == dest->bottom) dest->bottom = tmp.top; } } return TRUE; } /********************************************************************** * DllEntryPoint (USER.374) */ BOOL WINAPI DllEntryPoint( DWORD reason, HINSTANCE16 inst, WORD ds, WORD heap, DWORD reserved1, WORD reserved2 ) { if (reason != DLL_PROCESS_ATTACH) return TRUE; if (USER_HeapSel) return TRUE; /* already called */ USER_HeapSel = ds; register_wow_handlers(); gdi_inst = LoadLibrary16( "gdi.exe" ); LoadLibrary16( "display.drv" ); LoadLibrary16( "keyboard.drv" ); LoadLibrary16( "mouse.drv" ); LoadLibrary16( "user.exe" ); /* make sure it never gets unloaded */ return TRUE; } /********************************************************************** * SetMenuContextHelpId (USER.384) */ BOOL16 WINAPI SetMenuContextHelpId16( HMENU16 hMenu, DWORD dwContextHelpID) { return SetMenuContextHelpId( HMENU_32(hMenu), dwContextHelpID ); } /********************************************************************** * GetMenuContextHelpId (USER.385) */ DWORD WINAPI GetMenuContextHelpId16( HMENU16 hMenu ) { return GetMenuContextHelpId( HMENU_32(hMenu) ); } /*********************************************************************** * LoadImage (USER.389) */ HANDLE16 WINAPI LoadImage16(HINSTANCE16 hinst, LPCSTR name, UINT16 type, INT16 cx, INT16 cy, UINT16 flags) { HGLOBAL16 handle; HRSRC16 hRsrc, hGroupRsrc; DWORD size; if (!hinst || (flags & LR_LOADFROMFILE)) { if (type == IMAGE_BITMAP) return HBITMAP_16( LoadImageA( 0, name, type, cx, cy, flags )); else return get_icon_16( LoadImageA( 0, name, type, cx, cy, flags )); } hinst = GetExePtr( hinst ); if (flags & LR_DEFAULTSIZE) { if (type == IMAGE_ICON) { if (!cx) cx = GetSystemMetrics(SM_CXICON); if (!cy) cy = GetSystemMetrics(SM_CYICON); } else if (type == IMAGE_CURSOR) { if (!cx) cx = GetSystemMetrics(SM_CXCURSOR); if (!cy) cy = GetSystemMetrics(SM_CYCURSOR); } } switch (type) { case IMAGE_BITMAP: { HBITMAP ret = 0; char *ptr; static const WCHAR prefixW[] = {'b','m','p',0}; BITMAPFILEHEADER header; WCHAR path[MAX_PATH], filename[MAX_PATH]; HANDLE file; filename[0] = 0; if (!(hRsrc = FindResource16( hinst, name, (LPCSTR)RT_BITMAP ))) return 0; if (!(handle = LoadResource16( hinst, hRsrc ))) return 0; if (!(ptr = LockResource16( handle ))) goto done; size = SizeofResource16( hinst, hRsrc ); header.bfType = 0x4d42; /* 'BM' */ header.bfReserved1 = 0; header.bfReserved2 = 0; header.bfSize = sizeof(header) + size; header.bfOffBits = 0; /* not used by the 32-bit loading code */ if (!GetTempPathW( MAX_PATH, path )) goto done; if (!GetTempFileNameW( path, prefixW, 0, filename )) goto done; file = CreateFileW( filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0 ); if (file != INVALID_HANDLE_VALUE) { DWORD written; BOOL ok; ok = WriteFile( file, &header, sizeof(header), &written, NULL ) && (written == sizeof(header)); if (ok) ok = WriteFile( file, ptr, size, &written, NULL ) && (written == size); CloseHandle( file ); if (ok) ret = LoadImageW( 0, filename, IMAGE_BITMAP, cx, cy, flags | LR_LOADFROMFILE ); } done: if (filename[0]) DeleteFileW( filename ); FreeResource16( handle ); return HBITMAP_16( ret ); } case IMAGE_ICON: case IMAGE_CURSOR: { HICON16 hIcon = 0; BYTE *dir, *bits; INT id = 0; if (!(hRsrc = FindResource16( hinst, name, (LPCSTR)(type == IMAGE_ICON ? RT_GROUP_ICON : RT_GROUP_CURSOR )))) return 0; hGroupRsrc = hRsrc; if (!(handle = LoadResource16( hinst, hRsrc ))) return 0; if ((dir = LockResource16( handle ))) id = LookupIconIdFromDirectory( dir, type == IMAGE_ICON ); FreeResource16( handle ); if (!id) return 0; if (!(hRsrc = FindResource16( hinst, MAKEINTRESOURCEA(id), (LPCSTR)(type == IMAGE_ICON ? RT_ICON : RT_CURSOR) ))) return 0; if ((flags & LR_SHARED) && (hIcon = find_shared_icon( hinst, hRsrc ) ) != 0) return hIcon; if (!(handle = LoadResource16( hinst, hRsrc ))) return 0; bits = LockResource16( handle ); size = SizeofResource16( hinst, hRsrc ); hIcon = CreateIconFromResourceEx16( bits, size, type == IMAGE_ICON, 0x00030000, cx, cy, flags ); FreeResource16( handle ); if (hIcon && (flags & LR_SHARED)) add_shared_icon( hinst, hRsrc, hGroupRsrc, hIcon ); return hIcon; } default: return 0; } } /****************************************************************************** * CopyImage (USER.390) Creates new image and copies attributes to it * */ HICON16 WINAPI CopyImage16(HANDLE16 hnd, UINT16 type, INT16 desiredx, INT16 desiredy, UINT16 flags) { if (flags & LR_COPYFROMRESOURCE) FIXME( "LR_COPYFROMRESOURCE not supported\n" ); switch (type) { case IMAGE_BITMAP: return HBITMAP_16( CopyImage( HBITMAP_32(hnd), type, desiredx, desiredy, flags )); case IMAGE_ICON: case IMAGE_CURSOR: return CopyIcon16( FarGetOwner16(hnd), hnd ); default: return 0; } } /********************************************************************** * DrawIconEx (USER.394) */ BOOL16 WINAPI DrawIconEx16(HDC16 hdc, INT16 xLeft, INT16 yTop, HICON16 hIcon, INT16 cxWidth, INT16 cyWidth, UINT16 istep, HBRUSH16 hbr, UINT16 flags) { return DrawIconEx(HDC_32(hdc), xLeft, yTop, get_icon_32(hIcon), cxWidth, cyWidth, istep, HBRUSH_32(hbr), flags); } /********************************************************************** * GetIconInfo (USER.395) */ BOOL16 WINAPI GetIconInfo16(HICON16 hIcon, LPICONINFO16 iconinfo) { CURSORICONINFO *info = get_icon_ptr( hIcon ); INT height; if (!info) return FALSE; if ((info->ptHotSpot.x == ICON_HOTSPOT) && (info->ptHotSpot.y == ICON_HOTSPOT)) { iconinfo->fIcon = TRUE; iconinfo->xHotspot = info->nWidth / 2; iconinfo->yHotspot = info->nHeight / 2; } else { iconinfo->fIcon = FALSE; iconinfo->xHotspot = info->ptHotSpot.x; iconinfo->yHotspot = info->ptHotSpot.y; } height = info->nHeight; if (info->bBitsPerPixel > 1) { iconinfo->hbmColor = HBITMAP_16( CreateBitmap( info->nWidth, info->nHeight, info->bPlanes, info->bBitsPerPixel, (char *)(info + 1) + info->nHeight * get_bitmap_width_bytes(info->nWidth,1) )); } else { iconinfo->hbmColor = 0; height *= 2; } iconinfo->hbmMask = HBITMAP_16( CreateBitmap( info->nWidth, height, 1, 1, info + 1 )); release_icon_ptr( hIcon, info ); return TRUE; } /*********************************************************************** * FinalUserInit (USER.400) */ void WINAPI FinalUserInit16( void ) { /* FIXME: Should chain to FinalGdiInit */ } /*********************************************************************** * CreateCursor (USER.406) */ HCURSOR16 WINAPI CreateCursor16(HINSTANCE16 hInstance, INT16 xHotSpot, INT16 yHotSpot, INT16 nWidth, INT16 nHeight, LPCVOID lpANDbits, LPCVOID lpXORbits) { CURSORICONINFO info; info.ptHotSpot.x = xHotSpot; info.ptHotSpot.y = yHotSpot; info.nWidth = nWidth; info.nHeight = nHeight; info.nWidthBytes = 0; info.bPlanes = 1; info.bBitsPerPixel = 1; return CreateCursorIconIndirect16(hInstance, &info, lpANDbits, lpXORbits); } /*********************************************************************** * CreateIcon (USER.407) */ HICON16 WINAPI CreateIcon16( HINSTANCE16 hInstance, INT16 nWidth, INT16 nHeight, BYTE bPlanes, BYTE bBitsPixel, LPCVOID lpANDbits, LPCVOID lpXORbits ) { CURSORICONINFO info; info.ptHotSpot.x = ICON_HOTSPOT; info.ptHotSpot.y = ICON_HOTSPOT; info.nWidth = nWidth; info.nHeight = nHeight; info.nWidthBytes = 0; info.bPlanes = bPlanes; info.bBitsPerPixel = bBitsPixel; return CreateCursorIconIndirect16( hInstance, &info, lpANDbits, lpXORbits ); } /*********************************************************************** * CreateCursorIconIndirect (USER.408) */ HGLOBAL16 WINAPI CreateCursorIconIndirect16( HINSTANCE16 hInstance, CURSORICONINFO *info, LPCVOID lpANDbits, LPCVOID lpXORbits ) { HICON16 handle; CURSORICONINFO *ptr; int sizeAnd, sizeXor; hInstance = GetExePtr( hInstance ); /* Make it a module handle */ if (!lpXORbits || !lpANDbits || info->bPlanes != 1) return 0; info->nWidthBytes = get_bitmap_width_bytes(info->nWidth,info->bBitsPerPixel); sizeXor = info->nHeight * info->nWidthBytes; sizeAnd = info->nHeight * get_bitmap_width_bytes( info->nWidth, 1 ); if (!(handle = alloc_icon_handle( sizeof(CURSORICONINFO) + sizeXor + sizeAnd ))) return 0; FarSetOwner16( handle, hInstance ); ptr = get_icon_ptr( handle ); memcpy( ptr, info, sizeof(*info) ); memcpy( ptr + 1, lpANDbits, sizeAnd ); memcpy( (char *)(ptr + 1) + sizeAnd, lpXORbits, sizeXor ); release_icon_ptr( handle, ptr ); return handle; } /*********************************************************************** * InitThreadInput (USER.409) */ HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags ) { /* nothing to do here */ return 0xbeef; } /******************************************************************* * InsertMenu (USER.410) */ BOOL16 WINAPI InsertMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags, UINT16 id, SEGPTR data ) { UINT pos32 = (UINT)pos; if ((pos == (UINT16)-1) && (flags & MF_BYPOSITION)) pos32 = (UINT)-1; if (IS_MENU_STRING_ITEM(flags) && data) return InsertMenuA( HMENU_32(hMenu), pos32, flags, id, MapSL(data) ); return InsertMenuA( HMENU_32(hMenu), pos32, flags, id, (LPSTR)data ); } /******************************************************************* * AppendMenu (USER.411) */ BOOL16 WINAPI AppendMenu16(HMENU16 hMenu, UINT16 flags, UINT16 id, SEGPTR data) { return InsertMenu16( hMenu, -1, flags | MF_BYPOSITION, id, data ); } /********************************************************************** * RemoveMenu (USER.412) */ BOOL16 WINAPI RemoveMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags ) { return RemoveMenu( HMENU_32(hMenu), nPos, wFlags ); } /********************************************************************** * DeleteMenu (USER.413) */ BOOL16 WINAPI DeleteMenu16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags ) { return DeleteMenu( HMENU_32(hMenu), nPos, wFlags ); } /******************************************************************* * ModifyMenu (USER.414) */ BOOL16 WINAPI ModifyMenu16( HMENU16 hMenu, UINT16 pos, UINT16 flags, UINT16 id, SEGPTR data ) { if (IS_MENU_STRING_ITEM(flags)) return ModifyMenuA( HMENU_32(hMenu), pos, flags, id, MapSL(data) ); return ModifyMenuA( HMENU_32(hMenu), pos, flags, id, (LPSTR)data ); } /********************************************************************** * CreatePopupMenu (USER.415) */ HMENU16 WINAPI CreatePopupMenu16(void) { return HMENU_16( CreatePopupMenu() ); } /********************************************************************** * SetMenuItemBitmaps (USER.418) */ BOOL16 WINAPI SetMenuItemBitmaps16( HMENU16 hMenu, UINT16 nPos, UINT16 wFlags, HBITMAP16 hNewUnCheck, HBITMAP16 hNewCheck) { return SetMenuItemBitmaps( HMENU_32(hMenu), nPos, wFlags, HBITMAP_32(hNewUnCheck), HBITMAP_32(hNewCheck) ); } /*********************************************************************** * wvsprintf (USER.421) */ INT16 WINAPI wvsprintf16( LPSTR buffer, LPCSTR spec, VA_LIST16 args ) { WPRINTF_FORMAT format; LPSTR p = buffer; UINT i, len, sign; CHAR number[20]; CHAR char_view = 0; LPCSTR lpcstr_view = NULL; INT int_view; SEGPTR seg_str; while (*spec) { if (*spec != '%') { *p++ = *spec++; continue; } spec++; if (*spec == '%') { *p++ = *spec++; continue; } spec += parse_format( spec, &format ); switch(format.type) { case WPR_CHAR: char_view = VA_ARG16( args, CHAR ); len = format.precision = 1; break; case WPR_STRING: seg_str = VA_ARG16( args, SEGPTR ); if (IsBadReadPtr16( seg_str, 1 )) lpcstr_view = ""; else lpcstr_view = MapSL( seg_str ); if (!lpcstr_view) lpcstr_view = "(null)"; for (len = 0; !format.precision || (len < format.precision); len++) if (!lpcstr_view[len]) break; format.precision = len; break; case WPR_SIGNED: if (format.flags & WPRINTF_LONG) int_view = VA_ARG16( args, INT ); else int_view = VA_ARG16( args, INT16 ); len = sprintf( number, "%d", int_view ); break; case WPR_UNSIGNED: if (format.flags & WPRINTF_LONG) int_view = VA_ARG16( args, UINT ); else int_view = VA_ARG16( args, UINT16 ); len = sprintf( number, "%u", int_view ); break; case WPR_HEXA: if (format.flags & WPRINTF_LONG) int_view = VA_ARG16( args, UINT ); else int_view = VA_ARG16( args, UINT16 ); len = sprintf( number, (format.flags & WPRINTF_UPPER_HEX) ? "%X" : "%x", int_view); break; case WPR_UNKNOWN: continue; } if (format.precision < len) format.precision = len; if (format.flags & WPRINTF_LEFTALIGN) format.flags &= ~WPRINTF_ZEROPAD; if ((format.flags & WPRINTF_ZEROPAD) && (format.width > format.precision)) format.precision = format.width; if (format.flags & WPRINTF_PREFIX_HEX) len += 2; sign = 0; if (!(format.flags & WPRINTF_LEFTALIGN)) for (i = format.precision; i < format.width; i++) *p++ = ' '; switch(format.type) { case WPR_CHAR: *p = char_view; /* wsprintf16 ignores null characters */ if (*p != '\0') p++; else if (format.width > 1) *p++ = ' '; break; case WPR_STRING: if (len) memcpy( p, lpcstr_view, len ); p += len; break; case WPR_HEXA: if (format.flags & WPRINTF_PREFIX_HEX) { *p++ = '0'; *p++ = (format.flags & WPRINTF_UPPER_HEX) ? 'X' : 'x'; len -= 2; } /* fall through */ case WPR_SIGNED: /* Transfer the sign now, just in case it will be zero-padded*/ if (number[0] == '-') { *p++ = '-'; sign = 1; } /* fall through */ case WPR_UNSIGNED: for (i = len; i < format.precision; i++) *p++ = '0'; if (len > sign) memcpy( p, number + sign, len - sign ); p += len-sign; break; case WPR_UNKNOWN: continue; } if (format.flags & WPRINTF_LEFTALIGN) for (i = format.precision; i < format.width; i++) *p++ = ' '; } *p = 0; return p - buffer; } /*********************************************************************** * _wsprintf (USER.420) */ INT16 WINAPIV wsprintf16( LPSTR buffer, LPCSTR spec, VA_LIST16 valist ) { return wvsprintf16( buffer, spec, valist ); } /*********************************************************************** * lstrcmp (USER.430) */ INT16 WINAPI lstrcmp16( LPCSTR str1, LPCSTR str2 ) { int ret; /* Looks too complicated, but in optimized strcpy we might get * a 32bit wide difference and would truncate it to 16 bit, so * erroneously returning equality. */ ret = strcmp( str1, str2 ); if (ret < 0) return -1; if (ret > 0) return 1; return 0; } /*********************************************************************** * AnsiUpper (USER.431) */ SEGPTR WINAPI AnsiUpper16( SEGPTR strOrChar ) { /* uppercase only one char if strOrChar < 0x10000 */ if (HIWORD(strOrChar)) { CharUpperA( MapSL(strOrChar) ); return strOrChar; } else return (SEGPTR)CharUpperA( (LPSTR)strOrChar ); } /*********************************************************************** * AnsiLower (USER.432) */ SEGPTR WINAPI AnsiLower16( SEGPTR strOrChar ) { /* lowercase only one char if strOrChar < 0x10000 */ if (HIWORD(strOrChar)) { CharLowerA( MapSL(strOrChar) ); return strOrChar; } else return (SEGPTR)CharLowerA( (LPSTR)strOrChar ); } /*********************************************************************** * AnsiUpperBuff (USER.437) */ UINT16 WINAPI AnsiUpperBuff16( LPSTR str, UINT16 len ) { CharUpperBuffA( str, len ? len : 65536 ); return len; } /*********************************************************************** * AnsiLowerBuff (USER.438) */ UINT16 WINAPI AnsiLowerBuff16( LPSTR str, UINT16 len ) { CharLowerBuffA( str, len ? len : 65536 ); return len; } /******************************************************************* * InsertMenuItem (USER.441) * * FIXME: untested */ BOOL16 WINAPI InsertMenuItem16( HMENU16 hmenu, UINT16 pos, BOOL16 byposition, const MENUITEMINFO16 *mii ) { MENUITEMINFOA miia; miia.cbSize = sizeof(miia); miia.fMask = mii->fMask; miia.dwTypeData = (LPSTR)mii->dwTypeData; miia.fType = mii->fType; miia.fState = mii->fState; miia.wID = mii->wID; miia.hSubMenu = HMENU_32(mii->hSubMenu); miia.hbmpChecked = HBITMAP_32(mii->hbmpChecked); miia.hbmpUnchecked = HBITMAP_32(mii->hbmpUnchecked); miia.dwItemData = mii->dwItemData; miia.cch = mii->cch; if (IS_MENU_STRING_ITEM(miia.fType)) miia.dwTypeData = MapSL(mii->dwTypeData); return InsertMenuItemA( HMENU_32(hmenu), pos, byposition, &miia ); } /********************************************************************** * DrawState (USER.449) */ BOOL16 WINAPI DrawState16( HDC16 hdc, HBRUSH16 hbr, DRAWSTATEPROC16 func, LPARAM ldata, WPARAM16 wdata, INT16 x, INT16 y, INT16 cx, INT16 cy, UINT16 flags ) { struct draw_state_info info; UINT opcode = flags & 0xf; if (opcode == DST_TEXT || opcode == DST_PREFIXTEXT) { /* make sure DrawStateA doesn't try to use ldata as a pointer */ if (!wdata) wdata = strlen( MapSL(ldata) ); if (!cx || !cy) { SIZE s; if (!GetTextExtentPoint32A( HDC_32(hdc), MapSL(ldata), wdata, &s )) return FALSE; if (!cx) cx = s.cx; if (!cy) cy = s.cy; } } info.proc = func; info.param = ldata; return DrawStateA( HDC_32(hdc), HBRUSH_32(hbr), draw_state_callback, (LPARAM)&info, wdata, x, y, cx, cy, flags ); } /********************************************************************** * CreateIconFromResourceEx (USER.450) * * FIXME: not sure about exact parameter types */ HICON16 WINAPI CreateIconFromResourceEx16(LPBYTE bits, UINT16 cbSize, BOOL16 bIcon, DWORD dwVersion, INT16 width, INT16 height, UINT16 cFlag) { return get_icon_16( CreateIconFromResourceEx( bits, cbSize, bIcon, dwVersion, width, height, cFlag )); } /*********************************************************************** * AdjustWindowRectEx (USER.454) */ BOOL16 WINAPI AdjustWindowRectEx16( LPRECT16 rect, DWORD style, BOOL16 menu, DWORD exStyle ) { RECT rect32; BOOL ret; rect32.left = rect->left; rect32.top = rect->top; rect32.right = rect->right; rect32.bottom = rect->bottom; ret = AdjustWindowRectEx( &rect32, style, menu, exStyle ); rect->left = rect32.left; rect->top = rect32.top; rect->right = rect32.right; rect->bottom = rect32.bottom; return ret; } /********************************************************************** * GetIconID (USER.455) */ WORD WINAPI GetIconID16( HGLOBAL16 hResource, DWORD resType ) { BYTE *dir = GlobalLock16(hResource); switch (resType) { case RT_CURSOR: return LookupIconIdFromDirectoryEx16( dir, FALSE, GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR), LR_MONOCHROME ); case RT_ICON: return LookupIconIdFromDirectoryEx16( dir, TRUE, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), 0 ); } return 0; } /********************************************************************** * LoadIconHandler (USER.456) */ HICON16 WINAPI LoadIconHandler16( HGLOBAL16 hResource, BOOL16 bNew ) { return CreateIconFromResourceEx16( LockResource16( hResource ), 0xffff, TRUE, bNew ? 0x00030000 : 0x00020000, 0, 0, LR_DEFAULTCOLOR ); } /*********************************************************************** * DestroyIcon (USER.457) */ BOOL16 WINAPI DestroyIcon16(HICON16 hIcon) { int count; TRACE("%04x\n", hIcon ); count = release_shared_icon( hIcon ); if (count != -1) return !count; /* assume non-shared */ free_icon_handle( hIcon ); return TRUE; } /*********************************************************************** * DestroyCursor (USER.458) */ BOOL16 WINAPI DestroyCursor16(HCURSOR16 hCursor) { return DestroyIcon16( hCursor ); } /*********************************************************************** * DumpIcon (USER.459) */ DWORD WINAPI DumpIcon16( SEGPTR pInfo, WORD *lpLen, SEGPTR *lpXorBits, SEGPTR *lpAndBits ) { CURSORICONINFO *info = MapSL( pInfo ); int sizeAnd, sizeXor; if (!info) return 0; sizeXor = info->nHeight * info->nWidthBytes; sizeAnd = info->nHeight * get_bitmap_width_bytes( info->nWidth, 1 ); if (lpAndBits) *lpAndBits = pInfo + sizeof(CURSORICONINFO); if (lpXorBits) *lpXorBits = pInfo + sizeof(CURSORICONINFO) + sizeAnd; if (lpLen) *lpLen = sizeof(CURSORICONINFO) + sizeAnd + sizeXor; return MAKELONG( sizeXor, sizeXor ); } /******************************************************************* * DRAG_QueryUpdate16 * * Recursively find a child that contains spDragInfo->pt point * and send WM_QUERYDROPOBJECT. Helper for DragObject16. */ static BOOL DRAG_QueryUpdate16( HWND hQueryWnd, SEGPTR spDragInfo ) { BOOL bResult; WPARAM wParam; POINT pt, old_pt; LPDRAGINFO16 ptrDragInfo = MapSL(spDragInfo); RECT tempRect; HWND child; if (!IsWindowEnabled(hQueryWnd)) return FALSE; old_pt.x = ptrDragInfo->pt.x; old_pt.y = ptrDragInfo->pt.y; pt = old_pt; ScreenToClient( hQueryWnd, &pt ); child = ChildWindowFromPointEx( hQueryWnd, pt, CWP_SKIPINVISIBLE ); if (!child) return FALSE; if (child != hQueryWnd) { wParam = 0; if (DRAG_QueryUpdate16( child, spDragInfo )) return TRUE; } else { GetClientRect( hQueryWnd, &tempRect ); wParam = !PtInRect( &tempRect, pt ); } ptrDragInfo->pt.x = pt.x; ptrDragInfo->pt.y = pt.y; ptrDragInfo->hScope = HWND_16(hQueryWnd); bResult = SendMessage16( HWND_16(hQueryWnd), WM_QUERYDROPOBJECT, wParam, spDragInfo ); if (!bResult) { ptrDragInfo->pt.x = old_pt.x; ptrDragInfo->pt.y = old_pt.y; } return bResult; } /****************************************************************************** * DragObject (USER.464) */ DWORD WINAPI DragObject16( HWND16 hwndScope, HWND16 hWnd, UINT16 wObj, HANDLE16 hOfStruct, WORD szList, HCURSOR16 hCursor ) { MSG msg; LPDRAGINFO16 lpDragInfo; SEGPTR spDragInfo; HCURSOR hOldCursor=0, hBummer=0, hCursor32; HGLOBAL16 hDragInfo = GlobalAlloc16( GMEM_SHARE | GMEM_ZEROINIT, 2*sizeof(DRAGINFO16)); HCURSOR hCurrentCursor = 0; HWND16 hCurrentWnd = 0; lpDragInfo = (LPDRAGINFO16) GlobalLock16(hDragInfo); spDragInfo = WOWGlobalLock16(hDragInfo); if( !lpDragInfo || !spDragInfo ) return 0L; if (!(hBummer = LoadCursorA(0, MAKEINTRESOURCEA(OCR_NO)))) { GlobalFree16(hDragInfo); return 0L; } if ((hCursor32 = get_icon_32( hCursor ))) SetCursor( hCursor32 ); lpDragInfo->hWnd = hWnd; lpDragInfo->hScope = 0; lpDragInfo->wFlags = wObj; lpDragInfo->hList = szList; /* near pointer! */ lpDragInfo->hOfStruct = hOfStruct; lpDragInfo->l = 0L; SetCapture( HWND_32(hWnd) ); ShowCursor( TRUE ); do { GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST ); *(lpDragInfo+1) = *lpDragInfo; lpDragInfo->pt.x = msg.pt.x; lpDragInfo->pt.y = msg.pt.y; /* update DRAGINFO struct */ if( DRAG_QueryUpdate16(WIN_Handle32(hwndScope), spDragInfo) > 0 ) hCurrentCursor = hCursor32; else { hCurrentCursor = hBummer; lpDragInfo->hScope = 0; } if( hCurrentCursor ) SetCursor(hCurrentCursor); /* send WM_DRAGLOOP */ SendMessage16( hWnd, WM_DRAGLOOP, hCurrentCursor != hBummer, spDragInfo ); /* send WM_DRAGSELECT or WM_DRAGMOVE */ if( hCurrentWnd != lpDragInfo->hScope ) { if( hCurrentWnd ) SendMessage16( hCurrentWnd, WM_DRAGSELECT, 0, MAKELPARAM(LOWORD(spDragInfo)+sizeof(DRAGINFO16), HIWORD(spDragInfo)) ); hCurrentWnd = lpDragInfo->hScope; if( hCurrentWnd ) SendMessage16( hCurrentWnd, WM_DRAGSELECT, 1, spDragInfo); } else if( hCurrentWnd ) SendMessage16( hCurrentWnd, WM_DRAGMOVE, 0, spDragInfo); } while( msg.message != WM_LBUTTONUP && msg.message != WM_NCLBUTTONUP ); ReleaseCapture(); ShowCursor( FALSE ); if( hCursor ) SetCursor(hOldCursor); if( hCurrentCursor != hBummer ) msg.lParam = SendMessage16( lpDragInfo->hScope, WM_DROPOBJECT, hWnd, spDragInfo ); else msg.lParam = 0; GlobalFree16(hDragInfo); return (DWORD)(msg.lParam); } /*********************************************************************** * DrawFocusRect (USER.466) */ void WINAPI DrawFocusRect16( HDC16 hdc, const RECT16* rc ) { RECT rect32; rect32.left = rc->left; rect32.top = rc->top; rect32.right = rc->right; rect32.bottom = rc->bottom; DrawFocusRect( HDC_32(hdc), &rect32 ); } /*********************************************************************** * AnsiNext (USER.472) */ SEGPTR WINAPI AnsiNext16(SEGPTR current) { char *ptr = MapSL(current); return current + (CharNextA(ptr) - ptr); } /*********************************************************************** * AnsiPrev (USER.473) */ SEGPTR WINAPI AnsiPrev16( LPCSTR start, SEGPTR current ) { char *ptr = MapSL(current); return current - (ptr - CharPrevA( start, ptr )); } /**************************************************************************** * GetKeyboardLayoutName (USER.477) */ INT16 WINAPI GetKeyboardLayoutName16( LPSTR name ) { return GetKeyboardLayoutNameA( name ); } /*********************************************************************** * SystemParametersInfo (USER.483) */ BOOL16 WINAPI SystemParametersInfo16( UINT16 uAction, UINT16 uParam, LPVOID lpvParam, UINT16 fuWinIni ) { BOOL16 ret; TRACE("(%u, %u, %p, %u)\n", uAction, uParam, lpvParam, fuWinIni); switch (uAction) { case SPI_GETBEEP: case SPI_GETSCREENSAVEACTIVE: case SPI_GETICONTITLEWRAP: case SPI_GETMENUDROPALIGNMENT: case SPI_GETFASTTASKSWITCH: case SPI_GETDRAGFULLWINDOWS: { BOOL tmp; ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni ); if (ret && lpvParam) *(BOOL16 *)lpvParam = tmp; break; } case SPI_GETBORDER: case SPI_ICONHORIZONTALSPACING: case SPI_GETSCREENSAVETIMEOUT: case SPI_GETGRIDGRANULARITY: case SPI_GETKEYBOARDDELAY: case SPI_ICONVERTICALSPACING: { INT tmp; ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni ); if (ret && lpvParam) *(INT16 *)lpvParam = tmp; break; } case SPI_GETKEYBOARDSPEED: case SPI_GETMOUSEHOVERWIDTH: case SPI_GETMOUSEHOVERHEIGHT: case SPI_GETMOUSEHOVERTIME: { DWORD tmp; ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni ); if (ret && lpvParam) *(WORD *)lpvParam = tmp; break; } case SPI_GETICONTITLELOGFONT: { LOGFONTA tmp; ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni ); if (ret && lpvParam) logfont_32_to_16( &tmp, (LPLOGFONT16)lpvParam ); break; } case SPI_GETNONCLIENTMETRICS: { NONCLIENTMETRICSA tmp; LPNONCLIENTMETRICS16 lpnm16 = (LPNONCLIENTMETRICS16)lpvParam; if (lpnm16 && lpnm16->cbSize == sizeof(NONCLIENTMETRICS16)) { tmp.cbSize = sizeof(NONCLIENTMETRICSA); ret = SystemParametersInfoA( uAction, uParam, &tmp, fuWinIni ); if (ret) { lpnm16->iBorderWidth = tmp.iBorderWidth; lpnm16->iScrollWidth = tmp.iScrollWidth; lpnm16->iScrollHeight = tmp.iScrollHeight; lpnm16->iCaptionWidth = tmp.iCaptionWidth; lpnm16->iCaptionHeight = tmp.iCaptionHeight; lpnm16->iSmCaptionWidth = tmp.iSmCaptionWidth; lpnm16->iSmCaptionHeight = tmp.iSmCaptionHeight; lpnm16->iMenuWidth = tmp.iMenuWidth; lpnm16->iMenuHeight = tmp.iMenuHeight; logfont_32_to_16( &tmp.lfCaptionFont, &lpnm16->lfCaptionFont ); logfont_32_to_16( &tmp.lfSmCaptionFont, &lpnm16->lfSmCaptionFont ); logfont_32_to_16( &tmp.lfMenuFont, &lpnm16->lfMenuFont ); logfont_32_to_16( &tmp.lfStatusFont, &lpnm16->lfStatusFont ); logfont_32_to_16( &tmp.lfMessageFont, &lpnm16->lfMessageFont ); } } else /* winfile 95 sets cbSize to 340 */ ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni ); break; } case SPI_GETWORKAREA: { RECT tmp; ret = SystemParametersInfoA( uAction, uParam, lpvParam ? &tmp : NULL, fuWinIni ); if (ret && lpvParam) { RECT16 *r16 = lpvParam; r16->left = tmp.left; r16->top = tmp.top; r16->right = tmp.right; r16->bottom = tmp.bottom; } break; } default: ret = SystemParametersInfoA( uAction, uParam, lpvParam, fuWinIni ); break; } return ret; } /*********************************************************************** * USER_489 (USER.489) */ LONG WINAPI stub_USER_489(void) { FIXME("stub\n"); return 0; } /*********************************************************************** * USER_490 (USER.490) */ LONG WINAPI stub_USER_490(void) { FIXME("stub\n"); return 0; } /*********************************************************************** * USER_492 (USER.492) */ LONG WINAPI stub_USER_492(void) { FIXME("stub\n"); return 0; } /*********************************************************************** * USER_496 (USER.496) */ LONG WINAPI stub_USER_496(void) { FIXME("stub\n"); return 0; } /*********************************************************************** * FormatMessage (USER.606) */ DWORD WINAPI FormatMessage16( DWORD dwFlags, SEGPTR lpSource, /* [in] NOTE: not always a valid pointer */ WORD dwMessageId, WORD dwLanguageId, LPSTR lpBuffer, /* [out] NOTE: *((HLOCAL16*)) for FORMAT_MESSAGE_ALLOCATE_BUFFER*/ WORD nSize, LPDWORD args ) /* [in] NOTE: va_list *args */ { /* This implementation is completely dependent on the format of the va_list on x86 CPUs */ LPSTR target,t; DWORD talloced; LPSTR from,f; DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK; BOOL eos = FALSE; LPSTR allocstring = NULL; TRACE("(0x%x,%x,%d,0x%x,%p,%d,%p)\n", dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args); if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) && (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)) return 0; if ((dwFlags & FORMAT_MESSAGE_FROM_STRING) &&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) || (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0; if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK) FIXME("line wrapping (%u) not supported.\n", width); from = NULL; if (dwFlags & FORMAT_MESSAGE_FROM_STRING) { char *source = MapSL(lpSource); from = HeapAlloc( GetProcessHeap(), 0, strlen(source)+1 ); strcpy( from, source ); } else if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) { from = HeapAlloc( GetProcessHeap(),0,200 ); sprintf(from,"Systemmessage, messageid = 0x%08x\n",dwMessageId); } else if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) { INT16 bufsize; HINSTANCE16 hinst16 = ((HINSTANCE16)lpSource & 0xffff); dwMessageId &= 0xFFFF; bufsize=LoadString16(hinst16,dwMessageId,NULL,0); if (bufsize) { from = HeapAlloc( GetProcessHeap(), 0, bufsize +1); LoadString16(hinst16,dwMessageId,from,bufsize+1); } } target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100); t = target; talloced= 100; #define ADD_TO_T(c) \ do { \ *t++=c;\ if (t-target == talloced) {\ target = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\ t = target+talloced;\ talloced*=2;\ } \ } while(0) if (from) { f=from; while (*f && !eos) { if (*f=='%') { int insertnr; char *fmtstr,*x,*lastf; DWORD *argliststart; fmtstr = NULL; lastf = f; f++; if (!*f) { ADD_TO_T('%'); continue; } switch (*f) { case '1':case '2':case '3':case '4':case '5': case '6':case '7':case '8':case '9': insertnr=*f-'0'; switch (f[1]) { case '0':case '1':case '2':case '3': case '4':case '5':case '6':case '7': case '8':case '9': f++; insertnr=insertnr*10+*f-'0'; f++; break; default: f++; break; } if (*f=='!') { f++; if (NULL!=(x=strchr(f,'!'))) { *x='\0'; fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2); sprintf(fmtstr,"%%%s",f); f=x+1; } else { fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2); sprintf(fmtstr,"%%%s",f); f+=strlen(f); /*at \0*/ } } else { if(!args) break; fmtstr=HeapAlloc( GetProcessHeap(), 0, 3 ); strcpy( fmtstr, "%s" ); } if (args) { int ret; int sz; LPSTR b = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz = 100); argliststart=args+insertnr-1; /* CMF - This makes a BIG assumption about va_list */ while ((ret = vsnprintf(b, sz, fmtstr, (va_list) argliststart)) < 0 || ret >= sz) { LPSTR new_b; sz = (ret == -1 ? sz + 100 : ret + 1); new_b = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, b, sz); if (!new_b) break; b = new_b; } for (x=b; *x; x++) ADD_TO_T(*x); HeapFree(GetProcessHeap(), 0, b); } else { /* NULL args - copy formatstr * (probably wrong) */ while ((lastfleft; rect32.top = rc->top; rect32.right = rc->right; rect32.bottom = rc->bottom; ret = DrawFrameControl( HDC_32(hdc), &rect32, uType, uState ); rc->left = rect32.left; rc->top = rect32.top; rc->right = rect32.right; rc->bottom = rect32.bottom; return ret; } /********************************************************************** * DrawEdge (USER.659) */ BOOL16 WINAPI DrawEdge16( HDC16 hdc, LPRECT16 rc, UINT16 edge, UINT16 flags ) { RECT rect32; BOOL ret; rect32.left = rc->left; rect32.top = rc->top; rect32.right = rc->right; rect32.bottom = rc->bottom; ret = DrawEdge( HDC_32(hdc), &rect32, edge, flags ); rc->left = rect32.left; rc->top = rect32.top; rc->right = rect32.right; rc->bottom = rect32.bottom; return ret; } /********************************************************************** * CheckMenuRadioItem (USER.666) */ BOOL16 WINAPI CheckMenuRadioItem16(HMENU16 hMenu, UINT16 first, UINT16 last, UINT16 check, BOOL16 bypos) { return CheckMenuRadioItem( HMENU_32(hMenu), first, last, check, bypos ); }