Jump to content

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


Aktonius
 Share

Recommended Posts

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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
Link to comment
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.

Link to comment
Share on other sites

Link to comment
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

Link to comment
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.
Link to comment
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?

Link to comment
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.
Link to comment
Share on other sites

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
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...