Shoutbox

Pathcou - TrackPopupMenuEx - Printable Version

-Shoutbox (https://shoutbox.menthix.net)
+-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58)
+--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4)
+---- Forum: Scripting (/forumdisplay.php?fid=39)
+----- Forum: Plug-Ins (/forumdisplay.php?fid=28)
+------ Thread: Pathcou - TrackPopupMenuEx (/showthread.php?tid=46134)

Pathcou - TrackPopupMenuEx by TazDevil on 06-11-2005 at 02:33 PM

patchou,
why i cant hook on the API TrackPopupMenuEx in order to get the menu handle of the system tray APIS32 says (!think!) that the value is returned to MsgPlusH.dll


RE: Pathcou - TrackPopupMenuEx by absorbation on 06-11-2005 at 03:12 PM

Try e-mailing patchou personally as he is not active and he repleys more to e-mails ;)


RE: Pathcou - TrackPopupMenuEx by Dempsey on 06-11-2005 at 03:25 PM

do you mean the menu handle of the context menu of the contact list?    If so I've spoken to Patchou about it before and I can't rememeber what he said, I'll see if I've still got the email


RE: Pathcou - TrackPopupMenuEx by Stigmata on 06-11-2005 at 03:33 PM

yeh, ive spoken to patch about this before, he recommended using TrackPopupMenuEx, but as i was unable to do so, i did try subclassing the WM_INITMENUPOPUP msg, but i was unable to gain the handle of the popup...


if you make a break through taz, please contact me and tell me how you did it :D :) thanks :)


RE: Pathcou - TrackPopupMenuEx by Dempsey on 06-11-2005 at 03:34 PM

quote:
Originally posted by Stigmata
i did try subclassing the WM_INITMENUPOPUP msg, but i was unable to gain the handle of the popup...
yea he said MSN doesnt send a WM_CONTEXT message
RE: Pathcou - TrackPopupMenuEx by TazDevil on 06-11-2005 at 03:41 PM

I am always talking about the system tray menu

i am not tryign to hook or subclass on the proc to get the menu handle because the way TrackPopupMenuEx is called it does not notify the wnd about WM_INITMENU etc..etc...

so the only way to het the menu handle is to hook on the actuall API to get the input arguments to the API, BUT i cannot hook on the TrackPopupMenuEx API, which is the BEST way. (that is what i am talking about MsgPlusH.dll that stops the hooking procedure)

instead i am hooking on the LoadMenuA API to get the result of the API to get the menu which is successful...

see the picture


RE: Pathcou - TrackPopupMenuEx by Dempsey on 06-11-2005 at 04:03 PM

so if you are already sucessfully doing it it an alternate way, why do you want to hook the tracppopupmenu call?


RE: Pathcou - TrackPopupMenuEx by TazDevil on 06-11-2005 at 04:07 PM

because it is most appropriate !!! to do it there
and plus prevents me for no actuall reason...

anyway if i did it there i could also get the menucommand once the menu was selected... the result of TrackP...

now i am using a detour that is not quite reliable
Hope it answered your q :D


RE: Pathcou - TrackPopupMenuEx by Dempsey on 06-11-2005 at 04:19 PM

ah right yea, so atm you can add the menu but not get the callback from it


RE: Pathcou - TrackPopupMenuEx by TazDevil on 06-11-2005 at 04:27 PM

no i get the callback, the menu is working.
but i get the menu command using WM_LBUTTONUP which is not very reliable


RE: Pathcou - TrackPopupMenuEx by Stigmata on 06-11-2005 at 04:42 PM

WM_COMMAND?


RE: Pathcou - TrackPopupMenuEx by TazDevil on 06-11-2005 at 05:26 PM

nope
TrackPopupMenuEx is called with TPM_NONOTIFY | TPM_RETURNCMD flags which
TPM_NONOTIFY -> If this flag is set, the function does not send notification messages when the user clicks on a menu item.
TPM_RETURNCMD -> If this flag is set, the function returns the menu item identifier of the user's selection in the return value.

so it does not send the WM_COMMAND message


RE: Pathcou - TrackPopupMenuEx by TazDevil on 06-14-2005 at 04:58 PM

Ok, i have made some more research... on this.

If i set a global hook, i can catch the TrackPopupMenu message, but the dll, gets loaded to all the process threads already running and this is not wanted...

is there another way to hook the entire process (all its threads) without hooking on other processes ???


RE: Pathcou - TrackPopupMenuEx by Patchou on 06-14-2005 at 08:28 PM

To answer your first question (and your email), my guess is that you cannot subclass TrackPopupMenuEx() when Plus! is loaded because of the way you're searching for the function location in the import table.

Using PIMAGE_THUNK_DATA.u1.Function, works fine as long as you're the only one who tries to subclass a function. As Messenger Plus! replaces the function pointer for its own, your search returns nothing and your subclass fails. To prevent that from happening, I suggest that you simply search for the function based on its name and not its address in memory.

Getting the name of an imported function is simple. Messenger Plus! does it this way:

code:
PIMAGE_THUNK_DATA pThunk
  = (PIMAGE_THUNK_DATA)( (PBYTE) hmodCaller + pImportDesc->FirstThunk );

//... iterate every function

PIMAGE_IMPORT_BY_NAME pImportName
  = (PIMAGE_IMPORT_BY_NAME)((PBYTE)hmodCaller + pThunkName->u1.AddressOfData);

if(!(IMAGE_SNAP_BY_ORDINAL(pThunkName->u1.Ordinal)) && pImportName->Name)
{
   /** Add code to make sure this is a pointer to a string **/

   /** Compare pImportName->Name to the known name of the function. If there's a match, proceed with the subclass like you do by searching with a pointer, however, make sure you chain the subclass properly by getting the current function address from the table and not the original function pointer. **/
}


Hope it helps :)
Patchou
RE: Pathcou - TrackPopupMenuEx by TheBlasphemer on 06-14-2005 at 09:22 PM

This is what I use in StuffPlug:

code:
void *HookImportedFunction(const char *Dll, const char *FuncName, int Ordinal, void *Function)
{
    DWORD oldProtect;
    void *PrevValue=0;

    DWORD image_base = (DWORD)GetModuleHandle(NULL);
    IMAGE_DOS_HEADER *idh = (IMAGE_DOS_HEADER *)image_base;
    IMAGE_FILE_HEADER *ifh = (IMAGE_FILE_HEADER *)(image_base +
        idh->e_lfanew + sizeof(DWORD));
    IMAGE_OPTIONAL_HEADER *ioh = (IMAGE_OPTIONAL_HEADER *)((DWORD)(ifh) +
        sizeof(IMAGE_FILE_HEADER));
    IMAGE_IMPORT_DESCRIPTOR *iid = (IMAGE_IMPORT_DESCRIPTOR *)(image_base +
        ioh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

    VirtualProtect((LPVOID)(image_base +
        ioh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress),
        ioh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size, PAGE_READWRITE,
        &oldProtect);

    while(iid->Name)
    {
        if(lstrcmpiA(Dll, (char *)(image_base + iid->Name)) == 0)
        {
            //trace_printf("Found descriptor: %s\n", dhook->name);
            IMAGE_THUNK_DATA * pThunk = (IMAGE_THUNK_DATA *)
                ((DWORD)iid->OriginalFirstThunk + image_base);
            IMAGE_THUNK_DATA * pThunk2 = (IMAGE_THUNK_DATA *)
                ((DWORD)iid->FirstThunk + image_base);
            while(pThunk->u1.AddressOfData)
            {
                char * name = 0;
                int ordinal;
                // Imported by ordinal only:
                if(pThunk->u1.Ordinal & 0x80000000)
                    ordinal = pThunk->u1.Ordinal & 0xffff;
                else    // Imported by name, with ordinal hint
                {
                    IMAGE_IMPORT_BY_NAME * pname = (IMAGE_IMPORT_BY_NAME *)
                        ((DWORD)pThunk->u1.AddressOfData + image_base);
                    ordinal = pname->Hint;
                    name = (char *)pname->Name;
                }

                if(name != 0 && FuncName && strcmp(name, FuncName) == 0)
                {
                    //trace_printf("Found entry name: %s\n", ehook->name);
                    PrevValue = (void*)pThunk2->u1.Function;
                    pThunk2->u1.Function = (DWORD)Function;
                }
                else if(ordinal == Ordinal)
                {
                    //trace_printf("Found entry ordinal: %s\n", ehook->name);
                    PrevValue = (void*)pThunk2->u1.Function;
                    pThunk2->u1.Function = (DWORD)Function;
                }

                pThunk++;
                pThunk2++;
            }
        }
        iid++;
    }
    return PrevValue;
}


THANKS A MILLION by TazDevil on 06-15-2005 at 06:38 AM

THANKS A MILLION !!!! (Patchou  + TB)

i have fixed it now, and Patchou was right

quote:
Using PIMAGE_THUNK_DATA.u1.Function, works fine as long as you're the only one who tries to subclass a function. As Messenger Plus! replaces the function pointer for its own, your search returns nothing and your subclass fails. To prevent that from happening, I suggest that you simply search for the function based on its name and not its address in memory.

And life (development) goes on...


I have one more question for Patchou or anyone who can answer for the moment.

If i have the option Open Messenger Window on Messenger start OFF, then the plugin is not loaded, on startup but after a small delay, which spoils everything with my system tray modifs.

From what i read in a post, and if i understand well, the MsgPlusLoader.dll searches for the Messenger window in order to hook... wouldn;t be the same if it searched for the hidden window of the tray in order to hook so that the plugins get loaded immediatelly ???
or is there another reason for the delay ?
RE: Pathcou - TrackPopupMenuEx by RaceProUK on 06-15-2005 at 07:29 PM

quote:
Originally posted by Patchou
code:
/* stuff */

quote:
Originally posted by TheBlasphemer
code:
/* stuff */

Nicked!

Actually, this will help me a lot in the future. Looks plenty clearer than the examples I've seen on the Internet.
RE: Pathcou - TrackPopupMenuEx by TazDevil on 06-15-2005 at 11:10 PM

Heh, ask a you shall receive !!! <- that is my moto :)

these guys are really good...

it would be much easier for vb developers thought if patchou would manually send the WM_INITMENU, and WM_COMMAND on menu start and end so that noone has to get in the trable of hooking on anything and everything to get things done in his way (like me :))

taz.


RE: Pathcou - TrackPopupMenuEx by Patchou on 06-16-2005 at 04:48 PM

Hey Taz,

I'm glad to see the code was of some help to you. Messenger Plus! does search for Messenger windows and it actually also searches for the systray one. However, in order to prevent everythign to be initialised too soon or for no reason, when the systray window is created, Messenger Plus! waits a couple of seconds for one of the visible windows of Messenger to be created. If none is created before 5 or 6 seconds, everything is initialised and the plugins are loaded at the same time.

I understand this may not be the best thing for your plugin but for everything else, that's one of the things that insures that Messenger Plus! does not causes problems with Messenger :).


RE: Pathcou - TrackPopupMenuEx by TazDevil on 06-17-2005 at 01:00 AM

I see your point, there... it would be nice to bypass this thou, but since it is a minor detail i can leave with it...

It just occured to me !!! How do you diferentiate between different menus [status menu, contact context menu, etc], in order to add your own items. i didn't have a problem with the tray as there is only just one menu...

By just catching the TrackPopupMenuEx API is not enough for differentiating them, as all menus are childs of the contact list, things get created and destroyed all the time, so you dont have a contant handle,
And you do not catch the LoadMenu API [that 1 argument is actually the menu resource id] as i could hook it before changeing the hooking procedure...

So the only way i can think of is comparing the 1 menuitem's command ID to see which menu it is ??? i am i right here ???
Basically i cannot think of anything else :)


RE: Pathcou - TrackPopupMenuEx by Patchou on 06-17-2005 at 05:44 AM

Well, you guessed itcorrectly my friend... when a popup menu is displayed, Messenger Plus! searches for known menu IDs and if it finds one or two, then it assumes that this is the menu it's been looking for :).


RE: Pathcou - TrackPopupMenuEx by TazDevil on 06-17-2005 at 08:45 AM

Messenger, MSN Messenger at least, as i said before, things get loaded and destroyed, regurding menus, so maybe you could remove the unsertainty by catching the LoadMenuA api, which is sent before every TrackPo..., to see which resource gets loaded every time, and catch the menu handle, and build from thereon

But i guess you would figure this out, way before !!!
(it is just a suggestion, not that i had any problems so far with Plus menu addons...:D )


RE: Pathcou - TrackPopupMenuEx by RaceProUK on 06-17-2005 at 01:55 PM

If it works the way it currently works, why change it?


RE: Pathcou - TrackPopupMenuEx by TazDevil on 06-17-2005 at 02:27 PM

Well i said that if he has a hard time doing it (finding which is which there is another way to do, i didn't say he should change it)

THink this 2 versions of MSN 6, 7, + i don;t know how may version it supports for Windows Messenger...

Now think of all the menu possibilites + time consumed to check for a couple of items to is which is which and after all if someone else messes with it everything gets worse

Plus all the different (i dont know) command ids every version has
Consider how much code all these need...

On the other hand if you know which resource is to be loaded for every version on msn, it is quicker and you skip some time consuming loops

But then again i could be wrong right ? ;)