News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Attempting to send messages to another process

Started by boogara, January 11, 2008, 03:41:12 AM

Previous topic - Next topic

boogara

First off, I want to say this isn't a malicious hacking attack kind of thing...just something to make my job easier (mainly out of boredom I'm attempting this).

Anywho...here's the deal.  At work, we use the CISCO CTIOS software, which basically gives us a control panel kind of use to our phones.  Want I want to be able to do is simply be able to, for this post's sake, transfer calls without having to click 5-thousand different times.  What I want to know though, is how to tell the program that I'm sending it a "transfer" button message, and not a "conference" button message (for example).  I've attempted FindWindowEx(), FindWindow(), and a few other things without any luck.

The problem is that the class is "ATL:[hex numbers]" according to the program I use (since I don't currently have access to Spy++)...and so I've tried it with and without the "ATL:" part.  As you can see in the screen shot I'm providing below, the button itself doesn't have any text to it, or else I'd simply use FindWindowEx() with the button caption to do this.  I've also searched Google for a few hours trying to find out how to capture ATL buttons in a way that FWE() does, as well as search for ways to get ATL window handles on the control and the like.

I've thought about using EnumChildWindows(), but if FWE() doesn't give me any results, I'm not sure if EnumChildWindows() is going to work, either...(not to mention, setting it up is kind of confusing, but it seems like it's basically just as if I was programming a hook).

Here's a screen shot of what the program looks like, and some handle info for the transfer command: http://i4.photobucket.com/albums/y129/quantrizi/untitled-1.jpg

Edit

I think it'd be good to also state that all the buttons have the same class...which makes it even harder I'm thinking T_T  Also, don't handles to windows and children change each time the app is ran?

Ehtyar

Like many apps done in hll junk like this, this app might not be using the standard button control at all. Try using a window examiner of some kind, like WinExplorer to see what kind of child controls this window is harboring.

Ehtyar.

Tight_Coder_Ex

Enumerate windows first to find the parent and then enumerate child windows to find the handle to the button or whatever control your interested in and then establish a hook into it or simply send a message to that window.


boogara

Quote from: Ehtyar on January 11, 2008, 01:40:26 PM
Like many apps done in hll junk like this, this app might not be using the standard button control at all. Try using a window examiner of some kind, like WinExplorer to see what kind of child controls this window is harboring.

Ehtyar.
Alrighty, shall do :)  Also, thanks for the link :)  I'll do this and see what comes about today.

Quote from: Tight_Coder_Ex
Enumerate windows first to find the parent and then enumerate child windows to find the handle to the button or whatever control your interested in and then establish a hook into it or simply send a message to that window.

I already found the parent though...the only problem I have right now is finding children that don't have a caption...but, I'm going to do what Ehtyar said, and then try to send a message to it, since I don't want to deal with the ugliness of hooking right now.

Tight_Coder_Ex

There must be something that is unique to the window of interest and therefore calls that provide more specific information like GetWindowLong in the callback procedure should provide you with adequate information to narrow down your focus.

Hooking is not that difficult, but I do agree, in your case it's not specifically relevant  as your focus is to send info not be made aware when something happens in the other application.

boogara

Quote from: Tight_Coder_Ex on January 11, 2008, 06:25:28 PM
There must be something that is unique to the window of interest and therefore calls that provide more specific information like GetWindowLong in the callback procedure should provide you with adequate information to narrow down your focus.

Hooking is not that difficult, but I do agree, in your case it's not specifically relevant  as your focus is to send info not be made aware when something happens in the other application.
Hmmm...never thought about using GetWindowLong...I'll have to take a shot at that, especially if these window explorer programs don't work in the way they need to for this to be done.

Why oh why CISCO must you make this a pain in the tush? :'(

Isn't ATL just basically a wrapper for COM, anyways?

Tedd

You're making this way too hard. Today's Big Hints: :cheekygreen:

1. determine the offset (the center of) of your button to be clicked, from the top-left of the cisco app window, in pixels - this will be a constant which you write directly into your clicker code
(..and now, in your clicker..)
2. find the position of the cisco window (it's top-left corner)
3. add on the offset from 1 to the position in 2 to get the screen co-ordinate for where to click
4. either: find the handle of the button at this point and send it a button click message;
   or, use mouse_event to simulate a mouse click at that point.
No snowflake in an avalanche feels responsible.

boogara

Quote from: Tedd on January 11, 2008, 08:33:50 PM
You're making this way too hard. Today's Big Hints: :cheekygreen:

1. determine the offset (the center of) of your button to be clicked, from the top-left of the cisco app window, in pixels - this will be a constant which you write directly into your clicker code
(..and now, in your clicker..)
2. find the position of the cisco window (it's top-left corner)
3. add on the offset from 1 to the position in 2 to get the screen co-ordinate for where to click
4. either: find the handle of the button at this point and send it a button click message;
   or, use mouse_event to simulate a mouse click at that point.

I'll see if I can do that (shouldn't be all that hard in theory), but doesn't option b in step four require you to do hooking?

Also, for step 4...if I were to get the handle of the button, couldn't I just do a SendMessage() without doing steps 1-3, or would finding the coordinates and such make it easier to get the handle (if that's the case then I'll do that instead).

Tedd

Quote from: boogara on January 11, 2008, 08:46:24 PM
doesn't option b in step four require you to do hooking?
nope :bg

Quote
Also, for step 4...if I were to get the handle of the button, couldn't I just do a SendMessage() without doing steps 1-3
well yes, but 1--3 are an easy method to get the position of the button on screen -- to make it easy to get the handle (or click without using the handle). If you have an easier way to get the handle then use that - but then why this post? :P

Quote
would finding the coordinates and such make it easier to get the handle (if that's the case then I'll do that instead).
That was the idea - you can use the ChildWindowFromPoint function, though you also need the parent window handle (but you should have that from finding the cisco window anyway.)
However, that may not work (not that I've tested) when the buttons are actually child windows of child windows (which I would suspect they are.) If it doesn't work then 'mouse_event' can simulate a mouse-click (still no hooking required!) at that point, though you'd need to normalize the co-ordinates.
No snowflake in an avalanche feels responsible.

boogara

Quote from: Tedd on January 11, 2008, 09:15:28 PM
Quote
would finding the coordinates and such make it easier to get the handle (if that's the case then I'll do that instead).
That was the idea - you can use the ChildWindowFromPoint function, though you also need the parent window handle (but you should have that from finding the cisco window anyway.)
However, that may not work (not that I've tested) when the buttons are actually child windows of child windows (which I would suspect they are.) If it doesn't work then 'mouse_event' can simulate a mouse-click (still no hooking required!) at that point, though you'd need to normalize the co-ordinates.

Alrighty, I'll go with your method. :)  I do have a question though, do you have an example of how to use ChildWindowFromPoint()?  MSDN isn't exactly helpful there...I understand you'd do something like this:


childPoint POINT <>

invoke ChildWindowFromPoint,parentHandle,childPoint


But i'm not sure if its actually that simple, or if I have to fill in childPoint before calling CWFP()...and if I do have to do that, is there any ways I can get the coordinates?

Part of me was thinking of using something like Paint and trying that, but I doubt that's really efficient...

(And yes...you are right to say that they are childs of child windows)

donkey

Hi,

There are some inherent limitations to sending messages to other windows, you can normally only send numeric values. This is because the pointer you would send for a string is useless to the other process as it points to a relative address in your process. In order to send a string or any value by pointer you will have to create some shared memory between the processes and store the data there and use a pointer to that memory buffer. I have an example of this technique on my website...

LVDesktop9xNT.zip

It shows how to create shared memory in both 9x and NT based systems and pass the resulting pointers in a message to another process.

Donkey
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

boogara

Okay, so I got this mainly worked out...I'm testing this on a different button for now, and just need to know one thing...

I have a handle to the parent program, and a handle to a button (testing it on the statistics button)...

How do you send a button-click submit?  I know about SendMessage(), but unless I'm missing something, the closest you can do to this is:

SendMessage(CTIOS_hwnd, BM_CLICK,0,0);

Which, I don't think will do what I want it to do and display the statistics screen.

Any ideas?  I'm currently searching Google for this, but the search isn't going too well...

donkey

invoke SendMessage, [hButton], BM_CLICK, 0, 0

will simulate the button being clicked

You can also send the WM_COMMAND message that corresponds to the button..

invoke GetDlgCtrlID, [hButton]
push eax
invoke GetParent, [hButton]
pop ecx
invoke SendMessage, eax, WM_COMMAND, ecx, [hButton]


You only have to get the control ID and handle once you should get the same performance.

Donkey
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

boogara

Quote from: donkey on January 12, 2008, 01:28:44 AM
invoke SendMessage, [hButton], BM_CLICK, 0, 0

will simulate the button being clicked

You can also send the WM_COMMAND message that corresponds to the button..

invoke GetDlgCtrlID, [hButton]
push eax
invoke GetParent, [hButton]
pop ecx
invoke SendMessage, eax, WM_COMMAND, ecx, [hButton]


You only have to get the control ID and handle once you should get the same performance.

Donkey
Thanks to all whom have helped.

As for the SendMessage() option, that didn't work as planned (tried that origionally).

Anywho, I got this working now (thankfully)...

Here's the code I'm using:


invoke GetWindowRect,ChWnd,addr WinRect

.if eax == 0
invoke MessageBox,hWin,SADD("Unable to get window co-ordinates of CTIOS Agent software.",13,10,"Some functionality will be disabled."),NULL,MB_OK
.else
;invoke ShowWindow,ChWnd,SW_RESTORE and SW_SHOWDEFAULT ; Unless this window is
;invoke SetForegroundWindow,ChWnd ; visibly on the desktop, below code will not work

invoke ChildWindowFromPoint,ChWnd,703,58;665,59

mov tmp, eax

.if tmp == NULL
invoke wsprintf,addr tmp_str,addr sprint,WinRect.right,WinRect.bottom

invoke MessageBox,hWin,SADD("Point given is outside of program area."),NULL,MB_OK
invoke MessageBox,hWin,addr tmp_str,NULL,MB_OK
.elseif eax == ChWnd
invoke MessageBox,hWin,SADD("Returning only handle to parent, no child found."),NULL,MB_OK
.else
invoke MessageBox,hWin,SADD("Got handle to button.",13,10,"Attempting to show Statistics window."),NULL,MB_OK

mov eax, 665
sub eax, WinRect.left
and eax, 0FFFFh

mov edx, 59
sub edx, WinRect.top
shl edx, 16
or eax, edx

mov dw_stuff, eax

invoke SendMessage,tmp,WM_LBUTTONDOWN,NULL,dw_stuff
invoke SendMessage,tmp,WM_LBUTTONUP,NULL,dw_stuff

invoke FindWindow,NULL,SADD("CISCO CTIOS Statistics")

.if eax == NULL
invoke MessageBox,NULL,SADD("Button clicking test failed."), NULL, MB_OK
.else
invoke ShowWindow,eax,SW_SHOWDEFAULT
invoke MessageBox,NULL,SADD("Statistics screen should be displayed."),NULL,MB_OK
.endif
.endif
.endif


I know it's not clean by any means, but it works...and I'm going to be improving it...I just wanted to get something done for right now.

The following code:


mov eax, 665
sub eax, WinRect.left
and eax, 0FFFFh

mov edx, 59
sub edx, WinRect.top
shl edx, 16
or eax, edx

mov dw_stuff, eax


Is taken from another person who asked of a similar question to mine in a different thread, like, 2 years ago or something...modified to fit my purpose, of course.

Ehtyar