Passing String to other Applications with SendMessage,...

  • Thread starter Kerem Gümrükcü
  • Start date
K

Kerem Gümrükcü

Hi,

i want to emulate a (synchronous) BroadCastSystemMessage
with EnumWindows and SendMessage. I dont want to use
the BroadcastSystemMessage because it needs the SE_TCB_NAME
Privilege (you dont have this in normal). So i decided to use the
EnumWindows with SendMessage. What i try here is to pass a
WM_USER+1111 with LParam and WParam, pointing to strings.
But when i try to get the strings at the other end with
Marshal.PtrToStringAnsi,
the String itself is empty. I dont know what the mistake here is, so
a little code:

IntPtr ptrIPAddress = IntPtr.Zero;
IntPtr ptrGUID = IntPtr.Zero;

ptrIPAddress =
Marshal.AllocHGlobal(Encoding.ASCII.GetByteCount(this.textBoxGGIPAIPAddress.Text));
ptrGUID =
Marshal.AllocHGlobal(Encoding.ASCII.GetByteCount(this.guidApplicationGUID.ToString()));

ptrIPAddress = Marshal.StringToHGlobalAnsi(this.textBoxGGIPAIPAddress.Text);
ptrGUID = Marshal.StringToHGlobalAnsi(this.guidApplicationGUID.ToString());

//(IntPtr,uint, IntPtr,IntPtr)
SendMessage(hWnd, (uint)WindowsMessages.WM_USER + 1111, ptrGUID ,
ptrIPAddress );

Marshal.FreeHGlobal(ptrIPAddress);
Marshal.FreeHGlobal(ptrGUID);



At the other end i try this, but nothing is in there:

protected override void WndProc(ref Message m)
{
if (m.Msg == (uint) WindowsAPIClass.WindowsMessages.WM_USER + 1111)
{
String s = Marshal.PtrToStringAnsi(m.LParam);
MessageBox.Show(s);
}
base.WndProc(ref m);
}


How to do this? I cant use remoting or stuff like that, because
the message should be available for any application running on
the System,...it seems that the global memory isnt really global,...

Regards

Kerem

--
 
M

Michael C

Kerem Gümrükcü said:
Hi,

i want to emulate a (synchronous) BroadCastSystemMessage
with EnumWindows and SendMessage. I dont want to use
the BroadcastSystemMessage because it needs the SE_TCB_NAME
Privilege (you dont have this in normal). So i decided to use the
EnumWindows with SendMessage. What i try here is to pass a
WM_USER+1111 with LParam and WParam, pointing to strings.
But when i try to get the strings at the other end with
Marshal.PtrToStringAnsi,
the String itself is empty. I dont know what the mistake here is, so
a little code:

You can't pass a pointer cross process. Each application has it own
completely seperate memory space. What is a valid pointer for your app is
not a valid pointer for another. You should look at the WM_COPY_DATA message
as it will copy your string data cross-process and is quite easy to use.

Michael
 
K

Kerem Gümrükcü

Hi Michael,

yes i know this but I still tried to find a way. I know
the WM_COPYDATA but it would be great if
this would be possible with some sort of WM_USER.
But since processes are exclusive i think i have to
go the WM_COPYDATA way,...

Regards

Kerem
--
 
S

Serge Baltic

Hello,
i want to emulate a (synchronous) BroadCastSystemMessage
with EnumWindows and SendMessage.

Seems like you're trying to enumate SendMessage(HWND_BROADCAST, …) instead.
Why not use it?

(H) Serg
 
K

Kerem Gümrükcü

Hi Serge,
Seems like you're trying to enumate SendMessage(HWND_BROADCAST, .) instead.
Why not use it?

i need a synchronous way in sending the message. I also could use
PostMessage but it does place the message into the messageQ and
returns in the same moment. Send Message does not (if you use it
with every window handle obtained from EnumWindows and not
with HWND_BROADCAST,)...

Thanks anyway,...

Regards

Kerem

--
 
M

Mattias Sjögren

ptrIPAddress =
Marshal.AllocHGlobal(Encoding.ASCII.GetByteCount(this.textBoxGGIPAIPAddress.Text));
ptrGUID =
Marshal.AllocHGlobal(Encoding.ASCII.GetByteCount(this.guidApplicationGUID.ToString()));

ptrIPAddress = Marshal.StringToHGlobalAnsi(this.textBoxGGIPAIPAddress.Text);
ptrGUID = Marshal.StringToHGlobalAnsi(this.guidApplicationGUID.ToString());

By overwriting the pointers you're leaking the memory you first
allocated with AllocHGlobal. Those calls seem completely unnecessary.

How to do this? I cant use remoting or stuff like that, because
the message should be available for any application running on
the System,...it seems that the global memory isnt really global,...

If you want real global memory you should look at memory mapped files.
But it may be easier to use WM_COPYDATA as Michael suggested.


Mattias
 
K

Kerem Gümrükcü

Hi Mattias,
By overwriting the pointers you're leaking the memory you first
allocated with AllocHGlobal. Those calls seem completely unnecessary.

Yes, this was the call from a earlier try, i removed it....
If you want real global memory you should look at memory mapped files.
But it may be easier to use WM_COPYDATA as Michael suggested.

Memory mapped files are in my case and also the approach of global
available data not that secure since want to make the thing more secure.
I use encrypted data that must be transfered,...

Thanks for the reply,...


Regards

Kerem

--
 
M

Mattias Sjögren

Memory mapped files are in my case and also the approach of global
available data not that secure since want to make the thing more secure.
I use encrypted data that must be transfered,...

Sorry I'm not following. Memory mapped files seems lie a much more
secure solution in that case, since you can specify a security
descriptor for the file mapping and have complete control over who can
read and write from it.

Compare that to broadcasting data with window messages where any
message recipient gets to read the data.

Whether or not the data is encrypted is irrelevant to your
communication mechanism.


Mattias
 
S

Serge Baltic

Hello,
How to do this? I cant use remoting or stuff like that, because the
message should be available for any application running on the
System,...

What do you mean by “available for any application†— is that about not every
application being managed?

There're lots of things intended for communication in the Windows NT OS,
still I've made practical use of COM only. That should work equally good
for both managed and unmanaged. Putting an object into the Running Objects
Table makes it possible to place calls on it from other processes, handling
the string marshalling issues automatically for you.

If all you need to transmit are strings, you could take a look at DDE also.
That's perfectly suited for the case “broadcast a string message to a number
of listenersâ€, and could be implemented in .NET. For instance, that's the
way how Shell opens the second document in the existing application, like
a new link in IE, a new document in Word, and so on.

(H) Serge
 
K

Kerem Gümrükcü

Hi Mattias,

i solved it another way, but my problem is passing
the data between two windows does not work. I get
garbage at the other end when passing the data with
the WM_COPYDATA Message.

Here is Code:

//structure to pass
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct APP_IP_GUID_INFORMATION
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string ApplicationGUID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string IPAddress;
}


[StructLayout(LayoutKind.Sequential)]
public struct CopyDataStruct
{
public int dwData;
public int cbData;
public IntPtr pData;
}


IntPtr ptrAIGI = IntPtr.Zero;
IntPtr ptrCDS = IntPtr.Zero;
IntPtr hWnd = IntPtr.Zero;

GGIPAWin32APIClass.APP_IP_GUID_INFORMATION aigi;
aigi.ApplicationGUID = this.guidApplicationGUID.ToString();
aigi.IPAddress = this.textBoxGGIPAIPAddress.Text;

ptrAIGI =
Marshal.AllocHGlobal(Marshal.SizeOf(typeof(GGIPAWin32APIClass.APP_IP_GUID_INFORMATION)));
Marshal.StructureToPtr(aigi, ptrAIGI, false);

GGIPAWin32APIClass.CopyDataStruct cds;
cds.dwData = this.Handle.ToInt32();
cds.cbData =
Marshal.SizeOf(typeof(GGIPAWin32APIClass.APP_IP_GUID_INFORMATION));
cds.pData = ptrAIGI;

ptrCDS =
Marshal.AllocHGlobal(Marshal.SizeOf(typeof(GGIPAWin32APIClass.CopyDataStruct)));
Marshal.StructureToPtr(cds, ptrCDS, false);

/*...........*/

hWnd = new IntPtr(Convert.ToInt32(ClienthWnd.Key.ToString()));
HandleRef hWndRef = new HandleRef(this,hWnd);
GGIPAWin32APIClass.SendMessage(hWndRef,
(uint)GGIPAWin32APIClass.WindowsMessages.WM_COPYDATA, this.Handle, ptrCDS)


/*...........*/

Marshal.FreeHGlobal(ptrAIGI);
Marshal.FreeHGlobal(ptrCDS);


The dwData and cbData at the other end are ok, but the pointer to the data
is garbage,...why.
Any idea? All pinvoke-functions and data is ASCII or ANSI,...


Thanks in advance,...

Regards

Kerem

--
 
M

Michael C

Kerem Gümrükcü said:
The dwData and cbData at the other end are ok, but the pointer to the data
is garbage,...why.
Any idea? All pinvoke-functions and data is ASCII or ANSI,...

The pointer is garbage or what it points to is garbage? Are you sure you're
creating the data correctly? Try sending a byte array with a few arbitrary
values in it first. Also try using the rtlMoveMemory api to copy your data
to a byte array into your app as a test (ie not through SendMessage).

Michael
 
K

Kerem Gümrükcü

Hi Michael,

when i send the Data with WM_COPYDATA, the receiving
application has the right cbData and dwData values send from
my application, but pData is nothing else than random application.
I dont know whether the mistake lies on the sender or the receiver
side, but i think the mistake is on the sender side. I debugged my
reciver applications CopyDataStruct with VC++ (receiver is a
native app) and also a mannaged app. Bott apps pData is useless.
Dont as me why! Except the cbData and dwData nothing males sense.

Any ideas. Do i marshal the data the right way? Are my pinvoke
signatures ok?

Data should be TCHAR lpIPAddress[128] and
TCHAR lpApplicationGUID[128] at the other end...
But its something like "@/!29d)383Rgen%2%4"ß?0".
Pointing to "i dont know" data,...


Regards

Kerem

--
 
M

Michael C

Kerem Gümrükcü said:
Hi Michael,

when i send the Data with WM_COPYDATA, the receiving
application has the right cbData and dwData values send from
my application, but pData is nothing else than random application.
I dont know whether the mistake lies on the sender or the receiver
side, but i think the mistake is on the sender side. I debugged my
reciver applications CopyDataStruct with VC++ (receiver is a
native app) and also a mannaged app. Bott apps pData is useless.
Dont as me why! Except the cbData and dwData nothing males sense.

How do you know it's your pointer that is rubbish? The pointer will be
changed from one app to the other. It's possible that the data is incorrect
*before* it is sent and the SendMessage is working correctly. Check this
first using the 2 suggestion in my previous post.

Michael
 
K

Kerem Gümrükcü

Hi Michael,

i am desperately looking for a Memory Window
in my VStudio 2005 Standard Edition. Did i miss
something or do i dont have one there? I dont want
to debug it the native way or use some external
debugger to have a in-depth look into the pointers
memory address. I have a symbol file and i can use
some external debugger like Smidgeonsofts PEDebugger
or some other *.pdb able debugger.


But this is not the point here. When i do a MessageBox
on the Structs Members "IPAddress" and "ApplicationGUID"
i get valid Strings displayed. Maybe something is corrupted after
Marshal.StructToPtr,...i cant see the memory pointers address,
thats the point...

Regards

Kerem

--
 
M

Michael C

Kerem Gümrükcü said:
Hi Michael,

i am desperately looking for a Memory Window
in my VStudio 2005 Standard Edition. Did i miss
something or do i dont have one there?

Try Ctrl + Alt + M and then push 1. Otherwise it should be on a menu
somewhere.
I dont want
to debug it the native way or use some external
debugger to have a in-depth look into the pointers
memory address. I have a symbol file and i can use
some external debugger like Smidgeonsofts PEDebugger
or some other *.pdb able debugger.

My suggestion was to just copy the data to a byte array and have a look at
what's in the byte array. If that has what you expect then you are half way
there. Although looking at the memory window is probably easier.

The other idea is to create a small amount of arbitrary data (again, use a
byte array) and see if that gets copied across ok.

Michael
 
K

Kerem Gümrükcü

Hi Michael,

i was missing the Memory window and the command
you suggested didnt work. So i did a raw debugging with
ollydbg and a raw disassembly of the memory and looked
at the memory pointing from the CopyDataStruct.
Everything was fine, but i made a wrong calculation at the
other end receiving the WM_COPYDATA. The size and
the offset to the data was wrong, so it was clear the i
pointed at random process data. Problem solved,..everybody
is happy!


And now i found this, but too late...(sigh)

http://msdn2.microsoft.com/en-us/library/s3aw423e(VS.80).aspx
http://msdn2.microsoft.com/en-us/library/9k643651(VS.80).aspx

Will be usefull the next time!
Visual Studio: Every Day a new experience,...


Thank you very much,...

Regards

Kerem


--
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top