From 5ec4d1be97b19d57508d87df34fd7a7d32569d3c Mon Sep 17 00:00:00 2001 From: Martin Payne Date: Sun, 24 Sep 2017 09:04:51 +0100 Subject: [PATCH] user.exe16: Support Windows 2 menus. Signed-off-by: Martin Payne Signed-off-by: Alexandre Julliard --- dlls/krnl386.exe16/krnl386.exe16.spec | 1 + dlls/user.exe16/user.c | 44 +++++++++++++++++++-------- dlls/user.exe16/user_private.h | 1 + 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/dlls/krnl386.exe16/krnl386.exe16.spec b/dlls/krnl386.exe16/krnl386.exe16.spec index 62d37e5e4fd..0fd7e7a164c 100644 --- a/dlls/krnl386.exe16/krnl386.exe16.spec +++ b/dlls/krnl386.exe16/krnl386.exe16.spec @@ -706,6 +706,7 @@ @ stdcall -arch=win32 GetCurrentTask() @ stdcall -arch=win32 GetDOSEnvironment16() @ stdcall -arch=win32 GetExePtr(long) +@ stdcall -arch=win32 GetExeVersion16() @ stdcall -arch=win32 GetExpWinVer16(long) @ stdcall -arch=win32 GetModuleHandle16(str) @ stdcall -arch=win32 GlobalReAlloc16(long long long) diff --git a/dlls/user.exe16/user.c b/dlls/user.exe16/user.c index 35f25859594..eac4a19d39f 100644 --- a/dlls/user.exe16/user.c +++ b/dlls/user.exe16/user.c @@ -1428,7 +1428,7 @@ HMENU16 WINAPI LookupMenuHandle16( HMENU16 hmenu, INT16 id ) } -static LPCSTR parse_menu_resource( LPCSTR res, HMENU hMenu ) +static LPCSTR parse_menu_resource( LPCSTR res, HMENU hMenu, BOOL oldFormat ) { WORD flags, id = 0; LPCSTR str; @@ -1436,11 +1436,21 @@ static LPCSTR parse_menu_resource( LPCSTR res, HMENU hMenu ) do { - flags = GET_WORD(res); + /* 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; - res += sizeof(WORD); if (!(flags & MF_POPUP)) { id = GET_WORD(res); @@ -1452,7 +1462,7 @@ static LPCSTR parse_menu_resource( LPCSTR res, HMENU hMenu ) { HMENU hSubMenu = CreatePopupMenu(); if (!hSubMenu) return NULL; - if (!(res = parse_menu_resource( res, hSubMenu ))) return NULL; + if (!(res = parse_menu_resource( res, hSubMenu, oldFormat ))) return NULL; AppendMenuA( hMenu, flags, (UINT_PTR)hSubMenu, str ); } else /* Not a popup */ @@ -1468,22 +1478,32 @@ static LPCSTR parse_menu_resource( LPCSTR res, HMENU hMenu ) */ HMENU16 WINAPI LoadMenuIndirect16( LPCVOID template ) { + BOOL oldFormat; HMENU hMenu; WORD version, offset; LPCSTR p = template; TRACE("(%p)\n", template ); - version = GET_WORD(p); - p += sizeof(WORD); - if (version) + + /* 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) { - WARN("version must be 0 for Win16\n" ); - return 0; + 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; } - offset = GET_WORD(p); - p += sizeof(WORD) + offset; + if (!(hMenu = CreateMenu())) return 0; - if (!parse_menu_resource( p, hMenu )) + if (!parse_menu_resource( p, hMenu, oldFormat )) { DestroyMenu( hMenu ); return 0; diff --git a/dlls/user.exe16/user_private.h b/dlls/user.exe16/user_private.h index 7c91afb2ce0..336b89102d4 100644 --- a/dlls/user.exe16/user_private.h +++ b/dlls/user.exe16/user_private.h @@ -95,6 +95,7 @@ extern LRESULT WINPROC_CallProc32ATo16( winproc_callback16_t callback, HWND hwnd extern void call_WH_CALLWNDPROC_hook( HWND16 hwnd, UINT16 msg, WPARAM16 wp, LPARAM lp ) DECLSPEC_HIDDEN; +#define GET_BYTE(ptr) (*(const BYTE *)(ptr)) #define GET_WORD(ptr) (*(const WORD *)(ptr)) #define GET_DWORD(ptr) (*(const DWORD *)(ptr))