CSysError class:
// error.h #pragma once #include <Windows.h> #include <memory> class CError { public: CError(); virtual ~CError(); virtual const TCHAR* description() const = 0; unsigned long code() const; protected: unsigned long m_errCode; }; class CSysError : public CError { public: CSysError(); virtual ~CSysError(); virtual const TCHAR* description() const override; DWORD bytesInMsg() const; protected: std::shared_ptr<TCHAR> m_errMsg; }; // error.cpp #include "error.h" CError::CError() : m_errCode( 0UL ) {} CError::~CError() {} unsigned long CError::code() const { return m_errCode; } CSysError::CSysError() : CError() , m_errMsg( nullptr ) { DWORD dwErrCode = GetLastError(); HLOCAL pMsgBuf = NULL; FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER , NULL , dwErrCode , MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ) , (PTSTR) &pMsgBuf , 0 , NULL ); if( pMsgBuf != NULL ) { m_errMsg.reset( (TCHAR*) pMsgBuf ); m_errCode = dwErrCode; } else { // LocalFree( pMsgBuf ); } } CSysError::~CSysError() {} const TCHAR* CSysError::description() const { return ( m_errMsg ) ? m_errMsg.get() : __TEXT( "" ); } DWORD CSysError::bytesInMsg() const { if( m_errMsg ) return HeapSize( GetProcessHeap(), HEAP_NO_SERIALIZE, m_errMsg.get() ); return 0UL; } Problem place:
HANDLE hFile = CreateFile( __TEXT( "C:/Users/isnullxbh/Documents/Visual Studio 2015/Projects/winapi/example2.txt" ) , GENERIC_READ | GENERIC_WRITE , FILE_SHARE_READ , NULL , OPEN_EXISTING , NULL , NULL ); if( (unsigned) hFile == 0xffffffff ) { CSysError sysError; const TCHAR* pErrMsg = sysError.description(); DWORD dwBufSizeInBytes = sysError.bytesInMsg(); DWORD dwNumCharsForWrite = dwBufSizeInBytes / sizeof( TCHAR ); DWORD dwWrittenChars = 0; WriteConsole( hSTDErr, (LPCVOID) pErrMsg, dwNumCharsForWrite, &dwWrittenChars, NULL ); if( dwNumCharsForWrite != dwWrittenChars ) { // TODO } } When a destructor is called on a sysError object ( sysError class), indefinite behavior is observed (so to speak): with a release configuration everything goes without errors, with a debug configuration there are problems with std::shared_ptr destruction that complains about an incomplete TCHAR type. What tell me?
