The MASM Forum Archive 2004 to 2012

General Forums => The Workshop => Topic started by: donkey on December 12, 2010, 02:03:35 PM

Title: Interesting alternate use for an API
Post by: donkey on December 12, 2010, 02:03:35 PM
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
Title: Re: Interesting alternate use for an API
Post by: dedndave on December 12, 2010, 03:46:03 PM
i wonder if you set the right flag bit, it is available from FormatMessage
Title: Re: Interesting alternate use for an API
Post by: Magnum on December 12, 2010, 06:32:07 PM
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

Title: Re: Interesting alternate use for an API
Post by: dedndave on December 12, 2010, 08:33:39 PM
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
Title: Re: Interesting alternate use for an API
Post by: 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.

Title: Re: Interesting alternate use for an API
Post by: dedndave on December 12, 2010, 08:40:38 PM
doesn't sound very convenient in that context
the program that posts the message would have to have focus to recognize a keystroke
Title: Re: Interesting alternate use for an API
Post by: donkey on December 12, 2010, 08:53:31 PM
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
Title: Re: Interesting alternate use for an API
Post by: dedndave on December 12, 2010, 09:48:48 PM
can't you do that with SendMessage/GetMessage ???
Title: Re: Interesting alternate use for an API
Post by: Magnum on December 12, 2010, 10:05:26 PM
O.K.

I thought too much was alright, didn't want a buffer overflow.

Title: Re: Interesting alternate use for an API
Post by: donkey on December 12, 2010, 11:13:35 PM
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 (?)
Title: Re: Interesting alternate use for an API
Post by: jj2007 on December 12, 2010, 11:16:45 PM
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
Title: Re: Interesting alternate use for an API
Post by: donkey on December 12, 2010, 11:17:33 PM
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.
Title: Re: Interesting alternate use for an API
Post by: 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?
Title: Re: Interesting alternate use for an API
Post by: 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.

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
Title: Re: Interesting alternate use for an API
Post by: Antariy on December 12, 2010, 11:41:51 PM
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
Title: Re: Interesting alternate use for an API
Post by: donkey on December 13, 2010, 12:04:46 AM
Yup, you're right, the message remains until the Windows session ends.
Title: Re: Interesting alternate use for an API
Post by: jj2007 on December 13, 2010, 12:09:41 AM
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
Title: Re: Interesting alternate use for an API
Post by: Antariy on December 13, 2010, 12:14:03 AM
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.
Title: Re: Interesting alternate use for an API
Post by: dedndave on December 13, 2010, 01:51:50 AM
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
Title: Re: Interesting alternate use for an API
Post by: jj2007 on December 13, 2010, 02:40:32 AM
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.
Title: Re: Interesting alternate use for an API
Post by: dedndave on December 13, 2010, 03:21:33 AM
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
Title: Re: Interesting alternate use for an API
Post by: jj2007 on December 13, 2010, 04:17:42 AM
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.
Title: Re: Interesting alternate use for an API
Post by: dedndave on December 13, 2010, 04:50:51 AM
that's what i said   :bg