FWIW, I was trying out using the 'Safe String' functions from MASM32. You will need 'strsafe.lib' from the Platform SDK. 'strsafe.lib' in turn requires 'msvcrt.inc' and 'msvcrt.lib' available in this forum.
The documentation is here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/strings/usingstrsafefunctions.asp
The test program:
.586
.model flat, stdcall
option casemap:none
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
include c:\masm32\msvcrt\msvcrt.inc
include c:\masm32\strsafe\strsafe.inc
includelib c:\masm32\lib\kernel32.lib
includelib c:\masm32\msvcrt\msvcrt.lib
includelib c:\masm32\strsafe\strsafe.lib
.DATA
align 8
Pi REAL8 0.0
align 4
dwLen DWORD 0
szBuf1 BYTE 64 dup(0)
szBuf2 BYTE 64 dup(0)
szBuf3 BYTE 128 dup(0)
szMsg1 BYTE " Pi to ", 0
szMsg2 BYTE " digits = ", 0
szPAK BYTE 13, 10, "Press any key to continue...", 0
szCrLf BYTE 13, 10, 0
szFmt1 BYTE "%.17f", 0
szFmt2 BYTE "%u", 0
szFmt3 BYTE "%s", 0
.CODE
start:
finit
fldpi
fstp Pi
invoke StringCbPrintf, OFFSET szBuf2, SIZEOF szBuf2, OFFSET szFmt1, Pi
invoke StringCbLength, OFFSET szBuf2, SIZEOF szBuf2, OFFSET dwLen
dec dwLen
invoke StringCbPrintf, OFFSET szBuf1, SIZEOF szBuf1, OFFSET szFmt2, dwLen
invoke StringCbCopy, OFFSET szBuf3, SIZEOF szBuf3, OFFSET szCrLf
invoke StringCbCat, OFFSET szBuf3, SIZEOF szBuf3, OFFSET szMsg1
invoke StringCbCat, OFFSET szBuf3, SIZEOF szBuf3, OFFSET szBuf1
invoke StringCbCat, OFFSET szBuf3, SIZEOF szBuf3, OFFSET szMsg2
invoke StringCbCat, OFFSET szBuf3, SIZEOF szBuf3, OFFSET szBuf2
invoke StringCbCat, OFFSET szBuf3, SIZEOF szBuf3, OFFSET szCrLf
invoke printf, OFFSET szFmt3, OFFSET szBuf3
invoke printf, OFFSET szFmt3, OFFSET szPAK
invoke _getch
invoke printf, OFFSET szFmt3, OFFSET szCrLf
invoke ExitProcess, 0
end start
The include file I created, 'strsafe.inc':
; 'Safe String' Byte Count Functions
;
; 'strsafe.h' and 'strsafe.lib' are in the Platform SDK
;
; All functions are STDCALL except
; StringCbPrintfA due to :VARARG
;
; Greg Lyon - March 2005
;
; Tested and working
;
StringCbCatA PROTO :PTR BYTE, :DWORD, :PTR BYTE
StringCbCat EQU <StringCbCatA>
StringCbCopyA PROTO :PTR BYTE, :DWORD, :PTR BYTE
StringCbCopy EQU <StringCbCopyA>
StringCbLengthA PROTO :PTR BYTE, :DWORD, :DWORD
StringCbLength EQU <StringCbLengthA>
StringCbPrintfA PROTO C :PTR BYTE, :DWORD, :PTR BYTE, :VARARG
StringCbPrintf EQU <StringCbPrintfA>
; Not tested
;
;StringCbCatNA PROTO :PTR BYTE, :DWORD, :PTR BYTE, :DWORD
;StringCbCatN EQU <StringCbCatNA>
;
;StringCbCopyNA PROTO :PTR BYTE, :DWORD, :PTR BYTE, :DWORD
;StringCbCopyN EQU <StringCbCopyNA>
;
;StringCbVPrintfA PROTO :PTR BYTE, :DWORD, :PTR BYTE, :PTR BYTE
;StringCbVPrintf EQU <StringCbVPrintfA>
An example of error checking for the 'strsafe.h' functions:
invoke StringCbPrintf, OFFSET szBuf2, SIZEOF szBuf2, OFFSET szFmt1, Pi
.if (SDWORD PTR eax < 0)
jmp error
.endif
These functions return FAILED or SUCCEEDED. FAILED is anything < 0, SUCCEEDED is anything >= 0.
The SDWORD PTR is so eax will be treated as signed, the default is it is treated as unsigned.