SHELL32!SHLoadPopupMenu函数分析之添加属性菜单项
SHELL32!SHLoadPopupMenu函数分析之添加属性菜单项
第一部分:
//
// user does not support pop-up only menu.
//
STDAPI_(HMENU) SHLoadPopupMenu(HINSTANCE hinst, UINT id)
{
HMENU hmenuParent = LoadMenu(hinst, MAKEINTRESOURCE(id));
if (hmenuParent)
{
HMENU hpopup = GetSubMenu(hmenuParent, 0);
RemoveMenu(hmenuParent, 0, MF_BYPOSITION);
DestroyMenu(hmenuParent);
return hpopup;
}
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;
}
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);
第二部分:
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;
}
第二部分:
typedef struct { // version 1
DWORD dwHelpID;
DWORD fType;
DWORD fState;
DWORD menuId;
WORD wResInfo;
WCHAR mtString[1];
} MENUITEMTEMPLATE2, *PMENUITEMTEMPLATE2;
1: kd> db 0x77a42b80 lpMenuTemplate对应的数据
77a42b80 01 00 04 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
77a42b90 00 00 00 00 81 00 00 00-00 00 00 00 00 00 00 00 ................
77a42ba0 00 00 00 00 00 00 00 00-80 00 50 00 26 00 72 00 ..........P.&.r.
77a42bb0 6f 00 70 00 65 00 72 00-74 00 69 00 65 00 73 00 o.p.e.r.t.i.e.s.
77a42bc0 00 00 00 00 00 00 00 00-01 00 04 00 00 00 00 00 ................
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;
}
第三部分:
1: kd> dv
lpMenuTemplate = 0x77a42b88
phMenu = 0x00faec48
wResInfo = 0x80
mftRtl = 0
str = ""
hMenu = 0x002e00b1 最终结果1
mii = struct tagMENUITEMINFOW
hSubMenu = 0x0009010f 最终结果2
1: kd> dt win32k!menu 0xbc694b74
+0x000 head : _PROCDESKHEAD
+0x014 fFlags : 0
+0x018 iItem : 0n0
+0x01c cAlloced : 8
+0x020 cItems : 1
+0x024 cxMenu : 0
+0x028 cyMenu : 0
+0x02c cxTextAlign : 0
+0x030 spwndNotify : (null)
+0x034 rgItems : 0xbc6979c4 tagITEM
+0x038 pParentMenus : (null)
+0x03c dwContextHelpId : 0
+0x040 cyMax : 0
+0x044 dwMenuData : 0
+0x048 hbrBack : (null)
+0x04c iTop : 0n0
+0x050 iMaxTop : 0n0
+0x054 dwArrowsOn : 0y00
1: kd> dx -id 0,0,89589d88 -r1 ((win32k!tagITEM *)0xbc6979c4)
((win32k!tagITEM *)0xbc6979c4) : 0xbc6979c4 [Type: tagITEM *]
[+0x000] fType : 0x800 [Type: unsigned int]
[+0x004] fState : 0x3 [Type: unsigned int]
[+0x008] wID : 0x0 [Type: unsigned int]
[+0x00c] spSubMenu : 0xbc694c2c [Type: tagMENU *]
[+0x010] hbmpChecked : 0x0 [Type: void *]
[+0x014] hbmpUnchecked : 0x0 [Type: void *]
[+0x018] lpstr : 0x0 [Type: unsigned short *]
[+0x01c] cch : 0x0 [Type: unsigned long]
[+0x020] dwItemData : 0x0 [Type: unsigned long]
[+0x024] xItem : 0x0 [Type: unsigned long]
[+0x028] yItem : 0x0 [Type: unsigned long]
[+0x02c] cxItem : 0x0 [Type: unsigned long]
[+0x030] cyItem : 0x0 [Type: unsigned long]
[+0x034] dxTab : 0x0 [Type: unsigned long]
[+0x038] ulX : 0x7fffffff [Type: unsigned long]
[+0x03c] ulWidth : 0x0 [Type: unsigned long]
[+0x040] hbmp : 0x0 [Type: HBITMAP__ *]
[+0x044] cxBmp : -1 [Type: int]
[+0x048] cyBmp : 0 [Type: int]
1: kd> dx -id 0,0,89589d88 -r1 ((win32k!tagMENU *)0xbc694c2c)
((win32k!tagMENU *)0xbc694c2c) : 0xbc694c2c [Type: tagMENU *]
[+0x000] head [Type: _PROCDESKHEAD]
[+0x014] fFlags : 0x1 [Type: unsigned long]
[+0x018] iItem : 0 [Type: int]
[+0x01c] cAlloced : 0x8 [Type: unsigned int]
[+0x020] cItems : 0x1 [Type: unsigned int]
[+0x024] cxMenu : 0x0 [Type: unsigned long]
[+0x028] cyMenu : 0x0 [Type: unsigned long]
[+0x02c] cxTextAlign : 0x0 [Type: unsigned long]
[+0x030] spwndNotify : 0x0 [Type: tagWND *]
[+0x034] rgItems : 0xbc696d24 [Type: tagITEM *]
[+0x038] pParentMenus : 0xbc693b2c [Type: tagMENULIST *]
[+0x03c] dwContextHelpId : 0x0 [Type: unsigned long]
[+0x040] cyMax : 0x0 [Type: unsigned long]
[+0x044] dwMenuData : 0x0 [Type: unsigned long]
[+0x048] hbrBack : 0x0 [Type: HBRUSH__ *]
[+0x04c] iTop : 0 [Type: int]
[+0x050] iMaxTop : 0 [Type: int]
[+0x054 ( 1: 0)] dwArrowsOn : 0x0 [Type: unsigned long]
1: kd> dx -id 0,0,89589d88 -r1 ((win32k!tagITEM *)0xbc696d24)
((win32k!tagITEM *)0xbc696d24) : 0xbc696d24 [Type: tagITEM *]
[+0x000] fType : 0x0 [Type: unsigned int]
[+0x004] fState : 0x0 [Type: unsigned int]
[+0x008] wID : 0x0 [Type: unsigned int]
[+0x00c] spSubMenu : 0x0 [Type: tagMENU *]
[+0x010] hbmpChecked : 0x0 [Type: void *]
[+0x014] hbmpUnchecked : 0x0 [Type: void *]
[+0x018] lpstr : 0xbc696fe4 : 0x50 [Type: unsigned short *]
[+0x01c] cch : 0xb [Type: unsigned long]
[+0x020] dwItemData : 0x0 [Type: unsigned long]
[+0x024] xItem : 0x0 [Type: unsigned long]
[+0x028] yItem : 0x0 [Type: unsigned long]
[+0x02c] cxItem : 0x0 [Type: unsigned long]
[+0x030] cyItem : 0x0 [Type: unsigned long]
[+0x034] dxTab : 0x0 [Type: unsigned long]
[+0x038] ulX : 0x7fffffff [Type: unsigned long]
[+0x03c] ulWidth : 0x0 [Type: unsigned long]
[+0x040] hbmp : 0x0 [Type: HBITMAP__ *]
[+0x044] cxBmp : -1 [Type: int]
[+0x048] cyBmp : 0 [Type: int]
1: kd> db 0xbc696fe4
bc696fe4 50 00 26 00 72 00 6f 00-70 00 65 00 72 00 74 00 P.&.r.o.p.e.r.t.
bc696ff4 69 00 65 00 73 00 00 00-55 48 5f 54 41 49 4c 00 i.e.s...UH_TAIL.
bc697004 ab ab ab ab ab ab ab ab-07 00 ca ca 00 00 00 00 ................
bc697014 00 00 00 00 3d 00 0f 00-07 00 ca 00 60 03 67 bc ....=.......`.g.
bc697024 60 03 67 bc 07 00 ca ca-07 00 ca ca 07 00 ca ca `.g.............
bc697034 07 00 ca ca 07 00 ca ca-07 00 ca ca 07 00 ca ca ................
bc697044 07 00 ca ca 07 00 ca ca-07 00 ca ca 07 00 ca ca ................
bc697054 07 00 ca ca 07 00 ca ca-07 00 ca ca 07 00 ca ca ................