windows-nt/Source/XPSP1/NT/admin/activec/base/mmcerror.cpp
2020-09-26 16:20:57 +08:00

545 lines
14 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1999
//
// File: mmcerror.cpp
//
// Contents: Class definitions for mmc debug support code.
//
// History: 15-Jul-99 VivekJ Created
//
//--------------------------------------------------------------------------
#include "stdafx.h"
#include "conuistr.h" // needed for IDR_MAINFRAME
#define cchMaxSmallLine 256
#ifdef DBG
CTraceTag tagSCConversion(TEXT("SC"), TEXT("Conversion"));
CTraceTag tagCallDump( TEXT("Function calls"), TEXT("ALL") );
#endif //DBG
//############################################################################
//############################################################################
//
// Definition of GetStringModule() - used by all binaries
//
//############################################################################
//############################################################################
HINSTANCE GetStringModule()
{
return SC::GetHinst();
}
//############################################################################
//############################################################################
//
// Implementation of class SC
//
//############################################################################
//############################################################################
// static variables
HINSTANCE SC::s_hInst = 0;
HWND SC::s_hWnd = NULL;
DWORD SC::s_dwMainThreadID = -1;
#ifdef DBG
UINT SC::s_CallDepth = 0;
#endif
// accessors for the static variables.
void
SC::SetHinst(HINSTANCE hInst)
{
s_hInst = hInst;
}
void
SC::SetHWnd(HWND hWnd)
{
s_hWnd = hWnd;
}
void
SC::SetMainThreadID(DWORD dwThreadID)
{
ASSERT(-1 != dwThreadID);
s_dwMainThreadID = dwThreadID;
}
#ifdef DBG
SC&
SC::operator = (const SC& other)
{
m_facility = other.m_facility;
m_value = other.m_value;
return *this;
}
SC::SC(const SC& other)
: m_szFunctionName(NULL),
m_szSnapinName(NULL)
{
*this = other;
}
/*+-------------------------------------------------------------------------*
*
* SC::SetFunctionName
*
* PURPOSE: Sets the debug function name to the supplied string.
*
* PARAMETERS:
* LPCTSTR szFunctionName : the supplied string.
*
* RETURNS:
* inline void
*
*+-------------------------------------------------------------------------*/
inline void SC::SetFunctionName(LPCTSTR szFunctionName)
{
m_szFunctionName = szFunctionName;
INCREMENT_CALL_DEPTH();
// This computes the format string based on the call depth.
// eg if s_CallDepth is 4, the string is " %s" (four spaces)
// if s_CallDepth is 5, the string is " %s" (five spaces)
LPCTSTR szFormatString = TEXT(" %s");
UINT maxLen = _tcslen(szFormatString);
UINT formatLen = s_CallDepth + 2; // the -2 is for the "%s"
formatLen = (formatLen < maxLen ? formatLen : maxLen);
Trace(tagCallDump, szFormatString + (maxLen - formatLen), szFunctionName);
}
#endif
/*+-------------------------------------------------------------------------*
*
* SC::ToHr
*
* PURPOSE: Converts from a status code (SC) to an HRESULT. USE SPARINGLY.
*
* PARAMETERS: None
*
* RETURNS:
* HRESULT
*
*+-------------------------------------------------------------------------*/
HRESULT
SC::ToHr() const
{
HRESULT hr = S_OK;
switch(GetFacility())
{
default:
ASSERT(0 && "Should not come here.");
break;
case FACILITY_WIN:
hr = HRESULT_FROM_WIN32 (GetCode());
break;
case FACILITY_MMC:
Trace (tagSCConversion, _T("Converting from MMC error code to HRESULT, probable loss of fidelity"), *this);
hr = (GetCode() != 0) ? E_UNEXPECTED : S_OK;
break;
case FACILITY_HRESULT:
hr = (HRESULT) GetCode();
break;
}
return hr;
}
/*+-------------------------------------------------------------------------*
*
* SC::GetErrorMessage
*
* PURPOSE: Writes the error message corresponding to the error code to
* the buffer pointed to by szMessage.
*
* PARAMETERS:
* UINT maxLength : The maximum no of characters to output.
* LPTSTR szMessage : Pointer to the buffer to use. Must be non-null.
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void SC::GetErrorMessage(UINT maxLength, /*[OUT]*/ LPTSTR szMessage) const
{
ASSERT(szMessage != NULL && maxLength > 0);
if (szMessage == NULL || maxLength == 0)
return;
szMessage[0] = 0;
switch(GetFacility())
{
default:
ASSERT(0 && "SC::GetErrorMessage: Unknown SC facility.");
break;
case FACILITY_WIN:
case FACILITY_HRESULT:
{
int nChars = 0;
if ( GetCode() == E_UNEXPECTED )
{
nChars = ::LoadString(SC::GetHinst(), IDS_E_UNEXPECTED, szMessage, maxLength);
}
else
{
DWORD dwFlags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
void *lpSource = NULL;
// add XML module to be searched as well
HMODULE hmodXML = GetModuleHandle(_T("msxml.dll"));
if (hmodXML)
{
dwFlags |= FORMAT_MESSAGE_FROM_HMODULE;
lpSource = hmodXML;
}
DWORD dwMessageID = GetCode();
// reverse values made by HRESULT_FROM_WIN32
// Not sure why ::FormatMessage does not work with such values,
// but we need to convert them back, or else there won't be any messages
if ( (dwMessageID & 0xFFFF0000) == ((FACILITY_WIN32 << 16) | 0x80000000) )
dwMessageID &= 0x0000FFFF;
nChars = ::FormatMessage( dwFlags,
lpSource,
dwMessageID,
0, /*dwLangID*/
szMessage, /*lpBuffer*/
maxLength, /*nSize*/
0 /*Arguments*/
);
}
if (nChars)
break;
// if former failed - add a default error
nChars = ::LoadString(SC::GetHinst(), IDS_MESSAGE_NOT_FOUND_ERROR, szMessage, maxLength);
if (nChars == 0)
{
// too bad. we can only use hardcoded one
_tcsncpy(szMessage, _T("Unknown error"), maxLength);
szMessage[maxLength - 1] = 0;
}
}
break;
case FACILITY_MMC:
{
int nChars = ::LoadString(GetHinst(), GetCode(), szMessage, maxLength);
if(nChars == 0) // did not exist
{
nChars = ::LoadString(GetHinst(), IDS_MESSAGE_NOT_FOUND_ERROR, szMessage, maxLength);
ASSERT(nChars > 0);
}
}
break;
}
}
/*+-------------------------------------------------------------------------*
*
* SC::GetHelpID
*
* PURPOSE: Returns the help ID associated with a status code
*
* RETURNS:
* DWORD
*
*+-------------------------------------------------------------------------*/
DWORD
SC::GetHelpID()
{
return 0; // TODO
}
LPCTSTR
SC::GetHelpFile()
{
static TCHAR szFilePath[MAX_PATH] = TEXT("\0");
// set the path if not already set
if(*szFilePath == TEXT('\0') )
{
DWORD dwCnt = ExpandEnvironmentStrings(_T("%WINDIR%\\help\\mmc.chm"), szFilePath, MAX_PATH);
ASSERT(dwCnt != 0);
}
return szFilePath;
}
void SC::Throw() throw(SC)
{
// make exact copy of itself and destroy it (forces all the output)
#ifdef DBG
{
SC sc(*this);
sc.SetFunctionName(m_szFunctionName);
// forget the debug info - it will not be usefull anyway
// This will turn off the Trace on destructor
SetFunctionName(NULL);
}
#endif // DBG
throw(*this);
}
void SC::Throw(HRESULT hr)
{
(*this) = hr;
Throw();
}
/*+-------------------------------------------------------------------------*
*
* SC::FatalError
*
* PURPOSE: Terminates the application.
*
* RETURNS:
* void
*
*+-------------------------------------------------------------------------*/
void
SC::FatalError() const
{
MMCErrorBox(*this);
exit(1);
}
/*+-------------------------------------------------------------------------*
*
* SC::FromLastError
*
* PURPOSE: Fill SC with value from GetLastError.
*
* The SC is guaranteed to contain a failure code (i.e. IsError()
* will return true) when this function returns.
*
* RETURNS: Reference to the current SC
*
*+-------------------------------------------------------------------------*/
SC& SC::FromLastError()
{
FromWin32 (::GetLastError());
/*
* Some APIs will fail without setting extended error information.
* Presumably this function was called in response to an error, so
* we always want this SC to indicate *some* sort of error. If the
* failing API neglected to set extended error information, give
* this SC a generic error code
*/
if (!IsError())
MakeSc (FACILITY_HRESULT, E_FAIL);
ASSERT (IsError());
return (*this);
}
//############################################################################
//############################################################################
//
// Error formatting
//
//############################################################################
//############################################################################
/*
* Purpose: Formats an error message
*
* Parameters:
* ids String describing the operation in progress
* sc Error code describing the problem encountered
* pstrMessage
* the resulting message.
*/
void FormatErrorIds(UINT ids, SC sc, UINT maxLength, /*[OUT]*/ LPTSTR szMessage)
{
TCHAR sz[cchMaxSmallLine];
LoadString(SC::GetHinst(), IDR_MAINFRAME, sz, cchMaxSmallLine);
FormatErrorString(sz, sc, maxLength, szMessage);
}
//
// Returns a short version of an error message associated a given SC.
//
void FormatErrorShort(SC sc, UINT maxLength, /*[OUT]*/ LPTSTR szMessage)
{
FormatErrorString(NULL, sc, maxLength, szMessage, TRUE);
}
//
// FormatErrorString formats an error message from any SC
//
// Parameters:
// szOperation
// String describing the operation in progress
// May be NULL if sc is sufficient.
// szMessage
// the resulting message.
// fShort
// TRUE if you want the error message only (no header/footer)
//
void FormatErrorString(LPCTSTR szOperation, SC sc , UINT maxLength, /*[OUT]*/ LPTSTR szMessage, BOOL fShort)
{
sc.GetErrorMessage(maxLength, szMessage);
// TODO: add p
}
//############################################################################
//############################################################################
//
// MMCErrorBox
//
//############################################################################
//############################################################################
/*
* MMCErrorBox
*
* Purpose: Displays an Error Box for the given SZ.
* NOTE: This is the one that actually puts-up the dialog.
*
* Parameters:
* sz Pointer to the message to display
* fuStyle As per windows MessageBox
*
* Return value:
* int Button Pressed to dismiss the ErrorBox
*/
int MMCErrorBox(LPCTSTR szMessage, UINT fuStyle )
{
INT id;
// If not system modal (background thread), force task modal.
if (!(fuStyle & MB_SYSTEMMODAL))
fuStyle |= MB_TASKMODAL;
TCHAR szCaption[cchMaxSmallLine];
LoadString(SC::GetHinst(), IDR_MAINFRAME, szCaption, cchMaxSmallLine);
// get window to parent the message box
HWND hWndActive = SC::GetHWnd();
// cannot parent on hidden window!
if ( !IsWindowVisible(hWndActive) )
hWndActive = NULL;
id = ::MessageBox(hWndActive, szMessage, szCaption, fuStyle);
return id;
}
/*+-------------------------------------------------------------------------*
*
* MMCErrorBox
*
* PURPOSE: Displays an error box with the specified message and style
*
* PARAMETERS:
* UINT idsOperation :
* UINT fuStyle :
*
* RETURNS:
* int: Button pressed
*
*+-------------------------------------------------------------------------*/
int
MMCErrorBox(UINT idsOperation, UINT fuStyle)
{
TCHAR sz[cchMaxSmallLine];
LoadString(SC::GetHinst(), idsOperation, sz, cchMaxSmallLine);
return MMCErrorBox(sz, fuStyle);
}
/*
* MMCErrorBox
*
* Purpose: Displays a complex Error Box, given the operation
* and the status code
*
* Parameters:
* ids description of the operation that failed.
* SC Status Code to report
* fuStyle As per windows MessageBox
*
* Return value:
* int Button Pressed to dismiss the ErrorBox
*/
int MMCErrorBox(UINT ids, SC sc, UINT fuStyle)
{
TCHAR sz[cchMaxSmallLine];
LoadString(SC::GetHinst(), ids, sz, cchMaxSmallLine);
return MMCErrorBox(sz, sc, fuStyle);
}
/*
* MMCErrorBox
*
* Purpose: Displays a complex Error Box, given the operation
* and the status code
*
* Parameters:
* szOperation Description of the operation that failed.
* sz Status Code to report
* fuStyle As per windows MessageBox
*
* Return value:
* int Button Pressed to dismiss the ErrorBox
*/
int MMCErrorBox(LPCTSTR szOperation, SC sc, UINT fuStyle)
{
TCHAR sz[cchMaxSmallLine];
FormatErrorString(szOperation, sc, cchMaxSmallLine, sz);
return MMCErrorBox(sz, fuStyle);
}
/*
* MMCErrorBox
*
* Purpose: Displays an Error Box for the given Status Code.
*
* Parameters:
* SC Status Code to report
* fuStyle As per windows MessageBox
*
* Return value:
* int Button Pressed to dismiss the ErrorBox
*/
int MMCErrorBox(SC sc, UINT fuStyle)
{
TCHAR sz[cchMaxSmallLine];
FormatErrorString(NULL, sc, cchMaxSmallLine, sz);
return MMCErrorBox(sz, fuStyle);
}