void CMessageUtil::LOGERROR(const TCHAR* formatString, ...)
{ /*
** Insert the current time..
*/
PrintCurTime();
/*
** Parse the format string and write to the file
*/
if ( formatString == NULL)
{
        /*
** No point in continuiing
*/
return;
}

va_list argList;
/*
** Set va_list to the beginning of optional arguments
*/
va_start(argList, formatString);
const TCHAR* ptr = formatString; while(*ptr != '\0')
{
TCHAR* str = NULL;
int nInteger = 0;
unsigned int unInt = 0;
long lLong = 0;
unsigned long ulLong= 0;
double dDoub = 0; if(*ptr == '%')
{
switch(*(ptr+1))
{
case 's':
str = va_arg(argList, TCHAR*); if( NULL == str)
break;
*this << str;
ptr++;
break; case 'd':
nInteger = va_arg(argList, int);
*this << nInteger;
ptr++;
break; case 'u':
unInt = va_arg(argList, unsigned int);
*this << unInt;
ptr++;
break; case 'l':
ptr++;
if(*(ptr+1) == 'd')
{
lLong = va_arg(argList, long);
*this << lLong;
ptr++;
}
else if(*(ptr+1) == 'u')
{
ulLong = va_arg(argList, unsigned long);
*this << ulLong;
ptr++;
}
break;
case 'f':
dDoub = va_arg(argList, double);
*this << dDoub;
ptr++;
break;
default:
*this << *ptr;
}
} //  if(*ptr == '%')
else
{
*this << *ptr;
}
/*
** Increment pointer..
*/
ptr++;
}
*this << '\n';
}
see source code of CString, it also use va_arg