mirror of https://github.com/lianthony/NT4.0
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.
754 lines
22 KiB
754 lines
22 KiB
/****************************** Module Header ******************************\
|
|
*
|
|
* Module Name: clmenu.c
|
|
*
|
|
* Copyright (c) 1985-92, 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;
|
|
long 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.
|
|
*/
|
|
if ((menuFlags & MFT_OWNERDRAW)
|
|
&& (GetClientInfo()->dwTIFlags & TIF_16BIT)) {
|
|
lpmenuText = (LPWSTR)(*(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);
|
|
#ifdef MEMPHIS_MENUS
|
|
mii.fMask = MIIM_ID | MIIM_STATE | MIIM_FTYPE;
|
|
if ( lpmenuText )
|
|
mii.fMask |= MIIM_STRING;
|
|
#else
|
|
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
|
|
#endif // MEMPHIS_MENUS
|
|
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 = (DWORD) lpmenuText;
|
|
lpmenuText = 0;
|
|
}
|
|
mii.dwTypeData = (LPWSTR) lpmenuText;
|
|
mii.cch = (UINT)-1;
|
|
mii.wID = menuId;
|
|
#ifdef MEMPHIS_MENUS
|
|
mii.hbmpItem = NULL;
|
|
#endif // MEMPHIS_MENUS
|
|
if (!NtUserThunkedMenuItemInfo(hMenu, MFMWFP_NOITEM, TRUE, TRUE,
|
|
&mii, lpmenuText ? &str : NULL, FALSE)) {
|
|
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)
|
|
{
|
|
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);
|
|
#ifdef MEMPHIS_MENUS
|
|
mii.fMask = MIIM_ID | MIIM_STATE | MIIM_FTYPE ;
|
|
#else
|
|
mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
|
|
#endif // MEMPHIS_MENUS
|
|
|
|
mii.fType = lpMenuTemplate->fType;
|
|
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);
|
|
}
|
|
#ifdef MEMPHIS_MENUS
|
|
if ( lpMenuTemplate->mtString[0] ) {
|
|
lpmenuText = lpMenuTemplate->mtString;
|
|
mii.fMask |= MIIM_STRING;
|
|
} else
|
|
lpmenuText = NULL;
|
|
#else
|
|
lpmenuText = lpMenuTemplate->mtString[0] ?
|
|
lpMenuTemplate->mtString : NULL;
|
|
#endif // MEMPHIS_MENUS
|
|
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 = (DWORD) mii.dwTypeData;
|
|
mii.dwTypeData = 0;
|
|
}
|
|
|
|
if (wResInfo & MFR_POPUP) {
|
|
mii.fMask |= MIIM_SUBMENU;
|
|
lpMenuTemplate = MenuLoadChicagoTemplates(lpMenuTemplate,
|
|
&hSubMenu, MFR_POPUP);
|
|
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;
|
|
#ifdef MEMPHIS_MENUS
|
|
mii.hbmpItem = NULL;
|
|
#endif // MEMPHIS_MENUS
|
|
if (!NtUserThunkedMenuItemInfo(hMenu, MFMWFP_NOITEM, TRUE, TRUE,
|
|
&mii, &str, FALSE)) {
|
|
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 *)&hMenu);
|
|
break;
|
|
|
|
case 1:
|
|
MenuLoadChicagoTemplates((PMENUITEMTEMPLATE2)lpMenuTemplate, (HMENU *)&hMenu, 0);
|
|
break;
|
|
}
|
|
return hMenu;
|
|
}
|
|
|
|
/***************************************************************************\
|
|
* SetMenu (API)
|
|
*
|
|
* Sets the menu for the hwnd.
|
|
*
|
|
* History:
|
|
* 10-Mar-1996 ChrisWil Created.
|
|
\***************************************************************************/
|
|
|
|
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);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
HMENU WINAPI LoadMenuW(
|
|
HINSTANCE hmod,
|
|
LPCWSTR lpName)
|
|
{
|
|
HANDLE hRes;
|
|
|
|
if (hRes = FINDRESOURCEW(hmod, (LPWSTR)lpName, RT_MENU))
|
|
return CommonLoadMenu(hmod, hRes);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef MEMPHIS_MENUS
|
|
//-----------------------------------------------------------------------------
|
|
// MIIOneWayConvert() -
|
|
//
|
|
// converts 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
|
|
//
|
|
// returns TRUE if structure is a valid 95 or 96 size; FALSE otherwise
|
|
// History:
|
|
// 11-8-95 Ported from Nashville - jjk
|
|
//-----------------------------------------------------------------------------
|
|
BOOL MIIOneWayConvert(LPMENUITEMINFOW lpmiiIn, LPMENUITEMINFOW lpmiiOut)
|
|
{
|
|
if (lpmiiIn->cbSize == sizeof(MENUITEMINFO))
|
|
lpmiiOut->hbmpItem = lpmiiIn->hbmpItem;
|
|
else if (lpmiiIn->cbSize == SIZEOFMENUITEMINFO95)
|
|
lpmiiOut->hbmpItem = NULL;
|
|
else
|
|
return(FALSE);
|
|
|
|
lpmiiOut->cbSize = sizeof(MENUITEMINFO);
|
|
lpmiiOut->fMask = lpmiiIn->fMask;
|
|
|
|
lpmiiOut->fState = lpmiiIn->fState;
|
|
lpmiiOut->wID = lpmiiIn->wID;
|
|
lpmiiOut->hSubMenu = lpmiiIn->hSubMenu;
|
|
lpmiiOut->hbmpChecked = lpmiiIn->hbmpChecked;
|
|
lpmiiOut->hbmpUnchecked = lpmiiIn->hbmpUnchecked;
|
|
lpmiiOut->dwItemData = lpmiiIn->dwItemData;
|
|
lpmiiOut->dwTypeData = lpmiiIn->dwTypeData;
|
|
lpmiiOut->cch = lpmiiIn->cch;
|
|
lpmiiOut->fType = lpmiiIn->fType;
|
|
|
|
if (lpmiiIn->fMask & MIIM_TYPE) {
|
|
//
|
|
// convert MFT_BITMAP to MIIM_BITMAP
|
|
// and !MFT_NONSTRING to MIIM_STRING
|
|
//
|
|
// NOTE: we leave MFT_BITMAP and MFT_STRING in the struct so the
|
|
// validation layer can see them and put up a warning saying
|
|
// 'obsolete flags' -- they are not actually used anywhere;
|
|
// all internal code now keys off of MIIM_BITMAP and MIIM_STRING
|
|
//
|
|
if (lpmiiIn->fType & MFT_BITMAP) {
|
|
lpmiiOut->fMask |= MIIM_BITMAP;
|
|
lpmiiOut->hbmpItem = (HBITMAP)lpmiiIn->dwTypeData;
|
|
} else if (!(lpmiiIn->fType & MFT_NONSTRING)) {
|
|
lpmiiOut->fMask |= MIIM_STRING;
|
|
}
|
|
|
|
lpmiiOut->fMask |= MIIM_FTYPE;
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ValidateMENUITEMINFO() -
|
|
// Validates the MII structure.
|
|
// Note: This does not validate the USER objects like HMENUs the way Nashville
|
|
// does because these will be validated and locked in the Kernel.
|
|
//
|
|
// History:
|
|
// 12-8-95 Ported from Nashville - jjk
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOL ValidateMENUITEMINFO(LPMENUITEMINFOW lpmii, WORD wAPICode)
|
|
{
|
|
MENUITEMINFO mii;
|
|
|
|
#define ERR_StrOld "USER: MENUITEMINFO: MFT_STRING obsolete; use MIIM_STRING instead"
|
|
#define ERR_BmpOld "USER: MENUITEMINFO: MFT_BITMAP obsolete; use MIIM_BITMAP instead"
|
|
#define ERR_Invalid "USER: MENUITEMINFO: Invalid %s"
|
|
#define ERR_Size "Invalid MENUITEMINFO Size cbSize: %04X"
|
|
#define ERR_Mask "Invalid MENUITEMINFO Mask fMask: %04X"
|
|
#define ERR_Type "Invalid MENUITEMINFO type Flags fType: %04X"
|
|
#define ERR_String "Invalid MENUITEMINFO String dwTypeData: %04X:%04X"
|
|
#define ERR_State "Invalid MENUITEMINFO State Flags fState: %04X"
|
|
#define ERR_Bitmap "Invalid MENUITEMINFO Bitmap: %04X"
|
|
#define ERR_Submenu "Invalid MENUITEMINFO Sub Menu: %04X"
|
|
#define ERR_CheckMark "Invalid MENUITEMINFO Check Mark: %04X"
|
|
|
|
|
|
if (!lpmii) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpmii->cbSize != sizeof(MENUITEMINFO)) {
|
|
RIPMSG1(RIP_WARNING, ERR_Size, lpmii->cbSize);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Validate fMask
|
|
//
|
|
if (lpmii->fMask & ~MIIM_MASK) {
|
|
RIPMSG1(RIP_WARNING, ERR_Mask, lpmii->fMask);
|
|
return FALSE;
|
|
}
|
|
|
|
// No validation needed for MIIM_ID, MIIM_DATA
|
|
if (wAPICode == MENUAPI_GET)
|
|
return TRUE;
|
|
|
|
if (lpmii->fMask & MIIM_FTYPE) {
|
|
#ifdef DEBUG
|
|
if (lpmii->fType & MFT_BITMAP)
|
|
;//RIPMSG0(RIP_WARNING, ERR_BmpOld);
|
|
if (lpmii->fType & MFT_STRING)
|
|
;//RIPMSG0(RIP_WARNING, ERR_StrOld);
|
|
#endif
|
|
|
|
if (lpmii->fType & ~MFT_MASK) {
|
|
RIPMSG1(RIP_WARNING, ERR_Type, lpmii->fType);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (lpmii->fMask & MIIM_STATE){
|
|
if (lpmii->fState & ~MFS_MASK) {
|
|
RIPMSG1(RIP_WARNING, ERR_State, lpmii->fState);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
if (lpmii->fMask & MIIM_CHECKMARKS) {
|
|
if (lpmii->hbmpChecked && !GdiValidateHandle((HBITMAP)lpmii->hbmpChecked)) {
|
|
RIPMSG1(RIP_WARNING, ERR_CheckMark, lpmii->hbmpChecked);
|
|
return(FALSE);
|
|
}
|
|
if (lpmii->hbmpUnchecked && !GdiValidateHandle((HBITMAP)lpmii->hbmpUnchecked)) {
|
|
RIPMSG1(RIP_WARNING, ERR_CheckMark, lpmii->hbmpUnchecked);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
if (lpmii->fMask & MIIM_SUBMENU) {
|
|
if (lpmii->hSubMenu && !VALIDATEHMENU(lpmii->hSubMenu)) {
|
|
RIPMSG1(RIP_WARNING, ERR_Submenu, lpmii->hSubMenu);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
if (lpmii->fMask & MIIM_STRING){
|
|
if (!lpmii->dwTypeData) {
|
|
//TODO: This slows down stress way too much.. jjk
|
|
; //RIPMSG2(RIP_WARNING, ERR_String, HIWORD(lpmii->dwTypeData), LOWORD(lpmii->dwTypeData));
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
if (lpmii->fMask & MIIM_BITMAP) {
|
|
HBITMAP hbmp = lpmii->hbmpItem;
|
|
if ((hbmp != HBMMENU_CALLBACK) && (hbmp >= HBMMENU_MAX) && !GdiValidateHandle((HBITMAP)hbmp)) {
|
|
RIPMSG1(RIP_WARNING, ERR_Bitmap, hbmp);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
mii;
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL GetMenuItemInfoInternal(HMENU hMenu, UINT uID, BOOL fByPosition,
|
|
LPMENUITEMINFO lpInfo)
|
|
{
|
|
PITEM pItem;
|
|
PMENU pMenu;
|
|
|
|
if ( lpInfo->cbSize != sizeof (MENUITEMINFO)) {
|
|
RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, "GetMenuItemInfo, bad size\n");
|
|
return FALSE;
|
|
}
|
|
|
|
pMenu = VALIDATEHMENU(hMenu);
|
|
|
|
if (pMenu == NULL)
|
|
return FALSE;
|
|
|
|
// Find out where the item we are modifying is.
|
|
pItem = MNLookUpItem(pMenu, uID, fByPosition, &pMenu);
|
|
|
|
if (pItem == NULL)
|
|
return FALSE;
|
|
|
|
if (lpInfo->fMask & MIIM_STATE)
|
|
lpInfo->fState = pItem->fState & MFS_MASK;
|
|
|
|
if (lpInfo->fMask & MIIM_ID)
|
|
lpInfo->wID = pItem->wID;
|
|
|
|
if ( (lpInfo->fMask & MIIM_SUBMENU) && (pItem->spSubMenu) ) {
|
|
lpInfo->hSubMenu = PtoH(REBASEPTR(pMenu, pItem->spSubMenu));
|
|
} else {
|
|
lpInfo->hSubMenu = NULL;
|
|
}
|
|
|
|
if (lpInfo->fMask & MIIM_CHECKMARKS) {
|
|
lpInfo->hbmpChecked = pItem->hbmpChecked;
|
|
lpInfo->hbmpUnchecked= pItem->hbmpUnchecked;
|
|
}
|
|
|
|
if (lpInfo->fMask & MIIM_DATA) {
|
|
lpInfo->dwItemData = pItem->dwItemData;
|
|
}
|
|
|
|
if (lpInfo->fMask & MIIM_FTYPE) {
|
|
lpInfo->fType = pItem->fType & MFT_MASK;
|
|
}
|
|
|
|
|
|
if ( lpInfo->fMask & MIIM_BITMAP) {
|
|
if (pItem->hbmp) {
|
|
lpInfo->hbmpItem = pItem->hbmp;
|
|
}
|
|
}
|
|
|
|
if ( lpInfo->fMask & MIIM_STRING) {
|
|
if ((lpInfo->cch) && (pItem->lpstr)) {
|
|
int cch;
|
|
|
|
cch = min(lpInfo->cch - 1, pItem->cch);
|
|
#if IS_ANSI
|
|
cch = WCSToMB(REBASEPTR(pMenu, pItem->lpstr), pItem->cch,
|
|
&(lpInfo->dwTypeData), cch, FALSE);
|
|
lpInfo->dwTypeData[cch] = '\0';
|
|
#else
|
|
wcsncpy(lpInfo->dwTypeData, (LPWSTR)REBASEPTR(pMenu, pItem->lpstr), cch);
|
|
lpInfo->dwTypeData[cch] = 0;
|
|
#endif
|
|
lpInfo->cch = cch;
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
#endif // MEMPHIS_MENUS
|
|
|
|
#ifdef MEMPHIS_MENU_WATERMARKS
|
|
BOOL ValidateMENUINFO(LPCMENUINFO lpmi, WORD wAPICode)
|
|
{
|
|
#define ERR_INVALID "USER: MENUINFO: Invalid"
|
|
#define ERR_SIZE "Size cbSize: %04X"
|
|
#define ERR_MASK "Mask fMask: %04X"
|
|
#define ERR_BRUSH "Brush hbrBack: %04X"
|
|
#define ERR_STYLE "Style dwStyle: %08X"
|
|
if (!lpmi) {
|
|
RIPMSG0( RIP_WARNING, ERR_INVALID );
|
|
return FALSE;;
|
|
}
|
|
|
|
if (lpmi->cbSize != sizeof(MENUINFO)) {
|
|
RIPMSG1( RIP_WARNING, ERR_SIZE, lpmi->cbSize);
|
|
return FALSE;;
|
|
}
|
|
|
|
//
|
|
// Validate fMask
|
|
//
|
|
if (lpmi->fMask & ~MIM_MASK) {
|
|
RIPMSG1( RIP_WARNING, ERR_MASK, lpmi->fMask);
|
|
return FALSE;
|
|
}
|
|
|
|
// No validation needed for MIIM_ID, MIIM_DATA
|
|
if (wAPICode == MENUAPI_GET){
|
|
return TRUE;
|
|
}
|
|
|
|
if ((lpmi->fMask & MIM_STYLE) && (lpmi->dwStyle & ~MNS_VALID)) {
|
|
RIPMSG1(RIP_WARNING, ERR_STYLE, lpmi->dwStyle);
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpmi->fMask & MIM_BACKGROUND) {
|
|
if (lpmi->hbrBack && !GdiValidateHandle((HBRUSH)lpmi->hbrBack)) {
|
|
RIPMSG1(RIP_WARNING, ERR_BRUSH, lpmi->hbrBack);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL GetMenuInfo(HMENU hMenu, LPMENUINFO lpmi)
|
|
{
|
|
PMENU pMenu;
|
|
|
|
if (!lpmi) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (lpmi->cbSize != sizeof(MENUINFO)) {
|
|
return FALSE;
|
|
}
|
|
|
|
pMenu = VALIDATEHMENU(hMenu);
|
|
|
|
if (lpmi->fMask & MIM_STYLE)
|
|
lpmi->dwStyle = TestMF(pMenu, MFNOCHECK) ? MNS_NOCHECK : 0;
|
|
|
|
//Once Scrolling menus are in place
|
|
//if (lpmi->fMask & MIM_MAXHEIGHT)
|
|
// lpmi->cyMax = MAKELONG(pMenu->cyMax, 0);
|
|
|
|
if (lpmi->fMask & MIM_BACKGROUND)
|
|
lpmi->hbrBack = pMenu->hbrBack;
|
|
|
|
//if (lpmi->fMask & MIM_HELPID)
|
|
// lpmi->dwContextHelpID = pMenu->dwContextHelpID;
|
|
|
|
//if (lpmi->fMask & MIM_MENUDATA)
|
|
// lpmi->dwMenuData = pMenu->dwMenuData;
|
|
|
|
return(TRUE);
|
|
}
|
|
#endif // MEMPHIS_MENU_WATERMARKS
|