[Question] Internal commans handling
Moderators: Hacker, petermad, Stefan2, white
[Question] Internal commans handling
2 Ghisler:
How does TC handle internal commands?
It's possible to make TC do something with finding a window of TTOTAL_CMD class and sending a WM_COPYDATA message to it.
During work on universal plugin interface, I managed to take over TTOTAL_CMD's WindowProc. And, surprise, it doesn't get any WM_COPYDATA messages.
Could you please tell what's happening with them?
How does TC handle internal commands?
It's possible to make TC do something with finding a window of TTOTAL_CMD class and sending a WM_COPYDATA message to it.
During work on universal plugin interface, I managed to take over TTOTAL_CMD's WindowProc. And, surprise, it doesn't get any WM_COPYDATA messages.
Could you please tell what's happening with them?
- majkinetor !
- Power Member
- Posts: 1580
- Joined: 2006-01-18, 07:56 UTC
- Contact:
Do you receive msg for calling comamnd (1075) ?
Anyway your code is probably wrong as I can catch WM_COPYDATA
Check out the screenshot:
Image: http://img265.imageshack.us/img265/1817/clipse5.png
I recorder this with TC open and using Favmenu to set the folder.
Anyway your code is probably wrong as I can catch WM_COPYDATA
Check out the screenshot:
Image: http://img265.imageshack.us/img265/1817/clipse5.png
I recorder this with TC open and using Favmenu to set the folder.
Habemus majkam!
- majkinetor !
- Power Member
- Posts: 1580
- Joined: 2006-01-18, 07:56 UTC
- Contact:
Well, this sounds like it is slow as hell...I don't, they are too slow.
Hooks are not too slow, they are just slower then subclassing.
Can you show relevant parts of your code ? Explain what you did ?
Bla bla...
Also, keep in mind that some other control may subclassed after you. So, it is removing messages from your quieue. You never know how subclass hierarachy is deep. You can easily have X > Y > Z > TotalCMD and your code being Y. Don't know how this can be detected atm.
Winispector probably use hooks. Otherwise, the only solution to monitor all programs AFAIK is being driver, and I doubt Winspector has driver part.
Habemus majkam!
There's at least one more way.majkinetor ! wrote:Winispector probably use hooks. Otherwise, the only solution to monitor all programs AFAIK is being driver, and I doubt Winspector has driver part.
Code injection. At the begining of each function I want to take over I writemajkinetor ! wrote:Can you show relevant parts of your code ? Explain what you did ?
Bla bla...
Code: Select all
mov eax, replacement_function_addr
jmp eax
I use it to get RegisterClass, what gives me the address of TTOTAL_CMD's WindowProc.
Then I just do the same trick again...and I'm ready.
Of course, while writing these jumps, I remember what was there before, so I can restore the original code whenever I want to.
Subclassing..I didn't think about it. It may be the problem. I'll take a closer look.majkinetor ! wrote: Also, keep in mind that some other control may subclassed after you. So, it is removing messages from your quieue. You never know how subclass hierarachy is deep. You can easily have X > Y > Z > TotalCMD and your code being Y. Don't know how this can be detected atm.
I think that TotalCommander forum is a better place for this topic, it's not about the interface, but about TC's internals.Hacker wrote:Moved to the Plugins and addons forum.
Hacker (Moderator)
- majkinetor !
- Power Member
- Posts: 1580
- Joined: 2006-01-18, 07:56 UTC
- Contact:
I didn't know you used this way. Its amazing how you made it work.Code injection.
So, you say that you change code for the func by overwriting the start of the function with your asm code ? But how do you call original function then as its start is deleted ? Did you do something like:
Code: Select all
originalCode = Redirect(@TC_Function, @replacement_function )
replacement_function()
{
...
Restore(@TC_Function, @originalCode)
TC_Function()
Redirect(@TC_Function, @replacement_function)
}
I don't understand this.I use it to get RegisterClass, what gives me the address of TTOTAL_CMD's WindowProc.
I usualy call GetWindowLong to find out WindowProc adr.
Habemus majkam!
That's exactly what I do.majkinetor ! wrote: So, you say that you change code for the func by overwriting the start of the function with your asm code ? But how do you call original function then as its start is deleted ? Did you do something like:Code: Select all
originalCode = Redirect(@TC_Function, @replacement_function ) replacement_function() { ... Restore(@TC_Function, @originalCode) TC_Function() Redirect(@TC_Function, @replacement_function) }
But to call GetWindowLong, there must be a window. I can obtain this address and do the modification before there's any window of this class created.majkinetor ! wrote:I don't understand this.I use it to get RegisterClass, what gives me the address of TTOTAL_CMD's WindowProc.
I usualy call GetWindowLong to find out WindowProc adr.
- majkinetor !
- Power Member
- Posts: 1580
- Joined: 2006-01-18, 07:56 UTC
- Contact:
So, how do you use RegisterClass to get proc adr ?. I can obtain this address and do the modification before there's any window of this class created.
I beleive this code may crash the TC in some situations.That's exactly what I do.
You should probably redirect and restore in critical sections. Anyway, amazing if it works correctly. I know there are Delphi modules for redirection, but they have disasemblers integrated AFAIK so they detect where to "stop deleting" original code as you can bump in the middle of instruction the way you do. Something may eventualy jump in the middle of your process of "fixing" and call the function you are "fixing".
If it works without problems, and you didn't use any 3th party modules for redirection, I must say I am impressed.
I suspect that Ghisler will hunt you until he burns you to death, for doing such nasty and dirty hacks to his only child.
Habemus majkam!
Every time TC registers a class, it calls my function. This function checks if the class name is "TTOTAL_CMD".majkinetor ! wrote:So, how do you use RegisterClass to get proc adr ?. I can obtain this address and do the modification before there's any window of this class created.
- If it's not, it does what you wrote above: restores the original RegisterClass, calls it and places a jump to itself on it again.
- If it is, reads the WndProc address ( from WNDCLASS given as a parameter ), places a jump there, releases RegisterClass and calls it (does not overtake it again, as it's not needed anymore).
You're definitely right, thank you.majkinetor ! wrote:I beleive this code may crash the TC in some situations.That's exactly what I do.
You should probably redirect and restore in critical sections.
- majkinetor !
- Power Member
- Posts: 1580
- Joined: 2006-01-18, 07:56 UTC
- Contact:
Will this redirected RegisterClass for entire system, not only TC ? RegsterClass is shared by all processes in the system IMO.
Well... its cool.
I have here little firewall (~50K) that is using this technique to redirect OpenSocket API. I just think it used hooks for some reason, possible to because OpenSocket isn't shared. I know its hard to turn it of without reseting computer (or I don't know to use it). Maybe you can do the same, and create little firewall as a FS plugin. Nothing fancy, just basic monitoring needs.
Well... its cool.
I have here little firewall (~50K) that is using this technique to redirect OpenSocket API. I just think it used hooks for some reason, possible to because OpenSocket isn't shared. I know its hard to turn it of without reseting computer (or I don't know to use it). Maybe you can do the same, and create little firewall as a FS plugin. Nothing fancy, just basic monitoring needs.

Habemus majkam!
I saw some results from it and there ware nothing but TC windows, so it's rather not shared. I'll do more tests tomorrow.majkinetor ! wrote:Will this redirected RegisterClass for entire system, not only TC ? RegsterClass is shared by all processes in the system IMO.
Well... its cool.
I have here little firewall (~50K) that is using this technique to redirect OpenSocket API. I just think it used hooks for some reason, possible to because OpenSocket isn't shared. I know its hard to turn it of without reseting computer (or I don't know to use it). Maybe you can do the same, and create little firewall as a FS plugin. Nothing fancy, just basic monitoring needs.
- majkinetor !
- Power Member
- Posts: 1580
- Joined: 2006-01-18, 07:56 UTC
- Contact:
But there's no way to ensure that my dll will get the same address in all processes.majkinetor ! wrote:Nothing special - you make a global hook, which loads your dll in every app, then you do your fixing thingie the same way as in TC.
I've been thinking about this Delphi module you mentioned and I think that finding ret was not the main purpose of disassemblation - if don't have enough space, you'll do nothing. But if you have the routine disassembled, you can assemble it again to work in a different part of memory (actually probably the only thing that has to be changed in the binary representation are jumps ). Why relocation is better than these jumps I do? I can't make it fully thread safe, this code may miss some calls. Example?
Code: Select all
Thread 1 | Thread 2
-----------------------------------------------------
call the "orig." function | // Thread 1 thinks it's the original function,
// but there's a jump
jump
enter the critical section |
restore the orig. code |
call the orig. function | call the orig. function // there's just the orig code =>
// Thread 2 has no critical section to enter
place the jump again |
leave the critical section |