You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
690 lines
21 KiB
690 lines
21 KiB
/****************************** Module Header ******************************\
|
|
*
|
|
* Module Name: clmenu.c
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
*
|
|
* Menu Loading Routines
|
|
*
|
|
* History:
|
|
* 24-Sep-1990 mikeke From win30
|
|
* 29-Nov-1994 JimA Moved from server.
|
|
\***************************************************************************/
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
/***************************************************************************\
|
|
* MenuLoadWinTemplates
|
|
*
|
|
* Recursive routine that loads in the new style menu template and
|
|
* builds the menu. Assumes that the menu template header has already been
|
|
* read in and processed elsewhere...
|
|
*
|
|
* History:
|
|
* 28-Sep-1990 mikeke from win30
|
|
\***************************************************************************/
|
|
|
|
LPBYTE MenuLoadWinTemplates(
|
|
LPBYTE lpMenuTemplate,
|
|
HMENU *phMenu)
|
|
{
|
|
HMENU hMenu;
|
|
UINT menuFlags = 0;
|
|
ULONG_PTR menuId = 0;
|
|
LPWSTR lpmenuText;
|
|
MENUITEMINFO mii;
|
|
UNICODE_STRING str;
|
|
|
|
if (!(hMenu = NtUserCreateMenu()))
|
|
goto memoryerror;
|
|
|
|
do {
|
|
|
|
/*
|
|
* Get the menu flags.
|
|
*/
|
|
menuFlags = (UINT)(*(WORD *)lpMenuTemplate);
|
|
lpMenuTemplate += 2;
|
|
|
|
if (menuFlags & ~MF_VALID) {
|
|
RIPERR1(ERROR_INVALID_DATA, RIP_WARNING, "Menu Flags %lX are invalid", menuFlags);
|
|
goto memoryerror;
|
|
}
|
|
|
|
|
|
if (!(menuFlags & MF_POPUP)) {
|
|
menuId = *(WORD *)lpMenuTemplate;
|
|
lpMenuTemplate += 2;
|
|
}
|
|
|
|
lpmenuText = (LPWSTR)lpMenuTemplate;
|
|
|
|
if (*lpmenuText) {
|
|
/*
|
|
* Some Win3.1 and Win95 16 bit apps (chessmaster, mavis typing) know that
|
|
* dwItemData for MFT_OWNERDRAW items is a pointer to a string in the resource data.
|
|
* So WOW has given us the proper pointer from the 16 bit resource.
|
|
*
|
|
* Sundown Note:
|
|
* __unaligned unsigned long value pointed by lpMenuTemplate is zero-extended to
|
|
* update lpmenuText. WOW restrictions.
|
|
*/
|
|
if ((menuFlags & MFT_OWNERDRAW)
|
|
&& (GetClientInfo()->dwTIFlags & TIF_16BIT)) {
|
|
lpmenuText = (LPWSTR)ULongToPtr( (*(DWORD UNALIGNED *)lpMenuTemplate) );
|
|
/*
|
|
* We'll skip one WCHAR later; so skip only the difference now.
|
|
*/
|
|
lpMenuTemplate += sizeof(DWORD) - sizeof(WCHAR);
|
|
} else {
|
|
/*
|
|
* If a string exists, then skip to the end of it.
|
|
*/
|
|
RtlInitUnicodeString(&str, lpmenuText);
|
|
lpMenuTemplate = lpMenuTemplate + str.Length;
|
|
}
|
|
|
|
} else {
|
|
lpmenuText = NULL;
|
|
}
|
|
|
|
/*
|
|
* Skip over terminating NULL of the string (or the single NULL
|
|
* if empty string).
|
|
*/
|
|
lpMenuTemplate += sizeof(WCHAR);
|
|
lpMenuTemplate = NextWordBoundary(lpMenuTemplate);
|
|
|
|
RtlZeroMemory(&mii, sizeof(mii));
|
|
mii.cbSize = sizeof(MENUITEMINFO);
|
|
mii.fMask = MIIM_ID | MIIM_STATE | MIIM_FTYPE;
|
|
if (lpmenuText) {
|
|
mii.fMask |= MIIM_STRING;
|
|
}
|
|
|
|
if (menuFlags & MF_POPUP) {
|
|
mii.fMask |= MIIM_SUBMENU;
|
|
lpMenuTemplate = MenuLoadWinTemplates(lpMenuTemplate,
|
|
(HMENU *)&menuId);
|
|
if (!lpMenuTemplate)
|
|
goto memoryerror;
|
|
|
|
mii.hSubMenu = (HMENU)menuId;
|
|
}
|
|
|
|
/*
|
|
* We have to take out MF_HILITE since that bit marks the end of a
|
|
* menu in a resource file. Since we shouldn't have any pre hilited
|
|
* items in the menu anyway, this is no big deal.
|
|
*/
|
|
if (menuFlags & MF_BITMAP) {
|
|
|
|
/*
|
|
* Don't allow bitmaps from the resource file.
|
|
*/
|
|
menuFlags = (UINT)((menuFlags | MFT_RIGHTJUSTIFY) & ~MF_BITMAP);
|
|
}
|
|
|
|
// We have to take out MFS_HILITE since that bit marks the end of a menu in
|
|
// a resource file. Since we shouldn't have any pre hilited items in the
|
|
// menu anyway, this is no big deal.
|
|
mii.fState = (menuFlags & MFS_OLDAPI_MASK) & ~MFS_HILITE;
|
|
mii.fType = (menuFlags & MFT_OLDAPI_MASK);
|
|
if (menuFlags & MFT_OWNERDRAW)
|
|
{
|
|
mii.fMask |= MIIM_DATA;
|
|
mii.dwItemData = (ULONG_PTR) lpmenuText;
|
|
lpmenuText = 0;
|
|
}
|
|
mii.dwTypeData = (LPWSTR) lpmenuText;
|
|
mii.cch = (UINT)-1;
|
|
mii.wID = (UINT)menuId;
|
|
|
|
if (!NtUserThunkedMenuItemInfo(hMenu, MFMWFP_NOITEM, TRUE, TRUE,
|
|
&mii, lpmenuText ? &str : NULL)) {
|
|
if (menuFlags & MF_POPUP)
|
|
NtUserDestroyMenu(mii.hSubMenu);
|
|
goto memoryerror;
|
|
}
|
|
|
|
} while (!(menuFlags & MF_END));
|
|
|
|
*phMenu = hMenu;
|
|
return lpMenuTemplate;
|
|
|
|
memoryerror:
|
|
if (hMenu != NULL)
|
|
NtUserDestroyMenu(hMenu);
|
|
*phMenu = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* MenuLoadChicagoTemplates
|
|
*
|
|
* Recursive routine that loads in the new new style menu template and
|
|
* builds the menu. Assumes that the menu template header has already been
|
|
* read in and processed elsewhere...
|
|
*
|
|
* History:
|
|
* 15-Dec-93 SanfordS Created
|
|
\***************************************************************************/
|
|
|
|
PMENUITEMTEMPLATE2 MenuLoadChicagoTemplates(
|
|
PMENUITEMTEMPLATE2 lpMenuTemplate,
|
|
HMENU *phMenu,
|
|
WORD wResInfo,
|
|
UINT mftRtl)
|
|
{
|
|
HMENU hMenu;
|
|
HMENU hSubMenu;
|
|
long menuId = 0;
|
|
LPWSTR lpmenuText;
|
|
MENUITEMINFO mii;
|
|
UNICODE_STRING str;
|
|
DWORD dwHelpID;
|
|
|
|
if (!(hMenu = NtUserCreateMenu()))
|
|
goto memoryerror;
|
|
|
|
do {
|
|
if (!(wResInfo & MFR_POPUP)) {
|
|
/*
|
|
* If the PREVIOUS wResInfo field was not a POPUP, the
|
|
* dwHelpID field is not there. Back up so things fit.
|
|
*/
|
|
lpMenuTemplate = (PMENUITEMTEMPLATE2)(((LPBYTE)lpMenuTemplate) -
|
|
sizeof(lpMenuTemplate->dwHelpID));
|
|
dwHelpID = 0;
|
|
} else
|
|
dwHelpID = lpMenuTemplate->dwHelpID;
|
|
|
|
menuId = lpMenuTemplate->menuId;
|
|
|
|
RtlZeroMemory(&mii, sizeof(mii));
|
|
mii.cbSize = sizeof(MENUITEMINFO);
|
|
mii.fMask = MIIM_ID | MIIM_STATE | MIIM_FTYPE ;
|
|
|
|
mii.fType = lpMenuTemplate->fType | mftRtl;
|
|
if (mii.fType & ~MFT_MASK) {
|
|
RIPERR1(ERROR_INVALID_DATA, RIP_WARNING, "Menu Type flags %lX are invalid", mii.fType);
|
|
goto memoryerror;
|
|
}
|
|
|
|
mii.fState = lpMenuTemplate->fState;
|
|
if (mii.fState & ~MFS_MASK) {
|
|
RIPERR1(ERROR_INVALID_DATA, RIP_WARNING, "Menu State flags %lX are invalid", mii.fState);
|
|
goto memoryerror;
|
|
}
|
|
|
|
wResInfo = lpMenuTemplate->wResInfo;
|
|
if (wResInfo & ~(MF_END | MFR_POPUP)) {
|
|
RIPERR1(ERROR_INVALID_DATA, RIP_WARNING, "Menu ResInfo flags %lX are invalid", wResInfo);
|
|
goto memoryerror;
|
|
}
|
|
|
|
if (dwHelpID) {
|
|
NtUserSetMenuContextHelpId(hMenu,dwHelpID);
|
|
}
|
|
if (lpMenuTemplate->mtString[0]) {
|
|
lpmenuText = lpMenuTemplate->mtString;
|
|
mii.fMask |= MIIM_STRING;
|
|
} else {
|
|
lpmenuText = NULL;
|
|
}
|
|
RtlInitUnicodeString(&str, lpmenuText);
|
|
|
|
mii.dwTypeData = (LPWSTR) lpmenuText;
|
|
|
|
/*
|
|
* skip to next menu item template (DWORD boundary)
|
|
*/
|
|
lpMenuTemplate = (PMENUITEMTEMPLATE2)
|
|
(((LPBYTE)lpMenuTemplate) +
|
|
sizeof(MENUITEMTEMPLATE2) +
|
|
((str.Length + 3) & ~3));
|
|
|
|
if (mii.fType & MFT_OWNERDRAW)
|
|
{
|
|
mii.fMask |= MIIM_DATA;
|
|
mii.dwItemData = (ULONG_PTR) mii.dwTypeData;
|
|
mii.dwTypeData = 0;
|
|
}
|
|
|
|
/*
|
|
* If MFT_RIGHTORDER is specified then all subsequent
|
|
* menus are right-to-left as well.
|
|
*/
|
|
if (mii.fType & MFT_RIGHTORDER)
|
|
{
|
|
mftRtl = MFT_RIGHTORDER;
|
|
NtUserSetMenuFlagRtoL(hMenu);
|
|
}
|
|
|
|
if (wResInfo & MFR_POPUP) {
|
|
mii.fMask |= MIIM_SUBMENU;
|
|
lpMenuTemplate = MenuLoadChicagoTemplates(lpMenuTemplate,
|
|
&hSubMenu, MFR_POPUP, mftRtl);
|
|
if (lpMenuTemplate == NULL)
|
|
goto memoryerror;
|
|
mii.hSubMenu = hSubMenu;
|
|
}
|
|
|
|
if (mii.fType & MFT_BITMAP) {
|
|
|
|
/*
|
|
* Don't allow bitmaps from the resource file.
|
|
*/
|
|
mii.fType = (mii.fType | MFT_RIGHTJUSTIFY) & ~MFT_BITMAP;
|
|
}
|
|
|
|
mii.cch = (UINT)-1;
|
|
mii.wID = menuId;
|
|
if (!NtUserThunkedMenuItemInfo(hMenu, MFMWFP_NOITEM, TRUE, TRUE,
|
|
&mii, &str)) {
|
|
if (wResInfo & MFR_POPUP)
|
|
NtUserDestroyMenu(mii.hSubMenu);
|
|
goto memoryerror;
|
|
}
|
|
wResInfo &= ~MFR_POPUP;
|
|
} while (!(wResInfo & MFR_END));
|
|
|
|
*phMenu = hMenu;
|
|
return lpMenuTemplate;
|
|
|
|
memoryerror:
|
|
if (hMenu != NULL)
|
|
NtUserDestroyMenu(hMenu);
|
|
*phMenu = NULL;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/***************************************************************************\
|
|
* CreateMenuFromResource
|
|
*
|
|
* Loads the menu resource named by the lpMenuTemplate parameter. The
|
|
* template specified by lpMenuTemplate is a collection of one or more
|
|
* MENUITEMTEMPLATE structures, each of which may contain one or more items
|
|
* and popup menus. If successful, returns a handle to the menu otherwise
|
|
* returns NULL.
|
|
*
|
|
* History:
|
|
* 28-Sep-1990 mikeke from win30
|
|
\***************************************************************************/
|
|
|
|
HMENU CreateMenuFromResource(
|
|
LPBYTE lpMenuTemplate)
|
|
{
|
|
HMENU hMenu = NULL;
|
|
UINT menuTemplateVersion;
|
|
UINT menuTemplateHeaderSize;
|
|
|
|
/*
|
|
* Win3 menu resource: First, strip version number word out of the menu
|
|
* template. This value should be 0 for Win3, 1 for win4.
|
|
*/
|
|
menuTemplateVersion = *((WORD *)lpMenuTemplate)++;
|
|
if (menuTemplateVersion > 1) {
|
|
RIPMSG0(RIP_WARNING, "Menu Version number > 1");
|
|
return NULL;
|
|
}
|
|
menuTemplateHeaderSize = *((WORD *)lpMenuTemplate)++;
|
|
lpMenuTemplate += menuTemplateHeaderSize;
|
|
switch (menuTemplateVersion) {
|
|
case 0:
|
|
MenuLoadWinTemplates(lpMenuTemplate, &hMenu);
|
|
break;
|
|
|
|
case 1:
|
|
MenuLoadChicagoTemplates((PMENUITEMTEMPLATE2)lpMenuTemplate, &hMenu, 0, 0);
|
|
break;
|
|
}
|
|
return hMenu;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* SetMenu (API)
|
|
*
|
|
* Sets the menu for the hwnd.
|
|
*
|
|
* History:
|
|
* 10-Mar-1996 ChrisWil Created.
|
|
\***************************************************************************/
|
|
|
|
|
|
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, SetMenu, HWND, hwnd, HMENU, hmenu)
|
|
BOOL SetMenu(
|
|
HWND hwnd,
|
|
HMENU hmenu)
|
|
{
|
|
return NtUserSetMenu(hwnd, hmenu, TRUE);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* LoadMenu (API)
|
|
*
|
|
* Loads the menu resource named by lpMenuName from the executable
|
|
* file associated by the module specified by the hInstance parameter. The
|
|
* menu is loaded only if it hasn't been previously loaded. Otherwise it
|
|
* retrieves a handle to the loaded resource. Returns NULL if unsuccessful.
|
|
*
|
|
* History:
|
|
* 04-05-91 ScottLu Fixed to work with client/server.
|
|
* 28-Sep-1990 mikeke from win30
|
|
\***************************************************************************/
|
|
|
|
HMENU CommonLoadMenu(
|
|
HINSTANCE hmod,
|
|
HANDLE hResInfo
|
|
)
|
|
{
|
|
HANDLE h;
|
|
PVOID p;
|
|
HMENU hMenu = NULL;
|
|
|
|
if (h = LOADRESOURCE(hmod, hResInfo)) {
|
|
|
|
if (p = LOCKRESOURCE(h, hmod)) {
|
|
|
|
hMenu = CreateMenuFromResource(p);
|
|
|
|
UNLOCKRESOURCE(h, hmod);
|
|
}
|
|
/*
|
|
* Win95 and Win3.1 do not free this resource; some 16 bit apps (chessmaster
|
|
* and mavis typing) require this for their ownerdraw menu stuff.
|
|
* For 32 bit apps, FreeResource is a nop anyway. For 16 bit apps,
|
|
* Wow frees the 32 bit resource (returned by LockResource16)
|
|
* in UnlockResource16; the actual 16 bit resource is freed when the task
|
|
* goes away.
|
|
*
|
|
* FREERESOURCE(h, hmod);
|
|
*/
|
|
}
|
|
|
|
return (hMenu);
|
|
}
|
|
|
|
|
|
FUNCLOG2(LOG_GENERAL, HMENU, WINAPI, LoadMenuA, HINSTANCE, hmod, LPCSTR, lpName)
|
|
HMENU WINAPI LoadMenuA(
|
|
HINSTANCE hmod,
|
|
LPCSTR lpName)
|
|
{
|
|
HANDLE hRes;
|
|
|
|
if (hRes = FINDRESOURCEA(hmod, (LPSTR)lpName, (LPSTR)RT_MENU))
|
|
return CommonLoadMenu(hmod, hRes);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
FUNCLOG2(LOG_GENERAL, HMENU, WINAPI, LoadMenuW, HINSTANCE, hmod, LPCWSTR, lpName)
|
|
HMENU WINAPI LoadMenuW(
|
|
HINSTANCE hmod,
|
|
LPCWSTR lpName)
|
|
{
|
|
HANDLE hRes;
|
|
|
|
if (hRes = FINDRESOURCEW(hmod, (LPWSTR)lpName, RT_MENU))
|
|
return CommonLoadMenu(hmod, hRes);
|
|
else
|
|
return NULL;
|
|
}
|
|
/***************************************************************************\
|
|
* InternalInsertMenuItem
|
|
*
|
|
* History:
|
|
* 09/20/96 GerardoB - Created
|
|
\***************************************************************************/
|
|
BOOL InternalInsertMenuItem (HMENU hMenu, UINT uID, BOOL fByPosition, LPCMENUITEMINFO lpmii)
|
|
{
|
|
return ThunkedMenuItemInfo(hMenu, uID, fByPosition, TRUE, (LPMENUITEMINFOW)lpmii, FALSE);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* ValidateMENUITEMINFO() -
|
|
* it converts and validates a MENUITEMINFO95 or a new-MENUITEMINFO-with-old-flags
|
|
* to a new MENUITEMINFO -- this way all internal code can assume one look for the
|
|
* structure
|
|
*
|
|
* History:
|
|
* 12-08-95 Ported from Nashville - jjk
|
|
* 07-19-96 GerardoB - Fixed up for 5.0
|
|
\***************************************************************************/
|
|
BOOL ValidateMENUITEMINFO(LPMENUITEMINFO lpmiiIn, LPMENUITEMINFO lpmii, DWORD dwAPICode)
|
|
{
|
|
BOOL fOldApp;
|
|
|
|
if (lpmiiIn == NULL) {
|
|
VALIDATIONFAIL(lpmiiIn);
|
|
}
|
|
|
|
/*
|
|
* In order to map the old flags to the new ones, we might have to modify
|
|
* the lpmiiIn structure. So we make a copy to avoid breaking anyone.
|
|
*/
|
|
fOldApp = (lpmiiIn->cbSize == SIZEOFMENUITEMINFO95);
|
|
UserAssert(SIZEOFMENUITEMINFO95 < sizeof(MENUITEMINFO));
|
|
RtlCopyMemory(lpmii, lpmiiIn, SIZEOFMENUITEMINFO95);
|
|
if (fOldApp) {
|
|
lpmii->cbSize = sizeof(MENUITEMINFO);
|
|
lpmii->hbmpItem = NULL;
|
|
} else if (lpmiiIn->cbSize == sizeof(MENUITEMINFO)) {
|
|
lpmii->hbmpItem = lpmiiIn->hbmpItem;
|
|
} else {
|
|
VALIDATIONFAIL(lpmiiIn->cbSize);
|
|
}
|
|
|
|
|
|
if (lpmii->fMask & ~MIIM_MASK) {
|
|
VALIDATIONFAIL(lpmii->fMask);
|
|
} else if ((lpmii->fMask & MIIM_TYPE)
|
|
&& (lpmii->fMask & (MIIM_FTYPE | MIIM_STRING | MIIM_BITMAP))) {
|
|
/*
|
|
* Don't let them mix new and old flags
|
|
*/
|
|
VALIDATIONFAIL(lpmii->fMask);
|
|
}
|
|
|
|
/*
|
|
* No more validation needed for Get calls
|
|
*/
|
|
if (dwAPICode == MENUAPI_GET) {
|
|
/*
|
|
* Map MIIM_TYPE for old apps doing a Get.
|
|
* Keep the MIIM_TYPE flag so we'll know this guy passed the old flags.
|
|
* GetMenuItemInfo uses lpmii->hbmpItem to determine if a bitmap
|
|
* was returned. So we NULL it out here. The caller is using the
|
|
* old flags so he shouldn't care about it.
|
|
*/
|
|
if (lpmii->fMask & MIIM_TYPE) {
|
|
lpmii->fMask |= MIIM_FTYPE | MIIM_BITMAP | MIIM_STRING;
|
|
lpmii->hbmpItem = NULL;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* Map MIIM_TYPE to MIIM_FTYPE
|
|
*/
|
|
if (lpmii->fMask & MIIM_TYPE) {
|
|
lpmii->fMask |= MIIM_FTYPE;
|
|
}
|
|
|
|
if (lpmii->fMask & MIIM_FTYPE) {
|
|
if (lpmii->fType & ~MFT_MASK) {
|
|
VALIDATIONFAIL(lpmii->fType);
|
|
}
|
|
/*
|
|
* If using MIIM_TYPE, Map MFT_BITMAP to MIIM_BITMAP
|
|
* and MFT_NONSTRING to MIIM_STRING.
|
|
* Old applications couldn't use string and bitmap simultaneously
|
|
* so setting one implies clearing the other.
|
|
*/
|
|
if (lpmii->fMask & MIIM_TYPE) {
|
|
if (lpmii->fType & MFT_BITMAP) {
|
|
/*
|
|
* Don't display a warning. A lot of shell menus hit this
|
|
* if (!fOldApp) {
|
|
* VALIDATIONOBSOLETE(MFT_BITMAP, MIIM_BITMAP);
|
|
* }
|
|
*/
|
|
lpmii->fMask |= MIIM_BITMAP | MIIM_STRING;
|
|
lpmii->hbmpItem = (HBITMAP)lpmii->dwTypeData;
|
|
lpmii->dwTypeData = 0;
|
|
} else if (!(lpmii->fType & MFT_NONSTRING)) {
|
|
/*
|
|
* Don't display a warning. A lot of shell menus hit this
|
|
* if (!fOldApp) {
|
|
* VALIDATIONOBSOLETE(MFT_STRING, MIIM_STRING);
|
|
* }
|
|
*/
|
|
lpmii->fMask |= MIIM_BITMAP | MIIM_STRING;
|
|
lpmii->hbmpItem = NULL;
|
|
}
|
|
} else if (lpmii->fType & MFT_BITMAP) {
|
|
/*
|
|
* Don't let them mix new and old flags
|
|
*/
|
|
VALIDATIONFAIL(lpmii->fType);
|
|
}
|
|
}
|
|
|
|
if ((lpmii->fMask & MIIM_STATE) && (lpmii->fState & ~MFS_MASK)){
|
|
VALIDATIONFAIL(lpmii->fState);
|
|
}
|
|
|
|
if (lpmii->fMask & MIIM_CHECKMARKS) {
|
|
if ((lpmii->hbmpChecked != NULL) && !GdiValidateHandle((HBITMAP)lpmii->hbmpChecked)) {
|
|
VALIDATIONFAIL(lpmii->hbmpChecked);
|
|
}
|
|
if ((lpmii->hbmpUnchecked != NULL) && !GdiValidateHandle((HBITMAP)lpmii->hbmpUnchecked)) {
|
|
VALIDATIONFAIL(lpmii->hbmpUnchecked);
|
|
}
|
|
}
|
|
|
|
if (lpmii->fMask & MIIM_SUBMENU) {
|
|
if ((lpmii->hSubMenu != NULL) && !VALIDATEHMENU(lpmii->hSubMenu)) {
|
|
VALIDATIONFAIL(lpmii->hSubMenu);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Warning: NULL lpmii->hbmpItem accepted as valid (or the explorer breaks)
|
|
*/
|
|
if (lpmii->fMask & MIIM_BITMAP) {
|
|
if ((lpmii->hbmpItem != HBMMENU_CALLBACK)
|
|
&& (lpmii->hbmpItem >= HBMMENU_MAX)
|
|
&& !GdiValidateHandle(lpmii->hbmpItem)) {
|
|
|
|
/*
|
|
* Compatibility hack
|
|
*/
|
|
if (((HBITMAP)LOWORD(HandleToUlong(lpmii->hbmpItem)) >= HBMMENU_MAX) || !IS_PTR(lpmii->hbmpItem)) {
|
|
VALIDATIONFAIL(lpmii->hbmpItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Warning: No dwTypeData / cch validation
|
|
*/
|
|
|
|
return TRUE;
|
|
|
|
VALIDATIONERROR(FALSE);
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* ValidateMENUINFO() -
|
|
*
|
|
* History:
|
|
* 07-22-96 GerardoB - Added header and Fixed up for 5.0
|
|
\***************************************************************************/
|
|
|
|
BOOL ValidateMENUINFO(LPCMENUINFO lpmi, DWORD dwAPICode)
|
|
{
|
|
if (lpmi == NULL) {
|
|
VALIDATIONFAIL(lpmi);
|
|
}
|
|
|
|
if (lpmi->cbSize != sizeof(MENUINFO)) {
|
|
VALIDATIONFAIL(lpmi->cbSize);
|
|
}
|
|
|
|
if (lpmi->fMask & ~MIM_MASK) {
|
|
VALIDATIONFAIL(lpmi->fMask);
|
|
}
|
|
|
|
/*
|
|
* No more validation needed for Get calls
|
|
*/
|
|
if (dwAPICode == MENUAPI_GET){
|
|
return TRUE;
|
|
}
|
|
|
|
if ((lpmi->fMask & MIM_STYLE) && (lpmi->dwStyle & ~MNS_VALID)) {
|
|
VALIDATIONFAIL(lpmi->dwStyle);
|
|
}
|
|
|
|
if (lpmi->fMask & MIM_BACKGROUND) {
|
|
if ((lpmi->hbrBack != NULL)
|
|
&& !GdiValidateHandle((HBRUSH)lpmi->hbrBack)) {
|
|
|
|
VALIDATIONFAIL(lpmi->hbrBack);
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
VALIDATIONERROR(FALSE);
|
|
}
|
|
/***************************************************************************\
|
|
* GetMenuInfo
|
|
*
|
|
* History:
|
|
* 07-22-96 GerardoB - Added header and Fixed up for 5.0
|
|
\***************************************************************************/
|
|
|
|
FUNCLOG2(LOG_GENERAL, BOOL, DUMMYCALLINGTYPE, GetMenuInfo, HMENU, hMenu, LPMENUINFO, lpmi)
|
|
BOOL GetMenuInfo(HMENU hMenu, LPMENUINFO lpmi)
|
|
{
|
|
PMENU pMenu;
|
|
|
|
if (!ValidateMENUINFO(lpmi, MENUAPI_GET)) {
|
|
return FALSE;
|
|
}
|
|
|
|
pMenu = VALIDATEHMENU(hMenu);
|
|
if (pMenu == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpmi->fMask & MIM_STYLE) {
|
|
lpmi->dwStyle = pMenu->fFlags & MNS_VALID;
|
|
}
|
|
|
|
if (lpmi->fMask & MIM_MAXHEIGHT) {
|
|
lpmi->cyMax = pMenu->cyMax;
|
|
}
|
|
|
|
if (lpmi->fMask & MIM_BACKGROUND) {
|
|
lpmi->hbrBack = KHBRUSH_TO_HBRUSH(pMenu->hbrBack);
|
|
}
|
|
|
|
if (lpmi->fMask & MIM_HELPID) {
|
|
lpmi->dwContextHelpID = pMenu->dwContextHelpId;
|
|
}
|
|
|
|
if (lpmi->fMask & MIM_MENUDATA) {
|
|
lpmi->dwMenuData = KERNEL_ULONG_PTR_TO_ULONG_PTR(pMenu->dwMenuData);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|