__inline void TraceW(const wchar_t *format, ...)
{
    if(g_bDebug)
    {
        if (format)
        {
            va_list arglist;
            wchar_t str[4096];

            va_start(arglist, format);
            StringCchVPrintfW(str, 4096, format, arglist);
            StringCbCatW(str, sizeof(str), L"\n");
            if (g_fLogFile)
            {
                FILE *fout = fopen(g_fLogFile, "a+t");
                if (fout)
                {
                    fwprintf(fout, str);
                    fclose(fout);
                }
            }
            
            wprintf(str);
            
            if (g_bDebugString)
            {               
                OutputDebugStringW(str);
            }

            va_end(arglist);
        }
    }
}
Пример #2
0
static BOOL DebugMessageV(DWORD dwSize, LPCWSTR lpszMessage, va_list arglist)
{
    LPWSTR     lpszMsgBuf;
    HRESULT    hr = S_FALSE;


    // Parameter checking.
    if( (NULL == lpszMessage)
            ||
            (0 == dwSize)
      )
    {
        return FALSE;
    }

    // Allocate memory for message buffer.
    lpszMsgBuf = new WCHAR[dwSize + 1];
    if(NULL == lpszMsgBuf)
        return FALSE;

    // Pass the variable parameters to wvsprintf to be formated.
    hr = StringCchVPrintfW (lpszMsgBuf, dwSize, lpszMessage, arglist);
    if ( SUCCEEDED (hr) )
    {
        // Dump string to debug output.
        OutputDebugStringW(lpszMsgBuf);
    }

    // Clean up.
    delete[] lpszMsgBuf;

    return TRUE;
}
Пример #3
0
//------------------------------------------------------------
//描述:安全的字符串格式化函数
void  CCommonFunc::SafeWStringPrintf(wchar_t* strDest, size_t iStrLen, wchar_t* strFormat, ...)
{
	va_list argList;
	va_start(argList, strFormat);
	StringCchVPrintfW(strDest, iStrLen, strFormat, argList);
	va_end(argList);
}
Пример #4
0
int __cdecl 
fwprintfEntry( 
	FILE *stream,
	const wchar_t *format,
	...
	)
{
	PDBG_OUTPUTW Filter;
	PBTR_FILTER_RECORD Record;
	BTR_PROBE_CONTEXT Context;
	FWPRINTF Routine;
	size_t Length;
	ULONG UserLength;
	va_list argptr;
	PULONG_PTR Sp;
	ULONG Result;
	WCHAR buffer[512];
	
	BtrFltGetContext(&Context);
	Routine = Context.Destine;

	//
	// N.B. Maximum support 16 arguments
	//

	Sp = (PULONG_PTR)&format + 1;
	Result = (*Routine)(stream, format, Sp[0], Sp[1], Sp[2], Sp[3], Sp[4],
			   Sp[5], Sp[6], Sp[7], Sp[8], Sp[9], 
			   Sp[10], Sp[11], Sp[12], Sp[13]);

	BtrFltSetContext(&Context);

	__try {

		va_start(argptr, format);
		StringCchVPrintfW(buffer, 512, format, argptr);
		Length = wcslen(buffer) + 1;
		va_end(argptr);

		UserLength = FIELD_OFFSET(DBG_OUTPUTW, Text[Length]);
		Record = BtrFltAllocateRecord(UserLength, DbgUuid, _fwprintf);
		if (!Record) {
			return Result;
		}

		Filter = FILTER_RECORD_POINTER(Record, DBG_OUTPUTW);
		Filter->Length = Length;
		StringCchCopyW(Filter->Text, Length, buffer);

		BtrFltQueueRecord(Record);
	}
	__except (EXCEPTION_EXECUTE_HANDLER) {
		if (Record) {
			BtrFltFreeRecord(Record);
		}		
	}

	return Result;
}
Пример #5
0
/********************************************************************
StrAllocFormattedArgs - allocates or reuses dynamic string memory
and formats it with the passed in args

NOTE: caller is responsible for freeing ppwz even if function fails
********************************************************************/
extern "C" HRESULT DAPI StrAllocFormattedArgs(
	__inout LPWSTR* ppwz,
	__in LPCWSTR wzFormat,
	__in va_list args
	)
{
	Assert(ppwz && wzFormat && *wzFormat);

	HRESULT hr = S_OK;
	DWORD_PTR cch = 0;
	LPWSTR pwzOriginal = NULL;
	DWORD_PTR cchOriginal = 0;

	if (*ppwz)
	{
		cch = MemSize(*ppwz);  // get the count in bytes so we can check if it failed (returns -1)
		if (-1 == cch)
			ExitOnFailure(hr = E_INVALIDARG, "failed to get size of destination string");
		cch /= sizeof(WCHAR);  //convert the count in bytes to count in characters

		cchOriginal = lstrlenW(*ppwz);
	}

	if (0 == cch)   // if there is no space in the string buffer
	{
		cch = 256;
		hr = StrAlloc(ppwz, cch);
		ExitOnFailure1(hr, "failed to allocate string to format: %S", wzFormat);
	}

	// format the message (grow until it fits or there is a failure)
	do
	{
		hr = StringCchVPrintfW(*ppwz, cch, wzFormat, args);
		if (STRSAFE_E_INSUFFICIENT_BUFFER == hr)
		{
			if (!pwzOriginal)
			{
				// this allows you to pass the original string as a formatting argument and not crash
				// save the original string and free it after the printf is complete
				pwzOriginal = *ppwz;
				*ppwz = NULL;
				// StringCchVPrintfW starts writing to the string...
				// NOTE: this hack only works with sprintf(&pwz, "%s ...", pwz, ...);
				pwzOriginal[cchOriginal] = 0;
			}
			cch *= 2;
			hr = StrAlloc(ppwz, cch);
			ExitOnFailure1(hr, "failed to allocate string to format: %S", wzFormat);
			hr = S_FALSE;
		}
	} while (S_FALSE == hr);
	ExitOnFailure(hr, "failed to format string");

LExit:
	ReleaseStr((void*) pwzOriginal);
	return hr;
}
Пример #6
0
void dump( const wchar_t*fmt, ... ) {
  wchar_t buf[ 4096 ];
  va_list va;
  va_start( va, fmt );
  auto r = StringCchVPrintfW( buf, _countof( buf ), fmt, va );  // ignore return value
  va_end( va );
  if ( ok( r ) || r == STRSAFE_E_INSUFFICIENT_BUFFER )
    OutputDebugStringW( buf );
}
Пример #7
0
static VOID
DokanDbgPrintW(LPCWSTR format, ...)
{
	WCHAR buffer[512];
	va_list argp;
	va_start(argp, format);
	StringCchVPrintfW(buffer, 127, format, argp);
    va_end(argp);
	OutputDebugStringW(buffer);
}
Пример #8
0
void
hippoDebugDialog(WCHAR *format, ...)
{
    WCHAR buf[1024];
    va_list vap;
    va_start(vap, format);
    StringCchVPrintfW(buf, sizeof(buf) / sizeof(buf[0]), format, vap);
    va_end(vap);
    MessageBoxW(NULL, buf, L"Hippo Debug", MB_OK);
}
Пример #9
0
void DebugMsg(const WCHAR* pszFormat, ...)
{
    WCHAR buf[1024];
    StringCchPrintfW(buf, sizeof(buf)/sizeof(WCHAR), L"(%lu): ", GetCurrentThreadId());
		va_list arglist;
		va_start(arglist, pszFormat);
		StringCchVPrintfW(&buf[wcslen(buf)], sizeof(buf)/sizeof(WCHAR), pszFormat, arglist);
		va_end(arglist);
    StringCchCatW(buf, sizeof(buf)/sizeof(WCHAR), L"\n");
    OutputDebugStringW(buf);
}
Пример #10
0
//--------------------------------------------------------------------------------------
// Outputs to the debug stream a formatted Unicode string with a variable-argument list.
//--------------------------------------------------------------------------------------
VOID DebugSpewV( LPCWSTR strMsg, ... )
{
    WCHAR strBuffer[512];

    va_list args;
    va_start( args, strMsg );
    StringCchVPrintfW( strBuffer, 512, strMsg, args );
    strBuffer[511] = L'\0';
    va_end( args );

    OutputDebugString( strBuffer );
}
Пример #11
0
void 
hippoDebugLogW(const WCHAR *format, ...) 
{
    WCHAR buf[1024];
    va_list vap;
    va_start (vap, format);
    StringCchVPrintfW(buf, sizeof(buf) / sizeof(buf[0]) - 2, format, vap);
    va_end (vap);

    StringCchCatW(buf, sizeof(buf) / sizeof(buf[0]) - 2, L"\r\n");

    OutputDebugStringW(buf);
}
Пример #12
0
HRESULT StringCchPrintfW(
    LPWSTR pszDest,
    size_t cchDest,
    LPCWSTR pszFormat,
    ...) {
    va_list argList;
    HRESULT result;

    va_start(argList, pszFormat);
    result = StringCchVPrintfW(pszDest, cchDest, pszFormat, argList);
    va_end(argList);

    return result;
}
Пример #13
0
        void AddLog(const wchar_t* lpFormat, ...)
        {
            const int nBufLen = MAX_PATH * 2;
            wchar_t szBuf[nBufLen + 1] = {0};
            va_list ap;
            va_start(ap, lpFormat);
            StringCchVPrintfW(szBuf, nBufLen, lpFormat, ap);
            va_end(ap);
            OutputDebugStringW(szBuf);

            std::wstring sLine = GetTimeHeader();
            sLine.append(szBuf);
            std::string sLineA = CW2A(sLine.c_str(), CP_UTF8).m_psz;
            AddMsgToList(sLineA);
        }
Пример #14
0
void 
hippoDebugLastErr(WCHAR *fmt, ...) 
{
    HippoBSTR str;
    HippoBSTR errstr;
    WCHAR buf[1024];
    HRESULT res = GetLastError();
    va_list vap;
    va_start(vap, fmt);
    StringCchVPrintfW(buf, sizeof(buf) / sizeof(buf[0]), fmt, vap);
    va_end(vap);
    str.Append(buf);
    hippoHresultToString(res, errstr);
    str.Append(errstr);
    MessageBoxW(NULL, str, L"Hippo Debug", MB_OK);
}
Пример #15
0
VOID DXUTOutputDebugStringW(LPCWSTR strMsg, ...)
{
#if defined(DEBUG) || defined(_DEBUG)
    WCHAR strBuffer[512];

    va_list args;
    va_start(args, strMsg);
    StringCchVPrintfW(strBuffer, 512, strMsg, args);
    strBuffer[511] = L'\0';
    va_end(args);

    OutputDebugString(strBuffer);
#else
    UNREFERENCED_PARAMETER(strMsg);
#endif
}
Пример #16
0
int __cdecl 
vfwprintfEntry(
	FILE *stream,
	const wchar_t *format,
	va_list argptr 
	)
{
	PDBG_OUTPUTW Filter;
	PBTR_FILTER_RECORD Record;
	BTR_PROBE_CONTEXT Context;
	VFWPRINTF Routine;
	size_t Length;
	ULONG UserLength;
	ULONG Result;
	WCHAR buffer[512];
	
	BtrFltGetContext(&Context);
	Routine = Context.Destine;
	Result = (*Routine)(stream, format, argptr);
	BtrFltSetContext(&Context);

	__try {

		StringCchVPrintfW(buffer, 512, format, argptr);
		Length = wcslen(buffer) + 1;

		UserLength = FIELD_OFFSET(DBG_OUTPUTW, Text[Length]);
		Record = BtrFltAllocateRecord(UserLength, DbgUuid, _vfwprintf);
		if (!Record) {
			return Result;
		}

		Filter = FILTER_RECORD_POINTER(Record, DBG_OUTPUTW);
		Filter->Length = Length;
		StringCchCopyW(Filter->Text, Length, buffer);

		BtrFltQueueRecord(Record);
	}
	__except (EXCEPTION_EXECUTE_HANDLER) {
		if (Record) {
			BtrFltFreeRecord(Record);
		}		
	}

	return Result;
}
Пример #17
0
	void SPLogHelper::WriteLog( wstring log, ... )
	{
		wofstream outLogFile;

		outLogFile.open("log\\spengine.log", ios::app);

		if (!outLogFile)
		{
			CreatLogFile();
			if (!outLogFile)
				return;
		}

		TCHAR szBuffer[1024];  // Large buffer for long filenames or URLs
		const size_t NUMCHARS = sizeof(szBuffer) / sizeof(szBuffer[0]);
		const int LASTCHAR = NUMCHARS - 1;

		// Format the input string
		va_list pArgs;
		va_start(pArgs, log);

		// Use a bounded buffer size to prevent buffer overruns.  Limit count to
		// character size minus one to allow for a NULL terminating character.
		(void)StringCchVPrintfW(szBuffer, NUMCHARS - 1, log.c_str(), pArgs);
		va_end(pArgs);

		// Ensure that the formatted string is NULL-terminated
		szBuffer[LASTCHAR] = TEXT('\0');

		SYSTEMTIME sys; 
		GetLocalTime( &sys ); 

		wstring str;

		outLogFile <<
			sys.wYear << "-" << 
			setw(2) <<  setfill(L'0') << sys.wMonth << "-" << 
			setw(2) <<  setfill(L'0') << sys.wDay << " "<< 
			setw(2) <<  setfill(L'0') << sys.wHour << ":" <<
			setw(2) <<  setfill(L'0') << sys.wMinute << ":" <<
			setw(2) <<  setfill(L'0') << sys.wSecond << " : " <<
			str.append(szBuffer) << endl;

		outLogFile.close();
	}
Пример #18
0
ULONG _cdecl NFS41DbgPrint( __in LPTSTR Format, ... )
{
    ULONG rc = 0;
    TCHAR szbuffer[256];

    va_list marker;
    va_start( marker, Format );
    {

        //StringCchVPrintfW( szbuffer, 127, Format, marker );
        StringCchVPrintfW( szbuffer, 256, Format, marker );
        szbuffer[255] = (TCHAR)0;
        OutputDebugString( TRACE_TAG );
        OutputDebugString( szbuffer );
    }

    return rc;
}
Пример #19
0
void
TraceMsg (
    _In_ LPWSTR szFormat,
    ...)
{
    static WCHAR szTempBuf[4096];

    va_list arglist;

    va_start(arglist, szFormat);

    StringCchVPrintfW ( szTempBuf,
        celems(szTempBuf),
        szFormat,
        arglist );

    OutputDebugStringW( szTempBuf );

    va_end(arglist);
}
Пример #20
0
void DisplayMsg(WCHAR * format, ...)
{
    va_list     argList;    /* holds the arguement list passed in */
    WCHAR       wbuffer[1024];

    /* get the argument list */
    va_start(argList, format);

    /*
     * using vprintf to perform the printing it is the same is printf, only
     * it takes a va_list or arguements
     */
    if (S_OK != StringCchVPrintfW (wbuffer, sizeof (wbuffer)/sizeof (wbuffer[0]) , format, argList))
    {
        return;
    }

    RETAILMSG(TRUE, (wbuffer));

    return;
}
Пример #21
0
VOID NdLogVar(LOG_OUTPUT_FLAG outputLogFlag, __in __format_string LPCWSTR fmt, ...)
{
	va_list argList;
	va_start(argList, fmt);
	WCHAR szMsg[4096];
	StringCchVPrintfW(szMsg, _countof(szMsg), fmt, argList);
	va_end(argList);

	if (outputLogFlag & LOF_DEBUG_VIEW)
	{
		OutputDebugStringW(szMsg);
	}

	if (outputLogFlag & LOF_PROCESS_MONITOR)
	{
		// ProcMonDebugOutput(szMsg);
	}

	if (outputLogFlag & LOF_FILE)
	{
		//NdFileLog(szMsg);
	}
}
Пример #22
0
VOID NdPerfLog(__in LPCWSTR logfile, __in __format_string LPCWSTR  fmt, ...)
{
	va_list argList;
	va_start(argList, fmt);	
	WCHAR szMsg[4096];
	StringCchVPrintfW(szMsg, _countof(szMsg), fmt, argList);
	va_end(argList);

	//MSG(동기화 추가);
	HANDLE hFile = CreateFile(
		logfile,
		GENERIC_WRITE,
		FILE_SHARE_READ | FILE_SHARE_WRITE,
		NULL,
		OPEN_ALWAYS,
		FILE_ATTRIBUTE_NORMAL,
		NULL
		);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		_stprintf_s(szMsg, L"Cannot create a log file. [errcode: %d][%s]\n", GetLastError(), logfile);
		OutputDebugString(szMsg);
	}
	else
	{
		(VOID)SetFilePointer(hFile, 0, 0, FILE_END);
		std::string s;
		s.append(ToAnsiStr(GetCurrentTimeStr().c_str()));
		s.append(" ");
		s.append(ToAnsiStr(szMsg));
		s.append("");
		DWORD dwWritten;
		(VOID)WriteFile(hFile, s.c_str(), (DWORD)s.size(), &dwWritten, 0);
		CloseHandle(hFile);
	}
}
//---------------------------------------------------------------------------
HRESULT CSimpleDialog::AddStatusMessage(LPCWSTR wszFormat, ...)
{
    HRESULT    hr                          = S_OK;
    HWND       hJobStatus;
    WCHAR      *pwszExistingText           = NULL;
    DWORD      cchExistingText             = 0;
    WCHAR      *pwszBuf                    = NULL;
    DWORD      cchBuf                      = 0;
    SYSTEMTIME Time;
    WCHAR      wszTimeBuf[20]              = {0};
    WCHAR      wszNewText[MAX_BUFFER_SIZE] = {0};
    

    if (!wszFormat)
    {
        return S_OK;
    }

    // 
    // Build a string with the text passed as a parameter
    //
    va_list arglist;
    va_start(arglist, wszFormat);

    hr = StringCchVPrintfW(wszNewText, MAX_BUFFER_SIZE, wszFormat, arglist);
    if (FAILED(hr))
    {
        goto cleanup;
    }

    //
    // Retrieve the text that is currently displayed in the Edit box
    //

    hJobStatus      = GetDlgItem(m_hWnd, IDC_JOBSTATUS);
    cchExistingText = GetWindowTextLength(hJobStatus) + 1;

    if (cchExistingText)
    {
        pwszExistingText = new WCHAR[cchExistingText];
        if (!pwszExistingText)
        {
            hr = E_OUTOFMEMORY;
            goto cleanup;
        }

        GetWindowText(hJobStatus, pwszExistingText, cchExistingText);
    }

    //
    // Get a string for the current time
    //

    GetLocalTime(&Time);
    hr = StringCchPrintfW(wszTimeBuf, ARRAYSIZE(wszTimeBuf), L"[%.2u:%.2u %.2u.%.3us] ", Time.wHour, Time.wMinute, Time.wSecond, Time.wMilliseconds);
    if (FAILED(hr))
    {
        goto cleanup;
    }

    //
    // Allocate a buffer for the new contents of the edit box
    //
    cchBuf  = cchExistingText + static_cast<DWORD>(wcslen(wszTimeBuf)) + static_cast<DWORD>(wcslen(wszNewText)) + 2 + 1;  // 2 for the break line
    pwszBuf = new WCHAR[cchBuf];
    if (!pwszBuf)
    {
        hr = E_OUTOFMEMORY;
        goto cleanup;
    }
    pwszBuf[0] = L'\0';

    //
    // Build the new string
    //
    hr = StringCchPrintfW(pwszBuf, cchBuf, L"%s%s%s\r\n", (pwszExistingText? pwszExistingText : L""), wszTimeBuf, wszNewText);
    if (FAILED(hr))
    {
        goto cleanup;
    }

    //
    // Update the control with the new string
    //
    if (!SetWindowText(hJobStatus, pwszBuf))
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        goto cleanup;
    }

    //
    // Automatically scroll down the edit box
    //
    SendMessage(hJobStatus, EM_SETSEL, (WPARAM)0, (LPARAM)-1);
	SendMessage(hJobStatus, EM_SCROLLCARET, 0, 0);

cleanup:

    va_end(arglist);

    if (pwszExistingText)
    {
        delete [] pwszExistingText;
        pwszExistingText = NULL;
    }

    if (pwszBuf)
    {
        delete [] pwszBuf;
        pwszBuf = NULL;
    }

    return hr;
}
Пример #24
0
INT
cdecl
PlotUIMsgBox(
    HWND    hWnd,
    LONG    IDString,
    LONG    Style,
    ...
)

/*++

Routine Description:

    This function pop up a simple message and let user to press key to
    continue

Arguments:

    hWnd        - Handle to the caller window

    IDString    - String ID to be output with

    ...         - Parameter

Return Value:





Development History:

    06-Dec-1993 Mon 21:31:41 created


Revision History:

    24-Jul-2000 Mon 12:18:12 updated
        Fix for someone's change due to the fact that NULL character is not
        counted for the string


--*/

{
    va_list vaList;
    LPWSTR  pwTitle;
    LPWSTR  pwFormat;
    LPWSTR  pwMessage;
    INT     i;
    INT     MBRet = IDCANCEL;
    HRESULT hr;

    //
    // We assume that UNICODE flag is turn on for the compilation, bug the
    // format string passed to here is ASCII version, so we need to convert
    // it to LPWSTR before the wvsprintf()
    //
    // 24-Jul-2000 Mon 13:17:13 updated
    //  1 MAX_IDS_STR_LEN for pwTitle,
    //  1 MAX_IDS_STR_LEN for pwFormat
    //  2 MAX_IDS_STR_LEN for pwMessage (wvsprintf)
    //

    if (!(pwTitle = (LPWSTR)LocalAlloc(LMEM_FIXED,
                                       sizeof(WCHAR) * MAX_IDS_STR_LEN * 4))) {

        return(0);
    }

    if (i = LoadString(hPlotUIModule,
                       IDS_PLOTTER_DRIVER,
                       pwTitle,
                       MAX_IDS_STR_LEN - 1)) {

        pwFormat = pwTitle + i + 1;

        if (i = LoadString(hPlotUIModule,
                           IDString,
                           pwFormat,
                           MAX_IDS_STR_LEN - 1)) {

            pwMessage = pwFormat + i + 1;

            va_start(vaList, Style);
            hr = StringCchVPrintfW(pwMessage, MAX_IDS_STR_LEN - 1, pwFormat, vaList);
            va_end(vaList);

            if ( SUCCEEDED(hr) )
            {
                MBRet = MessageBox(hWnd, pwMessage, pwTitle, MB_APPLMODAL | Style);
            }
        }
    }


    LocalFree((HLOCAL)pwTitle);

    return(MBRet);
}
Пример #25
0
VOID
cdecl
PlotDbgPrint(
    LPCSTR   pszFormat,
    ...
)

/*++

Routine Description:

    This fucntion output the debug informat to the debugger


Arguments:

    pszFormat   - format string

    ...         - variable data


Return Value:


    VOID

Author:

    15-Nov-1993 Mon 17:57:59 created


Revision History:


--*/

{
    va_list         vaList;

#if defined(UMODE) || defined(USERMODE_DRIVER)

    static WCHAR    wOutBuf[768];
    static WCHAR    wFormatBuf[256];
    size_t          cch;

    //
    // We assume that UNICODE flag is turn on for the compilation, bug the
    // format string passed to here is ASCII version, so we need to convert
    // it to LPWSTR before the wvsprintf()
    //

    if (!SUCCEEDED(StringCchLengthA(pszFormat, CCHOF(wFormatBuf), &cch)))
    {
        return;
    }

    va_start(vaList, pszFormat);
    MultiByteToWideChar(CP_ACP, 0, pszFormat, -1, wFormatBuf, CCHOF(wFormatBuf));
    if (!SUCCEEDED(StringCchVPrintfW(wOutBuf, CCHOF(wOutBuf), wFormatBuf, vaList)))
    {
        return;
    }
    va_end(vaList);

    OutputDebugString((LPCTSTR)wOutBuf);
    OutputDebugString(TEXT("\n"));

#else

    va_start(vaList, pszFormat);
    EngDebugPrint("PLOT",pszFormat,vaList);
    va_end(vaList);

#endif
}
Пример #26
0
void
CRecoveryHandler::PrintW(
	DWORD inPrintWhat,
	LPCWSTR inFormat,
	va_list inArgList)
/*++

Routine Description:

	Does for unicode strings what PrintA does for ascii strings

Arguments:

	refer PrintA

Returns:

	None

--*/
{
	wchar_t szMsg[1024];

	StringCchVPrintfW(
					szMsg,
					sizeof(szMsg)/sizeof(wchar_t),
					inFormat,
					inArgList);

	std::wstring trcMsg = szMsg;

	size_t i_CR = 0;

	while (i_CR != -1)
	{
		i_CR = trcMsg.find_first_of(L'\r', 0);

		if (i_CR != -1)
		{
			trcMsg.erase(i_CR, 1);
		}
	}

	std::wstring lastMsg;
	bool bUseLastMsg = false;

	int itemCount = ListView_GetItemCount(m_hwndListCtrl);
	if (itemCount > 0)
	{
		LVITEMW lastLvItem;
		ZeroMemory(&lastLvItem, sizeof(LVITEMW));
		lastLvItem.mask			= LVIF_TEXT | LVIF_PARAM;
		lastLvItem.pszText		= szMsg;
		lastLvItem.cchTextMax	= 512;
		lastLvItem.iItem		= itemCount - 1;
		lastLvItem.iSubItem		= 0;
		SendMessageW(m_hwndListCtrl, LVM_GETITEMW, 0, (LPARAM)&lastLvItem);

		if ((lastLvItem.lParam & 0x80000000) == 0 &&
			(lastLvItem.lParam & 0xFF) == inPrintWhat)
		{
			bUseLastMsg = true;
			lastMsg = lastLvItem.pszText;
			itemCount--;
		}
	}

	size_t i_begin = 0;
    size_t i_end = 0;

	do
	{
		if (i_begin >= trcMsg.length())
		{
			break;
		}

		DWORD templParam = 0;
		std::wstring newMsg;

		i_end = trcMsg.find_first_of('\n', i_begin);

		if (i_end != -1)
		{
			templParam = 0x80000000;
			newMsg = trcMsg.substr(i_begin, i_end - i_begin);
			i_begin = i_end + 1;
		}
		else
		{
			newMsg = trcMsg.substr(i_begin, trcMsg.length() - i_begin);
		}


		newMsg = lastMsg + newMsg;
		lastMsg = L"";

		LVITEMW lvItem;
		ZeroMemory(&lvItem, sizeof(LVITEMW));
		lvItem.mask		= LVIF_TEXT | LVIF_PARAM;
		lvItem.iItem	= itemCount++;
		lvItem.iSubItem = 0;
		lvItem.pszText	= (LPWSTR)newMsg.c_str();
		lvItem.lParam	= inPrintWhat | templParam;

		if(bUseLastMsg)
		{
			bUseLastMsg = false;
			SendMessageW(m_hwndListCtrl, LVM_SETITEMW, 0, (LPARAM)&lvItem);
		}
		else
		{
			SendMessageW(m_hwndListCtrl, LVM_INSERTITEMW, 0, (LPARAM)&lvItem);
			ListView_EnsureVisible(m_hwndListCtrl, itemCount - 1, FALSE);
		}
	}while (i_end != -1);
}