/////////////////////////////////////////////////////////////////////////////
// #ifndef __ARMEN_H__
// #define __ARMEN_H__
// Central Bank of Armenia, Information Security Department
// Armen Hakobyan, 2004. mailto:armen.h@web.am
// http://www.codeproject.com/script/articles/list_articles.asp?userid=25653
// #endif // __ARMEN_H__
/////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "main.h"
#if ( _ATL_VER < _ATL_VER_70 )
#include < atlimpl.cpp >
#endif
#include < LmErr.h >
/////////////////////////////////////////////////////////////////////////////
void DoEvents( void )
{
MSG msg = { 0 };
while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
BOOL bRet = ::GetMessage( &msg, NULL, 0, 0 );
if( bRet == -1 )
continue; // error, don't process
else if( bRet )
{
// Before you translate and dispatch you might consider
// checking if that message does not close you window
// you should ignore it because if you doevents() in a loop
// and the user click the close buton it closes !
// and you loop continues untill it ends:
if( ( msg.message != WM_DESTROY ) &&
( msg.message != WM_CLOSE ) &&
( ( msg.message != WM_SYSCOMMAND ) &&
( msg.wParam != SC_CLOSE ) ) )
{
::TranslateMessage( &msg );
::DispatchMessage( &msg );
}
}
else
break;
}
::Sleep( 0 );
}
/////////////////////////////////////////////////////////////////////////////
void TrimWorkingSet( void )
{
// 1. Compact CRT heap
// 2. Compact process heap
// 3. Minimize process workingset size
_heapmin();
::HeapCompact( ::GetProcessHeap(), 0 );
::SetProcessWorkingSetSize( ::GetCurrentProcess(), (DWORD)-1, (DWORD)-1 );
}
/////////////////////////////////////////////////////////////////////////////
INT _MessageBoxEx( IN UINT uID, IN UINT uType, ... )
{
va_list pszArgList = NULL;
va_start( pszArgList, uType ); /* Initialize variable arguments. */
TCHAR szFmt[ 1024 ] = { 0 };
if( AtlLoadString( uID, szFmt, _countof( szFmt ) ) )
{
TCHAR szOut[ 1024 ] = { 0 };
::wvsprintf( szOut, szFmt, pszArgList );
return _MessageBox( szOut, uType );
}
va_end( pszArgList );
return ( 0 );
}
INT _MessageBox( IN UINT uID, IN UINT uType /*MB_OK | MB_ICONSTOP*/ )
{
TCHAR szBuffer[ 1024 ] = { 0 };
if( AtlLoadString( uID, szBuffer, _countof( szBuffer ) ) )
return _MessageBox( szBuffer, uType );
return ( 0 );
}
INT _MessageBox( IN LPCTSTR pszText, IN UINT uType /*MB_OK | MB_ICONSTOP*/ )
{
return ::MessageBox( ::GetActiveWindow(), pszText, _Module.s_pszAppName, uType );
}
/////////////////////////////////////////////////////////////////////////////
// Not seacrhing just for last ']' occurance because it can also be
// in the user message, not only in the prefix.
// NOT REQUIRED IN DisplayComError, SEE SQLSERVER ODBCPrefix PROPERTY !!!
LPCTSTR SkipODBCPrefix( IN LPCTSTR pszSqlMsg )
{
// ODBC error message format has prefix [0][1][2][optional 3][optional 4]
// For example '[Microsoft][ODBC SQL Server Driver][SQL Server][SQL-DMO]...'
static LPCTSTR sppszPrefixes[ 12 ] = {
_T( "[Microsoft]" ), // 0
_T( "[ODBC Driver Manager]" ), // 1
_T( "[ODBC Cursor Library]" ), // 1
_T( "[ODBC SQL Server Driver]" ), // 1
_T( "[Named Pipes]" ), // 2
_T( "[Shared Memory]" ), // 2
_T( "[Multiprotocol]" ), // 2
_T( "[TCP/IP Sockets]" ), // 2
_T( "[NWLink IPX/SPX]" ), // 2
_T( "[Banyan VINES]" ), // 2
_T( "[SQL Server]" ), // 3
_T( "[SQL-DMO]" ) // 4
};
LPCTSTR pszToken = NULL;
LPCTSTR pszUsrMsg = NULL;
LPCTSTR pszTmpPtr = NULL;
for( INT n = ( _countof( sppszPrefixes ) - 1 ); n >= 0; n-- )
{
pszToken = sppszPrefixes[ n ];
pszTmpPtr = ::StrRStrI( pszSqlMsg, NULL, pszToken );
if( pszTmpPtr )
{
pszTmpPtr += ::lstrlen ( pszToken );
pszUsrMsg = pszTmpPtr;
break;
}
}
return pszSqlMsg; //( pszUsrMsg );
}
void DisplayComError( IN _com_error& e, IN BOOL bExtended )
{
LPTSTR pszMsg = ::StrDup( (LPCTSTR)e.Description() );
if( !pszMsg )
pszMsg = ::StrDup( (LPCTSTR)e.ErrorMessage() );
TCHAR szMsg[ 1024 ] = { 0 };
if( !bExtended )
::lstrcpyn( szMsg, pszMsg, _countof( szMsg ) );
else
{
LPCTSTR pszSrc = ::StrDup( (LPCTSTR)_bstr_t( e.Source() ) );
if( !pszSrc )
pszSrc = ::StrDup( _Module.s_pszAppName );
::wsprintf(
szMsg,
_T( "The program encountered the following error:\n\n" )
_T( "Number:\t\t%d\n" )
_T( "Source:\t\t%s\n" )
_T( "Description:\t%s" ),
HRESULT_CODE( e.Error() ),
pszSrc,
pszMsg
);
_localFree( pszSrc );
}
_localFree( pszMsg );
_MessageBox( szMsg );
}
/////////////////////////////////////////////////////////////////////////////
//
// FUNCTION: FormatMessage()
//
// PURPOSE: This function loads a string from a message file and
// replaces the inserts if necessary (formats).
//
// PARAMETERS: pszMsgDll
// [ in ] - location of the message file
// dwMsgCode
// [ in ] - message identifier for the requested
// message
// dwLangID
// [ in ] - language identifier for the requested
// message
// ppszMsg
// [ out ] - pointer to a pointer variable that
// receives a pointer to an allocated, read-only
// buffer containing the formatted (and null-terminated)
// message. Call the ::HeapFree function to free the
// buffer when you are finished with it.
// ...
// [ in ] - Specifies one or more optional arguments.
// The number and type of argument parameters depend on
// the corresponding format-control specifications that
// the message file was compiled with. These values are
// used as inserts in the formatted message. A %1 in the
// format string indicates the first value; a %2 indicates
/// the second argument; and so on.
//
// RETURN VALUE: Returns last error if fails, ERROR_SUCCESS otherwise.
// See Win API ::FormatMessage for more information.
//
// COMMENTS: 1. Requires #include < LmErr.h >
// 2. Call the ::HeapFree function to free the ppszMsg
// buffer when you are finished with it.
//
// COMPATIBILTY: Microsoft Windows 95 or later, NT 4.0 or later
//
// HISTORY: 15 Nov 2002 - first release
// 21 Nov 2002 - replaced ppszArgs with ... ( va_list )
// 22 Nov 2002 - added MSMQ errors processing
// 24 Nov 2002 - removed r�peated message buffer allocation
//
// LAST REVISION: 24 Nov 2002 by Armen Hakobyan
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//
// SAMPLE USAGE:
//
// // Assuming that the message has format: "%s %s"
//
// LPTSTR pszMsg = NULL;
// LPCTSTR pszArgs[ 2 ] = { _T( "Hello" ), _T( "Armen" ) };
//
// if( FormatMessage( &pszMsg, MSG_PRINTER_INSTALLED,
// pszArgs, _T( "pmsvcmsg.dll" ), 0 ) )
// {
// ::MessageBox( ::GetActiveWindow(), pszMsg,
// _T( "Sample" ), MB_OK | MB_ICONINFORMATION );
//
// ::HeapFree( ::GetProcessHeap(), 0, pszMsg );
// }
//
// // We'll get : "Hello Armen"
// // %s %s
//
/////////////////////////////////////////////////////////////////////////////
DWORD FormatMessage( IN LPCTSTR pszMsgDll,
IN DWORD dwMsgCode,
IN DWORD dwLangID,
OUT LPTSTR* ppszMsg,
IN ... )
{
// No check for pszMsgDll, because
// ::LoadLibraryEx will silently fail later.
ATLASSERT( !::IsBadReadPtr( ppszMsg, sizeof( LPTSTR* ) ) );
HMODULE hModule = NULL;
DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER;
if( pszMsgDll == NULL )
{
if( HRESULT_FACILITY( dwMsgCode ) == FACILITY_MSMQ ) // MSMQ errors only
pszMsgDll = _T( "mqutil.dll" );
else if( dwMsgCode >= NERR_BASE && dwMsgCode <= MAX_NERR ) // Get network errors
pszMsgDll = _T( "netmsg.dll" );
else // Get system errors
dwFlags |= FORMAT_MESSAGE_FROM_SYSTEM;
}
if( pszMsgDll != NULL )
{
hModule = ::LoadLibraryEx( pszMsgDll, NULL, LOAD_LIBRARY_AS_DATAFILE );
if( hModule != NULL )
dwFlags |= FORMAT_MESSAGE_FROM_HMODULE;
else
return ::GetLastError();
}
va_list pszArgs = NULL;
va_start( pszArgs, ppszMsg );
DWORD dwRet = ::FormatMessage( dwFlags, hModule, dwMsgCode, dwLangID,
(LPTSTR)ppszMsg, 0, (va_list*)&pszArgs );
va_end( pszArgs );
return ( dwRet );
}
/////////////////////////////////////////////////////////////////////////////
BOOL CheckDlgItemText( IN HWND hWnd, IN INT nID )
{
ATLASSERT( IS_INTRESOURCE( nID ) );
CWindow wndCtl = ::GetDlgItem( hWnd, nID );
ATLASSERT( wndCtl.IsWindow() );
if( wndCtl.GetWindowTextLength() <= 0 )
{
TCHAR szPar[ 256 ] = { 0 };
if( AtlLoadString( nID, szPar, _countof( szPar ) ) )
_MessageBoxEx( IDP_INVALID_STR, MB_ICONEXCLAMATION | MB_OK, szPar );
else
::MessageBeep( MB_ICONEXCLAMATION );
wndCtl.SetFocus();
return ( FALSE );
}
return ( TRUE );
}
/////////////////////////////////////////////////////////////////////////////
BOOL GetSqlServerPath( IN OUT LPTSTR pszPath,
IN OUT PULONG pulChars,
IN SQL_ROOTS eRoot )
{
ATLASSERT( pszPath != NULL );
ATLASSERT( AtlIsValidString( pszPath, *pulChars ) );
static LPCTSTR spszKeys[ 2 ] = {
_T( "SOFTWARE\\Microsoft\\Microsoft SQL Server\\80\\Tools\\ClientSetup" ),
_T( "SOFTWARE\\Microsoft\\MSSQLServer\\Setup" )
};
CRegKey regKey;
LONG lRetval = regKey.Open( HKEY_LOCAL_MACHINE, spszKeys[ eRoot ] );
if( lRetval == ERROR_SUCCESS )
{
#if defined( _ATL_VER ) && ( _ATL_VER >= _ATL_VER_70 )
lRetval = regKey.QueryStringValue( _T( "SQLPath" ), pszPath, pulChars );
#else
lRetval = regKey.QueryValue( pszPath, _T( "SQLPath" ), pulChars );
#endif
return ( lRetval == ERROR_SUCCESS );
}
return ( FALSE );
}