Sign in to follow this  
Followers 0
Aktonius

Sending wm_copydata/struct(with another struct as ->lpdata) to autoit app

15 posts in this topic

#1 ·  Posted (edited)

I need help with sending wm_copydata from dll to autit. Wm_copydata sends c++ struct which has all information needed for autoit app.

Struct with data sent(hwnd, wchar[1024]) is naturally stored in lpdata(ref: http://msdn.microsoft.com/query/dev10.qu...2B%22%29;k%28TargetOS-WINDOWS%)

c++ code and struct sent...

/////////////////////////////////
//make_struct c(L"text");
// just a struct with ctor, hwnd and text(passed) are stored in struct  
//c.text
//c.hwnd
/////////////////////

COPYDATASTRUCT cds;
::ZeroMemory(&cds, sizeof(COPYDATASTRUCT));
cds.dwData = 1;
cds.lpData = c;

::SendMessage(g_main, WM_COPYDATA, (WPARAM)::GetDesktopWindow(), (LPARAM)&cds);

Now the receiving part from autoit. I cant figure how to slice the struct in autoit code and get info piece by piece(hwnd then text(wchar))...

The only thing i managed to do is simply send wchar[1024] in lpdata, with the following code... I would prefer to send a struct as lpdata instead so i can receive hwnd as well without sending more wm_copydata messages.

Func WM_COPYDATA($hWnd, $MsgID, $wParam, $lParam)

    Switch $hWnd
        Case $myform
            Local $tCOPYDATA = DllStructCreate("ULONG_PTR;DWORD;PTR", $lParam)
            Local $tMsg = DllStructCreate("WCHAR[1024]", DllStructGetData($tCOPYDATA, 3))
            $sWM_COPYDATA_Received_String = DllStructGetData($tMsg, 1)
            ConsoleWrite("received str > "&$sWM_COPYDATA_Received_String&@LF)
    EndSwitch

EndFunc   ;==>WM_COPYDATA
Edited by Aktonius

Share this post


Link to post
Share on other sites



#3 ·  Posted (edited)

First, your C code is wrong. Reread the doc for the COPYDATASTRUCT. dwData is just some data, doesn't have to been anything. The important info is cbData, the size of the data pointed to by lpData, and the data itself. lpData is a pointer, not the struct itself, and can point to any kind of structure you want to create. If you need to pass different kinds of data, use an enumeration in dwData to tell AutoIt which structure it is receiving. Variable lengths of things like strings can be handled by checking cbData for the size.

On the AutoIt side, read up on Dll structs, and create whatever struct you need for you data (you should know what the structure is going to be) and create it at the pointer received by AutoIt in the lpData member of the received COPYDATASTRUCT.

Edited by wraithdu

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

On the AutoIt side, read up on Dll structs, and create whatever struct you need for you data (you should know what the structure is going to be) and create it at the pointer received by AutoIt in the lpData member of the received COPYDATASTRUCT.

wraithdu, yeah i know c code was wrong but that was just something wrapped in comment to show what i am doing.

But hey, thanks so much for the help, i cant believe how stupidly close i was to solution.

Func WM_COPYDATA($hWnd, $MsgID, $wParam, $lParam)
    ; http://www.autoitscript.com/forum/index....?showtopic=105861&view=findpos
    ; Melba23, based on code from Yashied
    ConsoleWrite("wm_copydata "&@LF)
    Switch $hWnd
        Case $Form2
            Local $tCOPYDATA = DllStructCreate("ULONG_PTR;DWORD;PTR", $lParam)
            Local $tMsg = DllStructCreate("HWND;WCHAR[1024]", DllStructGetData($tCOPYDATA, 3))
            $sWM_COPYDATA_Received_String = DllStructGetData($tMsg, 2)
            $HWND = DllStructGetData($tMsg, 1)
            ConsoleWrite("received str > "&$sWM_COPYDATA_Received_String&@LF)
            ConsoleWrite("$HWND  > "&$HWND&@LF)
    EndSwitch

EndFunc   ;==>WM_COPYDATA

THe only issue now that i have is that i cant get control hwnd in the dll by using

struct.hwnd = ::WindowFromDC(hdc);

This will only return hwnd from a window so when i receive hwnd it will only work if hdc belongs to top level window(not controls).

Any idea how i could get control hwnd(listview in this case) from hdc in the c++?

Thanks again

edit: Oh and another thing, since i am sending wm_copydata from a dll injected in another process, hooked process has giant hogs while sending data and i am pretty sure the issue is because it waits for sendmessage to return(finish processing in my autoit gui).

When i tested the same method where c app would receive this messages, there were no hogs at all. Is this because autoit is bit to slow for tasks like this? wm_copy data messages are unloaded all the time and with autoit the hooked process which sends messages will simply slow down alot while messages are processed.

I was thinking to use postmessage but then wm_copydata wont work with it

Edited by Aktonius

Share this post


Link to post
Share on other sites

Not sure about hanging the sending app, but make sure you return success (1 I think) from the AutoIt side. You should also not do any lengthy processing in the WM_COPYDATA function in AutoIt.

Share this post


Link to post
Share on other sites

any idea how to get this data then, i could store it in text file and read from there with autoit but this is kind of solution i somehow dont like

Share this post


Link to post
Share on other sites

Can't you just send the hwnd in a message? I think it would work the same way your sending all the other data.

As for the delay, I have noticed it in one project of mine, but that was only because I was sending a hundreds of msgs per second.

Share this post


Link to post
Share on other sites

You'll need to follow guidelines on managing GUIRegisterMsg without blocking. There are examples somewhere, I just can't find them at the moment.

Share this post


Link to post
Share on other sites

Ok pardon me for more question guys, notice that i am not MVP as most of you in this post :)

@Beege

I am also sendin ALOT of them because all messages contain bunch of data that is updated in real time. I cant send hwnd since hdc from listview wont return hwnd with windowfromdc(hdc). The same code and i will repeat same code again detects hwnd fine from the top level window but when it comes to hdc from the listview = nothing. Perhaps this hdc is somehow blocked from the app to not return hwnd, i dont know.

@wraithdu

The issue with wm_copydata is that it cant be used with anything but sendmessage() which must wait for return and therefore makes hogs. How would you avoid that blocking from that example?

@Yashied

I hooked to the function of the process that passes its own hdc, so i am pretty sure it belongs to the targeted process

Share this post


Link to post
Share on other sites

HDC should belong to the current process.

I hooked to the function of the process that passes its own hdc, so i am pretty sure it belongs to the targeted process

Anything you do with the handle to device context needs to happen in the context of the process that owns it. It has nothing to do with whether or not you have the right handle.

Share this post


Link to post
Share on other sites

Anything you do with the handle to device context needs to happen in the context of the process that owns it. It has nothing to do with whether or not you have the right handle.

I am using windowfromdc() in the dll which belongs to the targeted process, so it must happen in the context of process that owns hdc no?

Share this post


Link to post
Share on other sites

I am using windowfromdc() in the dll which belongs to the targeted process, so it must happen in the context of process that owns hdc no?

No, because you are calling the dll from your program. You have to actually inject a function into the target process and get that process to execute your function. This is doable at a low level, but certainly not in AutoIt without a lot of trouble.

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

No, because you are calling the dll from your program. You have to actually inject a function into the target process and get that process to execute your function. This is doable at a low level, but certainly not in AutoIt without a lot of trouble.

Thats exactly what i am doing. Not doing it with autoit though but through dll and detours.

Anyway, after some testing, everything works fine since i figured a way to properly filter stuff that i actually need to send to my autoit app, not hogging anymore.

Thanks for help everyone

Edited by Aktonius

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0