If you register a message in Windows you give it some text and Windows will return a message number, you use RegisterWindowMessage for this function. Thing is there is no matching function to reverse the API, that is there is no function (AFAIK) that takes the number and returns the text. Well, not quite, it seems the GetClipboardFormatName performs it quite nicely. Try this:
invoke RegisterWindowMessage,"ThisTest"
invoke GetClipboardFormatName,eax,offset MessageName,256
MessageName will contain the text "ThisTest"
Could be used to send short text strings between applications.
Edgar
i wonder if you set the right flag bit, it is available from FormatMessage
I got this far with the snippet.
.DATA
Info db "I swear it wasn't me, it was Bernie!!",0
.DATA?
MessageName db ?
.CODE
%Date db " &@Date" ; Compile date
start:
invoke RegisterWindowMessage,addr Info
invoke GetClipboardFormatName,eax,offset MessageName,256
QuoteI got this far with the snippet.
and ????? - lol
let me play with FormatMessage.....
it looks like this function was intended to be used for Find/Replace operations
it should be retievable with GetMessage
but, i am hard-headed - i still want to see if FormatMessage can access it :P
Looking for a use for it.
Maybe instead of the hotkey code, this can be used.
doesn't sound very convenient in that context
the program that posts the message would have to have focus to recognize a keystroke
Quote from: Magnum on December 12, 2010, 08:35:24 PM
Looking for a use for it.
Maybe instead of the hotkey code, this can be used.
One use I have for it is for one-shot interprocess communication. For example Help2Viewer can only run in a single instance, if it finds another instance it will send a WM_COPYDATA message with the command line and the running process will complete the operation while the new one shuts down. The command line can be sent as a registered message and the application can extract the text. Since I would be wary about polluting the system with registered messages I would probably only use it during shutdown of an application since the messages and their data are discarded once the process terminates. I plan on using it in a symbols program I never seem to get around to finishing, when an application receives a registered message the tool will display its string.
I really doubt that FormatMessage will get the text string here but its worth a try.
By the way Magnum, you have to allow enough room in the buffer you pass to GetClipboardFormatName to hold the entire string, obviously allocating 1 byte to hold a string that is 38 bytes long (with terminator) and telling it the buffer size is 256 bytes is not going to work well...
Edgar
can't you do that with SendMessage/GetMessage ???
O.K.
I thought too much was alright, didn't want a buffer overflow.
Quote from: Magnum on December 12, 2010, 10:05:26 PM
O.K.
I thought too much was alright, didn't want a buffer overflow.
You didn't have too much space in the buffer, you only have a 1 byte buffer in the code above, that is not enough space to hold the string, it will definitely overflow. Try to use this instead:
MessageName db 256 DUP (?)
Nice discovery, Edgar!
include \masm32\include\masm32rt.inc
.data?
MessageName dd 2048 dup(?)
.code
TheString db "A test string designed for 'InterProcessCommunication' aka IPC;", 13, 10, "it works also with special characters, and you can insert CrLf easily.",13, 10,\
"The string can be a little bit longer, but it should not exceed 256 characters,", 13, 10, "apparently. Beyond 256, it will choke", 0
start: invoke SetLastError, 0
print "Testing RegisterWindowMessage with a "
print str$(sizeof TheString), " byte string:", 13, 10
invoke RegisterWindowMessage, offset TheString
push eax
print LastError$(), 13,10
pop eax
invoke GetClipboardFormatName,eax,offset MessageName, sizeof MessageName
print LastError$(), 13,10
print offset MessageName
exit
end start
Quote from: dedndave on December 12, 2010, 09:48:48 PM
can't you do that with SendMessage/GetMessage ???
Not in most cases, you would need a way to marshal the data in order to transfer strings. Messages in Windows pass strings as pointers, the pointer from one process is meaningless to all other processes since they run in separate address spaces. The WM_COPYDATA message will marshal data for you but I was thinking this is much easier to set up for quick one-shot strings.
System have some strict limits for number of possible registered messages. In usual usage this is enough, but if program will register thousands of messages per second, this will overflowed after a couple of seconds. Is not it?
Quote from: Antariy on December 12, 2010, 11:25:39 PM
System have some strict limits for number of possible registered messages. In usual usage this is enough, but if program will register thousands of messages per second, this will overflowed after a couple of seconds. Is not it?
Hi Antariy,
That's why I added this caveat:
QuoteSince I would be wary about polluting the system with registered messages I would probably only use it during shutdown of an application since the messages and their data are discarded once the process terminates
If you have to pass thousands of strings you should be using other methods anyway, this would be a pretty lame way to do it. For any sizable amount of data custom marshalling (eg allocating buffers across process boundaries using VirtualAllocEx), shared data in a dll or memory mapped files would be better solutions. As with everything, the method has to fit the needs.
It is a good point to stress though so newbies don't run out and start trying to transfer War and Peace from one app to another using registered messages :wink
Edgar
Quote from: donkey on December 12, 2010, 11:35:02 PM
Quote from: Antariy on December 12, 2010, 11:25:39 PM
System have some strict limits for number of possible registered messages. In usual usage this is enough, but if program will register thousands of messages per second, this will overflowed after a couple of seconds. Is not it?
Hi Antariy,
That's why I added this caveat:
QuoteSince I would be wary about polluting the system with registered messages I would probably only use it during shutdown of an application since the messages and their data are discarded once the process terminates
If you have to pass thousands of strings you should be using other methods anyway, this would be a pretty lame way to do it. For any sizable amount of data custom marshalling (eg allocating buffers across process boundaries using VirtualAllocEx), shared data in a dll or memory mapped files would be better solutions. As with everything, the method has to fit the needs.
No, when application was ended, registered messages was *not* deleted. They stay registered until system reboot. Try to get a string from GetClipboardFormatName for an atom which you get earlyer in other running, and you will see.
Of course, as IPC this method is not good, shared memory a lot better and faster.
But I have not seen reversing of message name by its atom in back, this nice trick you invent :thumbu
Alex
Yup, you're right, the message remains until the Windows session ends.
Quote from: Antariy on December 12, 2010, 11:41:51 PM
No, when application was ended, registered messages was *not* deleted. They stay registered until system reboot. Try to get a string from GetClipboardFormatName for an atom which you get earlyer in other running, and you will see.
Testbed... Alex is right. Still, it has an advantage over WM_COPYDATA since the latter would not work with console app.
include \masm32\include\masm32rt.inc
.data?
MessageName dd 2048 dup(?)
.code
TheString db "A test string designed for 'InterProcessCommunication' aka IPC;", 13, 10, "it works also with special characters, and you can insert CrLf easily.",13, 10,\
"The string can be a little bit longer, but it should not exceed 256 characters,", 13, 10, "apparently. Beyond 256, it will chok", 0
start: invoke SetLastError, 0
print "Testing RegisterWindowMessage with a "
print str$(sizeof TheString), " byte string:", 13, 10
Round1=1
if Round1
invoke RegisterWindowMessage, offset TheString
else
mov eax, 49799 ; on first round, I see this value
endif
push eax
print str$(eax), 9
print LastError$(), 13,10
pop eax
invoke GetClipboardFormatName,eax,offset MessageName, sizeof MessageName
print LastError$(), 13,10
print offset MessageName
exit
end start
Quote from: donkey on December 13, 2010, 12:04:46 AM
Yup, you're right, the message remains until the Windows session ends.
Anyway, your trick is very useful. For message scanners etc.
you mean console apps cannot share memory ?
i have never had a need to do this - but it would be cool to know how :bg
Quote from: dedndave on December 13, 2010, 01:51:50 AM
you mean console apps cannot share memory ?
The problem is that console apps typically have no message loop/WndProc where you could check for WM_COPYDATA.
hmmmm
another thing i haven't tried yet :P
create a console proc, (i.e. no gui window) with a WndProc
well - that seems easy enough
that's what happens when i accidently link a gui app as console :bg
Quote from: dedndave on December 13, 2010, 03:21:33 AM
create a console proc, (i.e. no gui window) with a WndProc
If you create a GUI app with subsystem console, you will have a console for printing. Everything else works as usual.
I forgot to mention that you can
send WM_COPYDATA from a console.
that's what i said :bg