Hi,

I'm completely puzzled about C calling convention. By looking windows.inc I noticed that the wsprintf uses that C calling convention and :VARARG type parameter. Thats okay no problems with wsprintf.

Now I wan't to code my own wsprintf function basicly to check parameters to avoid possible buffer underruns before calling the real wsprintf.

My wsprintf is declared as follows:



swsprintf PROTO C :DWORD, :DWORD, :VARARG


and the proc itself is:



swsprintf proc uses ebx esi edi lpOut :DWORD, lpFmt :DWORD, :VARARG
ret
swsprintf endp


and I call it like:



invoke swsprintf, ADDR Dummy, CTEXT("It %s", 13, 10), CTEXT("works!")


All this gives me following output when compiled

Assembling: D:\wsprintf_Test\wsprintf_Test.asm
D:\wsprintf_Test\wsprintf_Test.asm(44) : error A2008: syntax error : :
D:\wsprintf_Test\wsprintf_Test.asm(46) : fatal error A1010: unmatched block nesting : swsprintf

That line 44 is the one with swsprintf proc uses...

What I'm doing wrong?

Regards,
Sami
Posted on 2004-05-24 15:03:08 by SamiP
You need variable name in front of :VARARG, e.g.


swsprintf proc lpOut :DWORD, lpFmt :DWORD, arglist:VARARG
[...]
swsprintf endp

and make sure that you specify that you want C calling convention, either by


option language:c

or, by


swsprintf proc C lpOut :DWORD, lpFmt :DWORD, arglist:VARARG
[...]
swsprintf endp
Posted on 2004-05-24 17:13:12 by Starless
Thanks Starless. Now it compiles without error, but how do I know how many parameters I have in "arglist", how do I use those parameters?

Also, do I need to do something to correct stack or does masm do it automatically when the C calling convention is specified?
Posted on 2004-05-25 01:56:46 by SamiP

Also, do I need to do something to correct stack or does masm do it automatically when the C calling convention is specified?


If you use invoke, then the stack is corrected automatically after the call.
Posted on 2004-05-25 02:08:18 by Petroizki
Thanks Petroizki. Normally I use invoke, but I'm curious mind what if I use call and push parameters manually?

Also how can I use those VARARG parameters. Is it something like VARARG+4 VARARG+8 etc. but how do I know how many parameters there are?

Damn, this is hard to me :(
Posted on 2004-05-25 02:44:41 by SamiP
VARARG+4,+8 etc is quite astute of you - yes, thats it.
How many are there? Who knows? MASM handles 30-ish params,
how to detect the end of the params? Two options are:check the stackpointer, or use a Canary value indicating the last param.

StartStack and EndStack are macros written by Ultrano (prompted by me) which can be used either side of a suspect call or block of code, they alert you to stack corruption, tell you by how many bytes and in which direction the stackpointer is invalid, and make an attempt to correct the stack if possible.
Posted on 2004-05-25 03:05:10 by Homer

Normally I use invoke, but I'm curious mind what if I use call and push parameters manually?
Then you would do like this:


push 12
push 23
call myfunc
add esp, 8
Posted on 2004-05-25 06:20:57 by Petroizki
Only true if esp is not repaired at end of stackframe with regards to expected #params ( but we knew this :tongue: )
Posted on 2004-05-25 06:36:29 by Homer

how do I know how many parameters there are?

You parse the format string and find out.
Posted on 2004-05-25 07:17:32 by death
What if the format string and the #parms passed don't agree? I figured that was the point of writing an abstraction proc in the first place here :tongue:
Posted on 2004-05-25 07:20:25 by Homer
Originally posted by SamiP
Also how can I use those VARARG parameters. Is it something like VARARG+4 VARARG+8 etc. but how do I know how many parameters there are?


The VARARG tells the assembler (masm) that the function can accept a variable number of parameter. Because of this fact you have to use C calling convention which means that the caller sets the esp back to the correct value instead of the esp being set back to the correct value by the function you called. If the function is specified as C-calling convention, masm will automaticalyl help you to correct the value in esp by an addition.

Okay back to your question, there are 2 methods. First would be a parameter to tell the function that is called how many parameters there are, or second, you can parse the string format (for wsprintf and related functions) or perhaps like what lingo12 did in his code http://www.asmcommunity.net/board/index.php?topic=13977 where there is a marker to mark the end of the parameters.
Posted on 2004-05-25 07:28:01 by roticv

What if the format string and the #parms passed don't agree?

Then you have a problem :). Or at least, if not enough params were passed, otherwise some just stay unused (which is still wrong but crashes less likely). Another problem is that types don't match (like passing integer 4 to a "%s").

Thomas
Posted on 2004-05-25 08:37:57 by Thomas
Thanks guys!

Now the C calling convention thing is much clearer to me.

Easyest method to achieve what I want/need is to add as last parameter a known value. Reason to make this new proc instead of using wsprintf is to check that the Out buffer is not overflown. Other failure possibilities are mistakes of coder, but something nasty can happen at runtime if user inputs too long string that the program is not expecting.
Posted on 2004-05-25 15:00:47 by SamiP
How about using one of these: StringCbPrintf, StringCbPrintfEx, StringCbVPrintf, StringCbVPrintfEx, StringCchPrintf, StringCchPrintfEx, StringCchVPrintf, or StringCchVPrintfEx
Posted on 2004-05-26 06:10:37 by Aaro
Good point Aaro. StringCbPrintf does exactly what I need and more... so I will definitely check the possibility to use it.
Posted on 2004-05-27 12:25:20 by SamiP
Any advice how to use StringCbPrintf?

I tried to make .inc file with lib2inc provided with masm32 package, but no luck. In the .inc file there are no StringCbPrintf function.
Posted on 2004-05-28 09:40:28 by SamiP