The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: Jimg on March 24, 2008, 01:16:10 PM

Title: Activating menu items in an executing program
Post by: Jimg on March 24, 2008, 01:16:10 PM
Does anyone know how to enumerate the menu items in an executing dll?
I used to force the "auto arrange" toggle in the context menu for the desktop by doing
    IDM_TOGGLEAUTOARRANGE equ 7041h
    inv SendMessage,hParent,WM_COMMAND,IDM_TOGGLEAUTOARRANGE,0

where hParent is the handle of the parent of the syslistview for the desktop.
Apparently, sometime in the last two years or so, by some windows security or other update, the menu item in shell32.dll has been changed from 7041h to 7051h, at least on my xp sp2.

Rather than just hard coding it again I would prefer to track down the correct value in case of future updates.

I tried
    invoke GetModuleHandle,addr shell32dll
    mov hShell32,eax
    inv GetMenu,hShell32
but no luck.  If I try
    inv GetModuleFileName,hShell32,addr menubuf,99
I get the file name properly, so hShell32 is correct.

When I tried
    inv EnumResourceTypes,hShell32,EnumResTypeProc,0
I got some weird stuff.
When I tried
    inv EnumResourceNames,hShell32,soff("RT_MENU"),EnumResNameProc,0
I got nothing.




Title: Re: Activating menu items in an executing program
Post by: sinsi on March 25, 2008, 01:52:43 AM
GetMenu needs a hwnd, not a hmod. You could try LoadMenu but you need the menu name/id as well.
Title: Re: Activating menu items in an executing program
Post by: Jimg on March 25, 2008, 02:29:40 PM
I know the handle of the window I'm interested in, there were just too many trees in the way.

I get this by searching for "Progman", searching that window for the child called "SHELLDLL_defVIEW" (which will be the parent, saved in hParent), and searching this for a window called "SysListView32" (which is the actual listview you see on the desktop).

I can trigger the menu item by doing

    IDM_TOGGLEAUTOARRANGE equ 7051h
    invoke SendMessage,hParent,WM_COMMAND,IDM_TOGGLEAUTOARRANGE,0

However, I cannot get any information about the menu by

    invoke GetMenu,hParent

The
    invoke EnumResourceTypes,hShell32,EnumResTypeProc,0
   
which wants a module handle, returns "AVI","REGINST","TYPELIB", and "UIFILE" which didn't help at all.

The
    inv EnumResourceNames,hShell32,soff("RT_MENU"),EnumResNameProc,0
   
returned nothing.   
   


I got the 7051h value by using Resouce Hacker on Shell32.dll and searching for a menu with the string "Auto Arrange".  But I can't do this on the fly in the program.

And I'm out of ideas. 


Title: Re: Activating menu items in an executing program
Post by: Jimg on March 25, 2008, 03:49:59 PM
If anyone wants to try it, this is the code I use to get the handles-

.data?
    hShell32     dd ?
    hProgMan     dd ?
    hParent      dd ?
    hListView    dd ?
.data
    shell32dll   db "Shell32.DLL",0
    progman      db "Progman",0
    defview      db "SHELLDLL_defVIEW", 0
    syslistview  db "SysListView32", 0
.code

    invoke GetModuleHandle,addr shell32dll
    mov hShell32,eax

    invoke FindWindow,addr progman,0 ; search for desktop listview
    mov hProgMan,eax
    invoke FindWindowEx,eax, 0,addr defview, 0
    mov hParent,eax
    invoke FindWindowEx,eax, 0, addr syslistview, 0
    mov hListView,eax
Title: Re: Activating menu items in an executing program
Post by: ragdog on March 25, 2008, 05:15:18 PM
hi

Try this i hope thats help you


Progman          db "Progman",0
ProgramManager   db "Program Manager",0
SHELLDLL_DefView db "SHELLDLL_DefView",0
SysListView32    db "SysListView32",0
FolderView       db "FolderView",0

.data?
hndl DWORD ?

.code
start:
        invoke FindWindowEx, NULL, NULL, addr Progman, addr ProgramManager
        mov    hndl,eax
        invoke FindWindowEx, hndl, NULL, addr SHELLDLL_DefView, NULL
        mov    hndl,eax
        invoke FindWindowEx, hndl, NULL, addr SysListView32, addr FolderView
        mov    hndl,eax

        invoke IsWindowVisible, hndl
        .if eax == FALSE
            invoke ShowWindow, hndl, SW_SHOWNOACTIVATE
        .else
            invoke ShowWindow, hndl, SW_HIDE
        .endif
Title: Re: Activating menu items in an executing program
Post by: ragdog on March 25, 2008, 05:25:24 PM
or this

[attachment deleted by admin]
Title: Re: Activating menu items in an executing program
Post by: Jimg on March 25, 2008, 07:30:07 PM
Thank you, ragdog, that's very interesting.  I'll put it away for later.

I couldn't see how knowing the handle of "FolderView" helps me.  Could you explain this?

I looked through your program and couldn't find anything that helps with this problem, could you point out what you had in mind?
Title: Re: Activating menu items in an executing program
Post by: ragdog on March 25, 2008, 09:05:25 PM
i cannot help with your problem this is not my source

this source have i found on my partion
I knew only that I had somewhere


sorry

greets
ragdog
Title: Re: Activating menu items in an executing program
Post by: sinsi on March 25, 2008, 09:42:59 PM
Use the value RT_MENU instead of the string "RT_MENU" in EnumResourceNames.
Title: Re: Activating menu items in an executing program
Post by: Jimg on March 26, 2008, 12:45:59 AM
Quote from: sinsi on March 25, 2008, 09:42:59 PM
Use the value RT_MENU instead of the string "RT_MENU" in EnumResourceNames.
Doh!  Some days are just like that.   Still didn't give me anything, but at least it's correct now :red
Title: Re: Activating menu items in an executing program
Post by: sinsi on March 26, 2008, 01:30:30 AM
No error checking in this, but it works for me.

    include \masm32\include\masm32rt.inc
   
    .code

ern proc uses ebx hmod,lptype,lpname,lparam
    mov eax,lpname
    print str$(eax)," "
    invoke LoadMenu,hmod,lpname
    mov ebx,eax
    invoke GetMenuItemCount,ebx
    print str$(eax),13,10
    invoke DestroyMenu,ebx
    ret
ern endp

shell32dll db 'shell32.dll',0

start:
    invoke LoadLibrary,addr shell32dll
    mov ebx,eax
    invoke EnumResourceNames,ebx,RT_MENU,addr ern,0
    inkey
    invoke ExitProcess,0
end start

Title: Re: Activating menu items in an executing program
Post by: jj2007 on March 26, 2008, 09:32:22 AM
I tried to get the names of the enumerated menus, using Sinsi's code. Among the results are Briefcase and Printer - not sure if that does make any sense. I have commented out my attempts to use GetMenuItemInfo - the MSDN documentation is utterly confused.

include \masm32\include\masm32rt.inc

.data?
mt MENUITEMINFO <>
hShell32 dd ?

.data
    shell32dll   db "Shell32.DLL",0
;    progman      db "Progman",0
;    defview      db "SHELLDLL_defVIEW", 0
;    syslistview  db "SysListView32", 0
buffer db " - "
db 512 dup(0)
.code

ern proc uses ebx hmod,lptype,lpname,lparam
    mov eax, hShell32
    mov eax,lpname
    print str$(eax)," "
    invoke LoadMenu,hmod,lpname
    mov ebx,eax
;    mov mt.fMask, MIIM_FTYPE or MIIM_STRING
;    mov mt.fType, MIIM_STRING ;MFT_STRING
;    mrm mt.dwTypeData, offset buffer
;    mov mt.cch, 512
;    invoke GetMenuItemInfo, eax, 0, 1, addr mt
;    mov eax, mt.cch
    invoke GetMenuItemCount, ebx
    .if eax
print str$(eax), 9
invoke GetMenuString, ebx, 0, addr buffer, 512, MF_BYPOSITION
.if eax
print offset buffer
.endif
print " ", 13, 10
    .else
print str$(eax),13,10
    .endif
    invoke DestroyMenu,ebx
    ret
ern endp

start:
    mov mt.cbSize, sizeof mt
    invoke LoadLibrary,addr shell32dll
    invoke GetModuleHandle,addr shell32dll
    mov hShell32,eax
    mov ebx,eax
    invoke EnumResourceNames, ebx, RT_MENU, addr ern, 0
    inkey
    invoke ExitProcess,0
end start

Title: Re: Activating menu items in an executing program
Post by: Jimg on March 26, 2008, 02:32:54 PM
Thank you Sinsi.

I have no excuse other than my inability to read the api documentation.

for EnumResNameProc, it clearly says:
QuotelpszName
Points to a null-terminated string specifying the name of the resource for which the name is being enumerated.
So I was printing it out as a string using MessageBox.
It is actually an integer, not a pointer to a string, so the messagebox crashed without giving me any indication that EnumResNameProc was ever called or that any error had occured.  When I changed my original code to print out an integer, everything worked as I had originally intended.

Again, thanks for the clarification.
Title: Re: Activating menu items in an executing program
Post by: sinsi on March 27, 2008, 05:32:48 AM
Just to confuse things, there a 3 different resource names
QuoteIf IS_INTRESOURCE(x) is TRUE for lpszName or lpszType, x specifies the integer identifier of the given resource. Otherwise, it is a pointer to a null-terminated string. If the first character of the string is a pound sign (#), the remaining characters represent a decimal number that specifies the integer identifier of the resource. For example, the string "#258" represents the identifier 258.
So it can be
- an int (00000000-0000FFFF)
- an address of a string which has the name
- an address of a string which has the ascii of an int
How stupid is the last one?
Title: Re: Activating menu items in an executing program
Post by: Jimg on March 27, 2008, 04:55:40 PM
Okay, Thanks.  Now I've got to move onto other things.

If anyone's interested, here's my test code the find the menu item I wanted.

    include \masm32\include\masm32rt.inc

inv equ invoke 
.data
shell32dll  db "Shell32.DLL",0
debugprt    db "hand=%lx rname=%li mcount=%li id=%li string=<%s>",0
sfound      db "Id found = %li %lxh",0
buffx       db 200 dup (0)
buffx2      db 50 dup (0)
continueflg dd 1
hShell32    dd 0
IdFound     dd 0
stringwanted db "&Auto Arrange",0   ; menu string to search for
.code

GetMenuStuff proc lmh,rname
    local mcnt,scnt,menuid,sinx   
    .if continueflg
        inv GetMenuItemCount,lmh
        mov mcnt,eax
        .if sdword ptr mcnt>0
            push ebx
            mov ebx,0
            .repeat
                inv GetSubMenu,lmh,ebx
                mov scnt,eax
                inv GetMenuItemID,lmh,ebx
                mov menuid,eax
                inv GetMenuString,lmh,ebx,addr buffx2,49,MF_BYPOSITION
                .if eax>0
                    inv wsprintf,addr buffx,addr debugprt,lmh,rname,mcnt,menuid,addr buffx2
                    ;inv MessageBox,0,addr buffx,0,0
                    print addr buffx,13,10
                    inv lstrcmp,addr stringwanted,addr buffx2
                    .if eax==0
                        m2m IdFound,menuid
                        mov continueflg,0
                        .break
                    .endif   
                .endif
                .if scnt ; if there was a submenu
                    inv GetMenuStuff,scnt,rname
                    .break .if continueflg==0
                .endif
                inc ebx
            .until ebx==mcnt
            pop ebx
        .endif
.endif
ret
GetMenuStuff endp

EnumResNameProc proc hand,typ,rname,extra
    local lmh
    inv LoadMenu,hand,rname
    mov lmh,eax
    inv GetMenuStuff,lmh,rname       
    inv DestroyMenu,lmh
    mov eax,continueflg
ret
EnumResNameProc endp

start:
    ;invoke GetModuleHandle,addr shell32dll  ; when already loaded in a windows program.
    invoke LoadLibrary,addr shell32dll
    mov hShell32,eax
    inv EnumResourceNames,hShell32,RT_MENU,addr EnumResNameProc,0
    inv wsprintf,addr buffx,addr sfound,IdFound,IdFound
    print addr buffx,13,10
    inkey
    invoke ExitProcess,0
end start


I'm sure it could be done more efficiently, if anyone wants to play.
Title: Re: Activating menu items in an executing program
Post by: xandaz on August 11, 2010, 10:47:24 AM
   I think i'm having some trouble with IS_INTRESOURCE macro. I didn't find the macro anywhere. I'd like to know if it does something like this or if it's otherwize.

EnumResTypesProc PROC   hModule:DWORD,lpszType:DWORD,lpszName:DWORD,lParam:DWORD

   mov eax,lpszName
   cmp eax,0
   je ret_FALSE
   shr eax,16
   cmp ax,0
   jne name_is_string
; ITS_INTRESOURCE
  mov eax,TRUE
  ret
ret_FALSE:
   mov eax,FALSE
   ret

is it something like this?
EnumResTypesProc endp
Title: Re: Activating menu items in an executing program
Post by: Twister on August 11, 2010, 12:40:40 PM
This thread is from 2 years back. ::)

I am guessing that the OP is trying to make a plugin for an editor, or something of that sort. He is using EnumMenu..  [ Someone please correct me if I am wrong. ]
Title: Re: Activating menu items in an executing program
Post by: sinsi on August 11, 2010, 01:06:41 PM
Quote from: MSDNThis macro checks whether all bits except the least 16 bits are zero. When true, wInteger is an integer identifier for a resource. Otherwise it is typically a pointer to a string.
So values 0-FFFFh are integers, values 10000h and up are string addresses.
Title: Re: Activating menu items in an executing program
Post by: xandaz on August 12, 2010, 10:55:46 AM
    thanks sinsi. That's what i thought. I was experiencing some porblems but i fixed it. I didn't have anything to do with integer lpszType.
    Thanks a lot anyway.
   Bye and best regards from X.