You should never use LOCAL variables with PostMessage, unless you can somehow make absolutely sure that the data will still be available when the message is processed by the recipient. Since locals are in the stack, they are gone when the function returns, so it's better to use globals, or memory objects. (As a side note, you also can't use pointers to any kind of data if the recipient happens to be in a different process. This is not related to your problem, but it was worth mentioning).

If using globals does not solve the problem, perhaps there is a bug somewhere else? I'm not very familiar with C, but are you sure you're passing a pointer to PostMessage? Those kind of bugs are quite tricky to find...
Posted on 2003-09-17 17:48:20 by QvasiModo
well, the globar var i use is a char variable with x size.
passing the variable actually gives the pointer to it, so thats probably the problem.
that means we can't send text messages with post message than?
Posted on 2003-09-23 07:40:31 by wizzra
You can pass test messages to PostMessage. All you have to do is make sure that the pointer will remain valid (and the data will still be there) by the time the message is processed. That means if you're sending a WM_SETTEXT message, when the GUI thread processes it the window procedure of your control will try to read the string at the address you specified. So it must be a global variable (or a heap memory object), and the data must still be there. And of course, you must pass a pointer (not the first char of the string, converted to DWORD). I used to program in C quite some time ago (back in DOS days :) ) and I remember it was kind of confusing to figure out how to pass a pointer correctly. I find assembler to be a bit more clear in that aspect. If it's still failing, you could take advantage of the fact that you know assembly ;) and open the EXE with OllyDbg, then see exactly what did the compiler make of your code...
Posted on 2003-09-23 10:27:39 by QvasiModo
ok, lets see what we get than.

extern char Buffer[128]; // global var

c:


for(...){
wsprintf(Buffer,"Processing Address: %08X",Disasm.Address);
PostMessage(GetDlgItem(mainhWnd,IDC_MESSAGE1),WM_SETTEXT,0,(LPARAM)Buffer);
}


asm


0041C8AB . 51 PUSH ECX ; /<%08X>
0041C8AC . 68 D89D4500 PUSH keygen2.00459DD8 ; |Format = "Processing Address: %08X"
0041C8B1 . 68 4C1E4600 PUSH OFFSET keygen2.Buffer ; |s = OFFSET keygen2.Buffer
0041C8B6 . FF15 74564600 CALL DWORD PTR DS:[<&USER32.wsprintfA>] ; \wsprintfA
0041C8BC . 83C4 0C ADD ESP,0C
0041C8BF . 3BF4 CMP ESI,ESP
0041C8C1 . E8 2ADC0100 CALL keygen2.__chkesp
0041C8C6 . 8BF4 MOV ESI,ESP
0041C8C8 . 68 4C1E4600 PUSH OFFSET keygen2.Buffer ; "Processing Address: 00401000"
0041C8CD . 6A 00 PUSH 0
0041C8CF . 6A 0C PUSH 0C
0041C8D1 . 8BFC MOV EDI,ESP
0041C8D3 . 68 37040000 PUSH 437 ; /ControlID = 437 (1079.) (IDC_MESSAGE1)
0041C8D8 . 8B15 6C254600 MOV EDX,DWORD PTR DS:[mainhWnd] ; |
0041C8DE . 52 PUSH EDX ; |hWnd => 001C03B2 ('PVDasm v1.02d Program Disasse...',class='#32770')
0041C8DF . FF15 A4564600 CALL DWORD PTR DS:[<&USER32.GetDlgItem>] ; \GetDlgItem
0041C8E5 . 3BFC CMP EDI,ESP
0041C8E7 . E8 04DC0100 CALL keygen2.__chkesp
0041C8EC . 50 PUSH EAX ; |hWnd
0041C8ED . FF15 0C564600 CALL DWORD PTR DS:[<&USER32.PostMessageA>] ; \PostMessageA

;EAX = 0



i think that the problem reside in the loop and the PostMessage, since everything is done fastly, the postMessage only queue the message, but wont be processed by the main gui? cuz by than the time we will send a new text next time the loop continues the old one gets overRides and its lost (?).
Posted on 2003-09-23 16:31:18 by wizzra
The problem is that you are using one buffer for all your messages, and PostMessage is a "nonblocking" request for service. That means that PostMessage can (and probably will) return before the data you passed (by pointer) is processed. You will have two threads racing to access the data buffer before the other needs it.

The only thing PostMessage is supposed to do is put the message parameters in the destination message queue. After the message is placed on the queue, PostMessage will not wait for a reply or acknowledgement.
Posted on 2003-09-23 19:28:00 by tenkey
Hi, wizzra
Sorry, I'm not sure what ecxactly your programm does.
Do you really need PostMessages to pass data to another thread?
Since I belive when we call PostMessage, it then (after some time) call WindowProc (this comes from Win16 "multitasking", afaik), I use in some cases a global data area to exchange the data between threads, no PostMessage at all.
Also, it's possible to call WindowProc directly , sometimes.
Posted on 2003-09-23 23:19:50 by S.T.A.S.
@tenkey: yes i know that problem.

@S.T.A.S: yeah, i need to pass information from a worker thread to my gui thread without lossing speed, as sendMessage is slow compare to PostMessage (will w8 for gui to process the data), and i do this allot of times.

Sorry, I'm not sure what ecxactly your programm does.

Disassembler.

i will look at WindowProc thnx.
Posted on 2003-09-24 03:47:16 by wizzra
Hi wizzra
I'm sure you're writting disassembler :)
I'm not sure how bytes are moving ;)
i need to pass information from a worker thread to my gui thread without lossing speed, as sendMessage is slow compare to PostMessage (will w8 for gui to process the data), and i do this allot of times.

Is PostMessage faster than SendMessage? imho, it just don't wait for response.
Isn't it faster to use some kind of movs? May be some sinchronization problem
Posted on 2003-09-24 18:39:25 by S.T.A.S.
I see. The coded is fine, the problem is the message gets overwritten before the GUI thread can process the message.

Is the buffer dedicated to this particular text? If it's not, make it so. That way, if the text gets overwritten it is not so much trouble. You could even synchronize with a mutex to make sure that the control won't display a string while it was being updated (half the old one, half the new one), but I guess it's just a waste of time and effort considering it's just a cosmetic feature. Just make sure that the message gets sent once every several loops (or use a timer for it), and use SendMessage. If you don't send too often, it won't huhrt performance much.

Another option is to post a custom message (WM_USER and on), passing it only numbers (NOT pointers to strings, or pointers of any kind). That way, the GUI thread always gets the correct number, and uses it to parse the string. No overwriting, since the buffer is used by the GUI thread only. (Needless to say, avoid having the Worker thread using the same buffer for anything).

S.T.A.S.: No, I don't think PostMessage is faster than SendMessage. It just doesn't wait for completion, wich helps when having two or more threads, so they don't have to wait for each other.

BTW, I think calling the WindProc would not make much difference... the problem is not in the SendMessage API, just in the synchronization.
Posted on 2003-09-24 21:49:00 by QvasiModo
I'm not sure how bytes are moving

na, i only want to display the Current disassembled address on the main GUI from a worker ID, but since the disasm engine do stuff fast and send info to the maon gui i must not w8 to it to process and continue, i want to queue the messages, all works fine untill u work with text/pointers.

thnx QvasiModo.
Posted on 2003-09-24 23:58:11 by wizzra
QvasiModo ,
...when having two or more threads, so they don't have to wait for each other.
imho, if we have just one CPU then threads can't be executed simultaneously :)

Yes, calling the WindProc would not make much difference... (but we're able to do this in asm)
the problem is not in the SendMessage API, just in the synchronization.

I sometimes get problems with some APIs (problems with reading docs :grin: )
So, in some cases it's easyer to write a few bytes of my own "api"

wizzra, this code seems to me strange
0041C8C8   . 68 4C1E4600    PUSH OFFSET keygen2.Buffer       ; "Processing Address: 00401000"
as far as i can understand your other thread already knows this value
May be it's possible to add one flag to this stru?ture and set it when you fill the buffer, it coud be used as "mutex" as well. Maybe you'll need a "ring buffer".
And no PostMessage at all.
Posted on 2003-09-25 00:30:24 by S.T.A.S.

QvasiModo ,
...when having two or more threads, so they don't have to wait for each other.
imho, if we have just one CPU then threads can't be executed simultaneously :)


Duh! :)
Of course you're right. But that's not the point... I mean that SendMessage waits for message processing to finish. So:

Thread 1: Posts the message and waits.
Thread 2: After it finishes doing whatever it was doing, it processes our message.
Thread 2: Now it's done, return from WinProc.
Thread 1: Returns from SendMessage.

There is a waste of time here... thread 1 has to wait for thread 1 to conclude a cosmetic task :P
Using PostMessage in a clever way can allow you to have thread 1 keep working while thread 2 does it's stuff. Take a look at the rest of the thread, you'll see wizzra's problems have mostly been solved by this. This particular issue is related to a bad buffering, not PostMessage.

So indeed, the buffer is static (maybe somewhere in your .data section, wizzra?) so it gets overwritten all the time. So there are two choices:

- Screw performance, and use SendMessage just because it's easier and the program looks pretty anyway :grin:
- Use a better system to let the GUI thread know what message to show instead.

That's why I proposed using WM_USER, passing it the same data currently used by Worker thread to parse the message string. That way if GUI thread uses it's own buffer for this, there is no conflict or synch problem at all.

So this could happen:

- Thread 1: Posts message and keeps going.
- Thread 2: Still working.
- Thread 1: Posts another message.
- Thread 2: Processing the first msg.
- Thread 1: Keeps working... it doesn't wait for thread 1 at all :)
- Thread 2: Process the second message...
etc.

This is bad if the buffer is used over and over. But if thread 1 sends numbers instead, there is no problem. Just that the messages might be shown too late, but the user will never know that :)
Posted on 2003-09-25 18:18:32 by QvasiModo
Originally posted by QvasiModo
... This particular issue is related to a bad buffering, not PostMessage...

so, ring buffer may be a solution (maybe it's wrong term :confused: )
anyway i like to do this stuff without PostMessage (just paranoia :tongue: )
Posted on 2003-09-25 18:33:57 by S.T.A.S.


so, ring buffer may be a solution (maybe it's wrong term :confused: )
anyway i like to do this stuff without PostMessage (just paranoia :tongue: )

:grin:
Yes, a ring buffer would work. I've seen it described as a "ring queue" or a "circular queue". But since the message queue is a queue (duh! :grin: ) you can try using it too, although there's a limit of 64 bytes of data per message (not counting the message code itself and the window handle, of course).
Posted on 2003-09-25 18:40:50 by QvasiModo
a limit of 64 bytes of data per message
I don't like limits, i belive bugs come from there :grin:
Posted on 2003-09-25 18:57:03 by S.T.A.S.
hi all, and thnx for ur ideas.
S.T.A.S's idea is nice, so post numbers insted of using a overwriten data (char) all the time.
but i never treid working with WM_USER's message.
so, if i post a WM_USER message i need to check in the MessageLoop if its has been sent? than i could get the number from the lParam ?
hope u have a small example for me.
something like:

Worker thread: PostMessage(gui_hwnd,WM_USER,0,(LPARAM)12345678);

Gui thread: at message loop i need to check if WM_USER has been posted..how?
hm..
can i do:


.IF uMsg == WM_USER
mov eax,lParam
.ENDIF

?

thnx all.
Posted on 2003-09-26 04:35:43 by wizzra
Originally posted by wizzra S.T.A.S's idea is nice, so post numbers insted of using a overwriten data (char) all the time.

:confused:
My english really sux :mad:

Sorry, you misunderstood me.
I don't use PostMessage :(

I use: MConOut "blablabla"

My example is in attachment.
I'm afraid, it'll not help, since your case is more complicated, and you have to use PostMessage, but still...
Posted on 2003-09-26 05:10:22 by S.T.A.S.
Wizzra, actually I was proposing to use WM_USER. STAS idea was a bit more evolved than that.
Anyway, yes, WM_USER is a message that you can process at the WindowProc, DlgProc or whatever. Just add it to your IF construct.
In fact, take a look at WIN32.HLP (or MSDN for that matter), there was somewhere (I promess to post it later) an explanation on message queues that explained the use of custom messages (messages greater than WM_USER). But in a nutshell, you can use the WM_USER equate to build your own messages... like this:
.if uMsg == WM_USER

; do some stuff here. wParam and lParam are set in the call to
; PostMessage, SendMessage or whatever.
.elseif uMsg == WM_USER + 1
;our second custom message
.elseif uMsg == WM_USER + 2
;etc...
.elseif uMsg == WM_USER + 100
;I think it was safe to add up to 400h or so. Messages after that are
;reserved for use with RegisterWindowMessage.
.endif

So if you pass numbers in wParam and lParam, your GUI thread (at the WindowProc) can se those values to parse the message string, instead of receiving it from a buffer.

STAS, I'll take a look at your sample... maybe we can work something out here (probably wizzra's problem will be solved already, but as an academic exercise it's not bad). :)
Posted on 2003-09-26 17:01:53 by QvasiModo
hi QvasiModo,
thnx for the propusal, i played with it now, here is my conclusions, working with USER Messages.

WorkerThread: PostMessage(mainhWnd,WM_USER+1,0,(LPARAM)Disasm.Address);

GUI:


.IF uMsg == WM_USER + 1
mov eax,lParam
invoke wsprintf,addr Buffer,Addr HexConv,eax
invoke SetDlgItemText, hwnd,IDC_MESSAGE1,addr Buffer ; no metter if using sendMessage
.ENDIF


this is the speed/gui result:
at beginning gui is acting slow.. its like its the same effect as if i didn't used postMessage in the worker thread, after few seconds 5-10 gui like going into speed, get bit screwed and job is finished, the gui is locked during this processing (??).
we do see the address changing, but in the buttom line this is not a clean sulotion.
also need to clear that the message posting happens allot of times during the worker thread. (decode engine)

Addition:
i found a solution, not a clean one, but it is way better than nothing (untill there is a sulotion)
as QvasiModo suggested in the beggining about increase the progress bar only if there is a real chage in the %, i used the same idea, every time the progress bar changes, i post the address also, that means, insted of posting the message millions of times, i post only 100 times in diff time interval, which fixes all the gui locking, and speed.
so this is the cleanest solution that i found, and i must say it looks pretty ok.

thnx alot, and i hope there is a sulotion to this 'Message Race' problem.
mabye we need to tell microsoft to do something about it in thier product ;D :grin:

thnx allot QvasiModo & s.t.a.s :alright:
Posted on 2003-09-26 17:32:35 by wizzra
There is nothing "unclean" about your solution, it is the only reasonable one! :grin:

It is not a Windows bug... your program was running so slow because by sending millions of messages you were putting the message queue under a big stress. I mean the overhead of sending so many messages as consuming too many resources.

That's why instead of simply setting a message over and over with the same values, you should only update the display when there is a change, to avoid unnecessary operations. For example, to updte the scroll bar, it is better to use the PBM_STEPIT message (maybe it was spelled differently, I don't remember) instead of recalculating the percentage and setting it again. In general, try to send as few messages as possible between threads (when it's inside the same thread it is different, because the result of a SendMessage to a window in your own thread is not very different to calling the WindowProc yourself).

Anyway, glad you solved your problem. Keep up the good work! :alright:
Posted on 2003-09-26 17:57:25 by QvasiModo