/////////////////////////////////////////////////////////////////////////////////////////
// Project: SP Numeric Edit Control 1.0
//
// File: SpNumericEdit.cpp
//
// Developer(s): Sergei Pavlovsky
// sergei_vp@hotmail.com
// Copyright (c) 2004
//
// Description: Implementation of DLL Exports.
//
// Platforms: Win32, ATL
//
// This code may be used in compiled form in any way you desire. This file may be
// redistributed unmodified by any means PROVIDING it is not sold for profit without
// the authors written consent, and providing that this notice and the authors name
// is included. If the source code in this file is used in any commercial application
// then acknowledgement must be made to the author of this file (in whatever form
// you wish).
//
// This file is provided "as is" with no expressed or implied warranty. The author
// accepts no liability for any damage/loss of business that this product may cause.
/////////////////////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "SpNumericEditModule.h"
#include <vector>
#include "DsgnErrorReportDlg.h"
/////////////////////////////////////////////////////////////////////////////////////////
// CSpNumericEditModule class implementation
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
// Constants
const UINT_PTR CSpNumericEditModule::ms_cchMaxResString = 128;
/////////////////////////////////////////////////////////////////////////////////////////
// Operations: Error handling
BOOL CSpNumericEditModule::LoadTypeLib(ITypeLib** ppiTypeLib)
{
ATLASSERT( ppiTypeLib );
const DWORD cchInitialBuffer = _MAX_PATH;
DWORD cchFileName;
DWORD cchBuffer = 0;
LPWSTR lpFileName = NULL;
do
{
cchBuffer += cchInitialBuffer;
void* lpBuffer = realloc(lpFileName, (cchBuffer + 1) * sizeof(WCHAR));
ATLASSERT( lpBuffer );
if ( !lpBuffer )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_CRT, 0,
IDS_ELR_OUTOFMEMORY);
free(lpFileName);
return FALSE;
}
lpFileName = reinterpret_cast<LPWSTR>(lpBuffer);
cchFileName = ::GetModuleFileNameW(_AtlBaseModule.GetResourceInstance(), lpFileName, cchBuffer);
}
while ( cchBuffer <= cchFileName );
HRESULT hr = ::LoadTypeLib(lpFileName, ppiTypeLib);
ATLASSERT( SUCCEEDED(hr) );
free(lpFileName);
if FAILED(hr)
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0,
IDS_ERCM_LOADTYPELIBRARY);
return FALSE;
}
return TRUE;
}
BOOL CSpNumericEditModule::GetValueTypesTypeInfo(ITypeLib* piTypeLib,
ITypeInfo** ppiTypeInfo)
{
ATLASSERT( piTypeLib );
ATLASSERT( !::IsBadWritePtr(ppiTypeInfo, sizeof(ITypeInfo*)) );
LPCWSTR lpcszTypeID = L"{EC31DA3A-C3C2-47fc-95C4-DA1EF188DCA9}";
// Get ITypeInfo for the ValueTypeConstants enum
GUID guid;
HRESULT hr = IIDFromString((LPOLESTR)lpcszTypeID, &guid);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0,
IDS_ERCM_IIDFROMSTRING);
return FALSE;
}
hr = piTypeLib->GetTypeInfoOfGuid(guid, ppiTypeInfo);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0,
IDS_ERCM_GETTYPEINFOBYID);
return FALSE;
}
return TRUE;
}
BOOL CSpNumericEditModule::GetFormatTypesTypeInfo(ITypeLib* piTypeLib,
ITypeInfo** ppiTypeInfo)
{
ATLASSERT( piTypeLib );
ATLASSERT( !::IsBadWritePtr(ppiTypeInfo, sizeof(ITypeInfo*)) );
LPCWSTR lpcszTypeID = L"{6F72E8CE-CA24-4178-A188-28023968B96D}";
// Get ITypeInfo for the FormatTypeConstants enum
GUID guid;
HRESULT hr = IIDFromString((LPOLESTR)lpcszTypeID, &guid);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0,
IDS_ERCM_IIDFROMSTRING);
return FALSE;
}
hr = piTypeLib->GetTypeInfoOfGuid(guid, ppiTypeInfo);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0,
IDS_ERCM_GETTYPEINFOBYID);
return FALSE;
}
return TRUE;
}
BOOL CSpNumericEditModule::GetFormatPropertiesTypeInfo(ITypeLib* piTypeLib,
ITypeInfo** ppiTypeInfo)
{
ATLASSERT( piTypeLib );
ATLASSERT( !::IsBadWritePtr(ppiTypeInfo, sizeof(ITypeInfo*)) );
LPCWSTR lpcszTypeID = L"{603D0A62-22C4-4ec5-ACD6-2AA4E254840E}";
// Get ITypeInfo for the FormatPropertyConstants enum
GUID guid;
HRESULT hr = IIDFromString((LPOLESTR)lpcszTypeID, &guid);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0,
IDS_ERCM_IIDFROMSTRING);
return FALSE;
}
hr = piTypeLib->GetTypeInfoOfGuid(guid, ppiTypeInfo);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0,
IDS_ERCM_GETTYPEINFOBYID);
return FALSE;
}
return TRUE;
}
BOOL CSpNumericEditModule::ConvertEnumValueName(ITypeInfo* piTypeInfo,
LPCOLESTR lpszName,
LONG* plValue)
{
ATLASSERT( piTypeInfo );
ATLASSERT( !::IsBadWritePtr(plValue, sizeof(LONG)) );
*plValue = 0;
// Define number of constants in the enum
TYPEATTR* pta;
HRESULT hr = piTypeInfo->GetTypeAttr(&pta);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0,
IDS_ERCM_GETTYPEINFORMATIONATTRIBUTE);
return FALSE;
}
WORD cVars = pta->cVars;
piTypeInfo->ReleaseTypeAttr(pta);
// Add constants names and values to the combobox
for ( WORD i = 0; i < cVars; i++ )
{
VARDESC* pvd = NULL;
hr = piTypeInfo->GetVarDesc(i, &pvd);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETTYPEINFORMATIONVAR);
return FALSE;
}
LONG lCurrValue = pvd->lpvarValue->lVal;
MEMBERID memid = pvd->memid;
piTypeInfo->ReleaseVarDesc(pvd);
CComBSTR cbsCurrName;
hr = piTypeInfo->GetDocumentation(memid, &cbsCurrName, NULL, NULL, NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETTYPEINFORMATIONDOC);
return FALSE;
}
if ( cbsCurrName == lpszName )
{
*plValue = lCurrValue;
break;
}
}
if ( i == cVars )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_FINDTYPEINFORMATIONVALUE);
return FALSE;
}
return TRUE;
}
BOOL CSpNumericEditModule::ConvertEnumValueName(ITypeInfo* piTypeInfo, LONG lValue,
BSTR* pbsName)
{
ATLASSERT( piTypeInfo );
ATLASSERT( !::IsBadWritePtr(pbsName, sizeof(BSTR)) );
*pbsName = NULL;
// Define number of constants in the enum
TYPEATTR* pta;
HRESULT hr = piTypeInfo->GetTypeAttr(&pta);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_COM, 0,
IDS_ERCM_GETTYPEINFORMATIONATTRIBUTE);
return FALSE;
}
WORD cVars = pta->cVars;
piTypeInfo->ReleaseTypeAttr(pta);
// Add constants names and values to the combobox
for ( WORD i = 0; i < cVars; i++ )
{
VARDESC* pvd = NULL;
hr = piTypeInfo->GetVarDesc(i, &pvd);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETTYPEINFORMATIONVAR);
return FALSE;
}
MEMBERID memid = pvd->memid;
LONG lCurrValue = pvd->lpvarValue->lVal;
piTypeInfo->ReleaseVarDesc(pvd);
if ( lValue == lCurrValue )
{
hr = piTypeInfo->GetDocumentation(memid, pbsName, NULL, NULL, NULL);
ATLASSERT( SUCCEEDED(hr) );
if ( FAILED(hr) )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_GETTYPEINFORMATIONDOC);
return FALSE;
}
break;
}
}
if ( i == cVars )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_SPNUMERICEDITBOX, 0,
IDS_ERCM_FINDTYPEINFORMATIONVALUE);
return FALSE;
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Operations: Resources
UINT_PTR CSpNumericEditModule::LoadString(UINT unID, LPTSTR lpszBuffer,
UINT_PTR cchBuffer)
{
ATLASSERT( !::IsBadWritePtr(lpszBuffer, sizeof(TCHAR) * cchBuffer) );
if ( lpszBuffer )
{
return ::LoadString(_AtlBaseModule.GetResourceInstance(), unID,
lpszBuffer, (int)cchBuffer);
}
else
{
UINT_PTR cchString;
UINT_PTR cchBuffer = 0;
__try
{
do
{
cchBuffer += ms_cchMaxResString;
void* lpBuf = realloc(lpszBuffer, (cchBuffer + 1) * sizeof(TCHAR));
ATLASSERT( lpBuf );
if ( !lpBuf )
{
SP::AccountError(SP::AE_LOG|SP::AE_SETMSG, IDS_ELS_CRT, 0,
IDS_ELR_OUTOFMEMORY);
return 0;
}
lpszBuffer = reinterpret_cast<LPTSTR>(lpBuf);
cchString = ::LoadString(_AtlBaseModule.GetResourceInstance(), unID,
lpszBuffer, int(cchBuffer + 1));
}
while ( cchBuffer <= cchString );
}
__finally
{
free(lpszBuffer);
}
return cchString;
}
}
LPCTSTR CSpNumericEditModule::LoadString(UINT unID, CTCharVector& vecBuffer)
{
if ( !unID )
return NULL;
UINT_PTR cchText = LoadString(unID, NULL, 0);
vecBuffer.resize(cchText + 1);
ATLASSERT( vecBuffer.size() == cchText + 1 );
if ( vecBuffer.size() < cchText + 1 )
return NULL;
LPTSTR lpszText = &vecBuffer.front();
LoadString(unID, lpszText, cchText + 1);
vecBuffer[cchText] = _T('\x0');
return lpszText;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Operations: Error history
void CSpNumericEditModule::LogErrorInfo(LPCTSTR lpcszSource, DWORD dwCode,
LPCTSTR lpcszReason, LPCTSTR lpcszDetails,
DWORD dwHelpContext,
LPCTSTR lpcszHelpFile)
{
// DWORD dwHelpContext = 0,
// LPCTSTR lpcszHelpFile = NULL
m_ejLast.LogEntry(lpcszSource, dwCode, lpcszReason, lpcszDetails,
dwHelpContext, lpcszHelpFile);
}
void CSpNumericEditModule::SetLastErrorInfo(LPCTSTR lpcszSource, DWORD dwCode,
LPCTSTR lpcszReason, LPCTSTR lpcszDetails,
DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
// Set Source
if ( lpcszSource )
m_eiLast.SetSource(lpcszSource, _tcslen(lpcszSource));
else
m_eiLast.SetSource(_T(""), 0);
// Set Code
m_eiLast.SetCode(dwCode);
// Set Reason
if ( lpcszReason )
m_eiLast.SetReason(lpcszReason, _tcslen(lpcszReason));
else
m_eiLast.SetReason(_T(""), 0);
// Set Details
if ( lpcszDetails )
m_eiLast.SetDetails(lpcszDetails, _tcslen(lpcszDetails));
else
m_eiLast.SetDetails(_T(""), 0);
// Set HelpContext
m_eiLast.SetHelpContext(dwHelpContext);
// Set HelpFile
if ( lpcszHelpFile )
m_eiLast.SetHelpFile(lpcszHelpFile, _tcslen(lpcszHelpFile));
else
m_eiLast.SetHelpFile(_T(""), 0);
}
void CSpNumericEditModule::AddReasonToLastError(LPCTSTR lpcszReason)
{
if ( lpcszReason )
m_eiLast.AddReason(lpcszReason, _tcslen(lpcszReason));
}
void CSpNumericEditModule::AttachReportedLog()
{
ATLASSERT( m_ejLast.IsEmpty() );
m_ejLast.Swap(m_ejReported);
}
HRESULT CSpNumericEditModule::ExportReportedLog(IErrorLog* piLog)
{
ATLASSERT( piLog );
UINT_PTR i = m_ejReported.GetEntriesCount();
while ( i-- )
{
const SP::CSMErrorInfo& eiSrc = m_ejReported.GetEntryAt(i);
CComExcepInfo eiDst;
eiDst.wCode = static_cast<WORD>(eiSrc.GetCode());
eiDst.wReserved = 0;
eiDst.bstrSource = ::SysAllocString(CT2OLE(eiSrc.GetSource()));
eiDst.bstrDescription = ::SysAllocString(CT2OLE(eiSrc.GetReason()));
eiDst.bstrHelpFile = ::SysAllocString(CT2OLE(eiSrc.GetHelpFile()));
eiDst.dwHelpContext = eiSrc.GetHelpContext();
eiDst.pvReserved = NULL;
HRESULT hr = piLog->AddError(L"Formatter", &eiDst);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
return E_FAIL;
}
return S_OK;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Helpers: Error report
UINT_PTR CSpNumericEditModule::BuildErrorInfoReport(const SP::CSMErrorInfo& entry,
LPTSTR lpszBuffer, UINT_PTR cchBuffer)
{
ATLASSERT( !::IsBadWritePtr(lpszBuffer, cchBuffer * sizeof(TCHAR)) );
const TCHAR szLF[] = _T("\r\n");
const UINT_PTR cchLF = sizeof(szLF)/sizeof(TCHAR) - 1;
UINT_PTR cchResult = 0;
// Source
LPCTSTR lpcszSource = entry.GetSource();
if ( lpcszSource && *lpcszSource )
{
TCHAR szTitle[128];
_AtlModule.LoadString(IDS_ERRORINFOSOURCE, szTitle, 128);
LPCTSTR lpcszTitle = szTitle;
UINT_PTR cchSource = _tcslen(lpcszSource);
if ( lpszBuffer && *lpcszTitle )
{
while ( cchBuffer && *lpcszTitle )
{
*lpszBuffer++ = *lpcszTitle++;
cchBuffer--;
cchResult++;
}
while ( cchBuffer && *lpcszSource )
{
*lpszBuffer++ = *lpcszSource++;
cchBuffer--;
cchResult++;
}
for ( UINT_PTR i = 0; i < cchLF && cchBuffer; i++ )
{
*lpszBuffer++ = szLF[i];
cchBuffer--;
cchResult++;
}
}
else
{
cchResult += _tcslen(lpcszTitle) + cchSource + cchLF;
}
}
// Reason
LPCTSTR lpcszReason = entry.GetReason();
if ( lpcszReason && *lpcszReason )
{
TCHAR szTitle[128];
_AtlModule.LoadString(IDS_ERRORINFOREASON, szTitle, 128);
LPCTSTR lpcszTitle = szTitle;
UINT_PTR cchReason = _tcslen(lpcszReason);
if ( lpszBuffer && *lpcszTitle )
{
while ( cchBuffer && *lpcszTitle )
{
*lpszBuffer++ = *lpcszTitle++;
cchBuffer--;
cchResult++;
}
while ( cchBuffer && *lpcszReason )
{
*lpszBuffer++ = *lpcszReason++;
cchBuffer--;
cchResult++;
}
for ( UINT_PTR i = 0; i < cchLF && cchBuffer; i++ )
{
*lpszBuffer++ = szLF[i];
cchBuffer--;
cchResult++;
}
}
else
{
cchResult += _tcslen(lpcszTitle) + cchReason + cchLF;
}
}
// Details
LPCTSTR lpcszDetails = entry.GetDetails();
if ( lpcszDetails && *lpcszDetails )
{
TCHAR szTitle[128];
_AtlModule.LoadString(IDS_ERRORINFODETAILS, szTitle, 128);
LPCTSTR lpcszTitle = szTitle;
UINT_PTR cchDetails = _tcslen(lpcszDetails);
if ( lpszBuffer && *lpcszTitle )
{
while ( cchBuffer )
{
*lpszBuffer++ = *lpcszTitle++;
cchBuffer--;
cchResult++;
}
while ( cchBuffer && *lpcszDetails )
{
*lpszBuffer++ = *lpcszDetails++;
cchBuffer--;
cchResult++;
}
for ( UINT_PTR i = 0; i < cchLF && cchBuffer; i++ )
{
*lpszBuffer++ = szLF[i];
cchBuffer--;
cchResult++;
}
}
else
{
cchResult += _tcslen(lpcszTitle) + cchDetails + cchLF;
}
}
return cchResult;
}
UINT_PTR CSpNumericEditModule::BuildErrorLogReport(const SP::CSMErrorJournal ej,
LPTSTR lpszBuffer,
UINT_PTR cchBuffer)
{
ATLASSERT( !::IsBadWritePtr(lpszBuffer, cchBuffer * sizeof(TCHAR)) );
const TCHAR szLF[] = _T("\r\n");
const UINT_PTR cchLF = sizeof(szLF)/sizeof(TCHAR) - 1;
UINT_PTR cchResult = 0;
for ( UINT_PTR i = 0; i < ej.GetCount(); i++ )
{
const SP::CSMErrorInfo& entry = ej.GetEntryAt(i);
UINT_PTR cchWritten = BuildErrorInfoReport(entry, lpszBuffer, cchBuffer);
if ( cchWritten )
{
if ( lpszBuffer )
{
lpszBuffer += cchWritten;
for ( UINT_PTR i = 0; i < cchLF && cchBuffer; i++ )
{
*lpszBuffer++ = szLF[i];
cchBuffer--;
cchResult++;
}
}
else
{
cchResult += cchWritten + cchLF;
}
}
}
return cchResult;
}
void CSpNumericEditModule::ReportComError(const CLSID& clsid, LPCSTR lpszDesc,
const IID& iid, HRESULT hRes)
{
AtlReportError(clsid, lpszDesc, iid, hRes);
}
void CSpNumericEditModule::ReportComError(const CLSID& clsid, LPCSTR lpszDesc,
DWORD dwHelpID, LPCSTR lpszHelpFile,
const IID& iid, HRESULT hRes)
{
AtlReportError(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes);
}
void CSpNumericEditModule::ReportComError(const CLSID& clsid, LPCOLESTR lpszDesc,
const IID& iid, HRESULT hRes)
{
AtlReportError(clsid, lpszDesc, iid, hRes);
}
void CSpNumericEditModule::ReportComError(const CLSID& clsid, LPCOLESTR lpszDesc,
DWORD dwHelpID, LPCOLESTR lpszHelpFile,
const IID& iid, HRESULT hRes)
{
AtlReportError(clsid, lpszDesc, dwHelpID, lpszHelpFile, iid, hRes);
}
void CSpNumericEditModule::ReportComError(const CLSID& clsid, UINT nID, const IID& iid,
HRESULT hRes)
{
AtlReportError(clsid, nID, iid, hRes, _AtlBaseModule.GetResourceInstance());
}
void CSpNumericEditModule::ReportComError(const CLSID& clsid, UINT nID, DWORD dwHelpID,
LPCOLESTR lpszHelpFile, const IID& iid,
HRESULT hRes)
{
AtlReportError(clsid, nID, dwHelpID, lpszHelpFile, iid, hRes,
_AtlBaseModule.GetResourceInstance());
}
/////////////////////////////////////////////////////////////////////////////////////////
// Operations: Error report
void CSpNumericEditModule::ReportLastErrorWithCom(const CLSID& clsid, const IID& iid,
HRESULT hRes)
{
// Put current error journal entries to the report journal
m_ejReported.Clear();
m_ejLast.Swap(m_ejReported);
ReportComError(clsid, CT2OLE(m_eiLast.GetReason()), iid, hRes);
m_eiLast.Clear();
}
void CSpNumericEditModule::ReportLastErrorWithDlg(HWND hWnd)
{
// Put current error journal entries to the report journal
m_ejReported.Clear();
m_ejLast.Swap(m_ejReported);
// Get Log report
UINT_PTR cchLog = BuildErrorLogReport(m_ejReported, NULL, 0);
CTCharVector vecLog(cchLog + 1);
LPTSTR lpszLog = &vecLog.front();
BuildErrorLogReport(m_ejReported, lpszLog, cchLog);
lpszLog[cchLog] = _T('\x0');
// Get Caption
UINT_PTR cchCaption = LoadString(IDS_ERROR, NULL, 0);
CTCharVector vecCaption(cchLog + 1);
LPTSTR lpszCaption = &vecCaption.front();
LoadString(IDS_ERROR, lpszCaption, cchCaption + 1);
lpszCaption[cchCaption] = _T('\x0');
CDsgnErrorReportDlg dlg;
dlg.DoModal(lpszCaption, m_eiLast.GetReason(), lpszLog);
m_eiLast.Clear();
}
INT_PTR CSpNumericEditModule::ReportLastErrorWithDlgEx(HWND hWnd, UINT fDlgParams,
LPCTSTR lpcszCaption,
LPCTSTR lpcszAddMsg)
{
const TCHAR szLF[] = _T("\r\n");
const UINT_PTR cchLF = sizeof(szLF)/sizeof(TCHAR) - 1;
// Put current error journal entries to the report journal
m_ejReported.Clear();
m_ejLast.Swap(m_ejReported);
// Form message
CTCharVector vecMsg;
LPCTSTR lpcszMsg;
if ( lpcszAddMsg )
{
LPCTSTR lpcszReason = m_eiLast.GetReason();
if ( lpcszReason && *lpcszReason )
{
const UINT_PTR cchRsn = m_eiLast.GetReason(NULL, 0);
const UINT_PTR cchAddRsn = _tcslen(lpcszAddMsg);
const UINT_PTR cchMsg = cchRsn + cchAddRsn + cchLF + 1;
vecMsg.resize(cchMsg);
LPTSTR lpszMsg = &vecMsg.front();
m_eiLast.GetReason(lpszMsg, cchRsn);
lpszMsg[cchRsn] = _T('\x0');
_tcscpy(lpszMsg + cchRsn, szLF);
_tcscpy(lpszMsg + cchRsn + cchLF, lpcszAddMsg);
lpcszMsg = lpszMsg;
}
else
{
lpcszMsg = lpcszAddMsg;
}
}
else
{
lpcszMsg = m_eiLast.GetReason();
}
// Form Log report
UINT_PTR cchLog = BuildErrorLogReport(m_ejReported, NULL, 0);
CTCharVector vecLog(cchLog + 1);
LPTSTR lpszLog = &vecLog.front();
BuildErrorLogReport(m_ejReported, lpszLog, cchLog);
lpszLog[cchLog] = _T('\x0');
CDsgnErrorReportDlg dlg;
INT_PTR nResult = dlg.DoModal(lpcszCaption, lpcszMsg, lpszLog, fDlgParams);
m_eiLast.Clear();
return nResult;
}
/////////////////////////////////////////////////////////////////////////////////////////
// Global routines: Error information managing
/////////////////////////////////////////////////////////////////////////////////////////
UINT_PTR SP::LoadErrorString(UINT unID, LPTSTR lpszBuffer, UINT_PTR cchBuffer)
{
return _AtlModule.LoadString(unID, lpszBuffer, cchBuffer);
}
void SP::AccountError(DWORD fOptions, LPCTSTR lpcszSource, DWORD dwCode,
LPCTSTR lpcszReason, LPCTSTR lpcszDetails,
DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
if ( fOptions & SP::AE_LOG )
_AtlModule.LogErrorInfo(lpcszSource, dwCode, lpcszReason, lpcszDetails,
dwHelpContext, lpcszHelpFile);
if ( fOptions & SP::AE_SETLOG )
_AtlModule.AttachReportedLog();
switch ( fOptions & AEM_MSG )
{
case SP::AE_SETMSG:
_AtlModule.SetLastErrorInfo(lpcszSource, dwCode, lpcszReason, lpcszDetails,
dwHelpContext, lpcszHelpFile);
break;
case SP::AE_ADDMSG:
_AtlModule.AddReasonToLastError(lpcszReason);
break;
}
}
void SP::AccountError(DWORD fOptions, UINT unSource, DWORD dwCode,
UINT unReason, UINT unDetails,
DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
CTCharVector vecSource, vecReason, vecDetails;
LPCTSTR lpcszSource = _AtlModule.LoadString(unSource, vecSource);
LPCTSTR lpcszReason = _AtlModule.LoadString(unReason, vecReason);
LPCTSTR lpcszDetails = _AtlModule.LoadString(unDetails, vecDetails);
SP::AccountError(fOptions, lpcszSource, dwCode, lpcszReason, lpcszDetails,
dwHelpContext, lpcszHelpFile);
}
void SP::AccountComError(DWORD fOptions, DWORD dwCode, HRESULT hRes,
IUnknown* piSrc, REFIID riid)
{
ATLASSERT( piSrc );
CComPtr<ISupportErrorInfo> spiSEI;
HRESULT hr = piSrc->QueryInterface(IID_ISupportErrorInfo, (void**)&spiSEI);
if FAILED(hr)
return;
hr = spiSEI->InterfaceSupportsErrorInfo(riid);
if ( hr != S_OK )
return;
CComPtr<IErrorInfo> spiEI;
hr = ::GetErrorInfo(0, &spiEI);
ATLASSERT( SUCCEEDED(hr) );
if FAILED(hr)
return;
// Set Source
CComBSTR cbsSource;
hr = spiEI->GetSource(&cbsSource);
ATLASSERT( SUCCEEDED(hr) );
// Get Reason
CComBSTR cbsReason;
hr = spiEI->GetDescription(&cbsReason);
ATLASSERT( SUCCEEDED(hr) );
// Get HelpContext
DWORD dwHelpContext;
hr = spiEI->GetHelpContext(&dwHelpContext);
ATLASSERT( SUCCEEDED(hr) );
// Get HelpFile
CComBSTR cbsHelpFile;
hr = spiEI->GetHelpFile(&cbsHelpFile);
ATLASSERT( SUCCEEDED(hr) );
SP::AccountError(fOptions, COLE2T(cbsSource), dwCode, COLE2T(cbsReason), NULL,
dwHelpContext, COLE2T(cbsHelpFile));
}
void SP::ReportErrorWithCom(DWORD fOptions, const CLSID& clsid, const IID& iid,
HRESULT hRes, LPCTSTR lpcszSource, DWORD dwCode,
LPCTSTR lpcszReason, LPCTSTR lpcszDetails,
DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
SP::AccountError(fOptions, lpcszSource, dwCode, lpcszReason, lpcszDetails,
dwHelpContext, lpcszHelpFile);
_AtlModule.ReportLastErrorWithCom(clsid, iid, hRes);
}
void SP::ReportErrorWithCom(DWORD fOptions, const CLSID& clsid, const IID& iid,
HRESULT hRes, UINT unSource, DWORD dwCode,
UINT unReason, UINT unDetails,
DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
SP::AccountError(fOptions, unSource, dwCode, unReason, unDetails,
dwHelpContext, lpcszHelpFile);
_AtlModule.ReportLastErrorWithCom(clsid, iid, hRes);
}
void SP::ReportErrorWithDlg(DWORD fOptions, HWND hwndParent,
LPCTSTR lpcszSource, DWORD dwCode, LPCTSTR lpcszReason,
LPCTSTR lpcszDetails,
DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
SP::AccountError(fOptions, lpcszSource, dwCode, lpcszReason, lpcszDetails,
dwHelpContext, lpcszHelpFile);
_AtlModule.ReportLastErrorWithDlg(hwndParent);
}
void SP::ReportErrorWithDlg(DWORD fOptions, HWND hwndParent,
UINT unSource, DWORD dwCode, UINT unReason, UINT unDetails,
DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
SP::AccountError(fOptions, unSource, dwCode, unReason, unDetails,
dwHelpContext, lpcszHelpFile);
_AtlModule.ReportLastErrorWithDlg(hwndParent);
}
INT_PTR SP::ReportErrorWithDlgEx(DWORD fOptions, HWND hwndParent, UINT fDlgParams,
LPCTSTR lpcszCaption, LPCTSTR lpcszAddMsg,
LPCTSTR lpcszSource, DWORD dwCode, LPCTSTR lpcszReason,
LPCTSTR lpcszDetails,
DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
SP::AccountError(fOptions, lpcszSource, dwCode, lpcszReason, lpcszDetails,
dwHelpContext, lpcszHelpFile);
return _AtlModule.ReportLastErrorWithDlgEx(hwndParent, fDlgParams, lpcszCaption,
lpcszAddMsg);
}
INT_PTR SP::ReportErrorWithDlgEx(DWORD fOptions, HWND hwndParent, UINT fDlgParams,
UINT unCaption, UINT unAddMsg,
UINT unSource, DWORD dwCode,
UINT unReason, UINT unDetails,
DWORD dwHelpContext, LPCTSTR lpcszHelpFile)
{
CTCharVector vecCaption, vecAddMsg, vecSource, vecReason, vecDetails;
LPCTSTR lpcszCaption = _AtlModule.LoadString(unCaption, vecCaption);
LPCTSTR lpcszAddMsg = _AtlModule.LoadString(unAddMsg, vecAddMsg);
LPCTSTR lpcszSource = _AtlModule.LoadString(unSource, vecSource);
LPCTSTR lpcszReason = _AtlModule.LoadString(unReason, vecReason);
LPCTSTR lpcszDetails = _AtlModule.LoadString(unDetails, vecDetails);
return SP::ReportErrorWithDlgEx(fOptions, hwndParent, fDlgParams,
lpcszCaption, lpcszAddMsg,
lpcszSource, dwCode, lpcszReason, lpcszDetails,
dwHelpContext, lpcszHelpFile);
}
/////////////////////////////////////////////////////////////////////////////////////////
// Global format designer's utilities
/////////////////////////////////////////////////////////////////////////////////////////
HRESULT __stdcall SpDfGetErrors(IErrorLog* piLog)
{
if ( !piLog )
return E_INVALIDARG;
return _AtlModule.ExportReportedLog(piLog);
}