WindowsXP-SP1/enduser/stuff/hhctrl/lasterr.cpp

352 lines
7.9 KiB
C++

///////////////////////////////////////////////////////////
//
// lasterr.cpp - Class which supports the HH_GET_LAST_ERROR function.
// - Included here is the CProcessError class.
//
//
///////////////////////////////////////////////////////////
//
// Include files
//
// Global header
#include "header.h"
#include "hhctrl.h"
// Our header
#include "lasterr.h"
///////////////////////////////////////////////////////////
//
// Internal Classes
//
///////////////////////////////////////////////////////////
//
// CProcessError
//
class CProcessError
{
public:
CProcessError()
: m_processid(0),
m_hr(E_FAIL) // Assumes failure, because we never set it...
{}
// Process Id
DWORD m_processid ;
// Last error for this process id.
HRESULT m_hr ;
};
///////////////////////////////////////////////////////////
//
// CLastError
//
///////////////////////////////////////////////////////////
//
// Constructor
//
CLastError::CLastError()
: m_ProcessErrorArray(NULL),
m_maxindex(0),
m_lastindex(0)
{
}
///////////////////////////////////////////////////////////
//
// Destructor
//
CLastError::~CLastError()
{
// Delete the array.
Finish() ;
}
///////////////////////////////////////////////////////////
//
// Set the error
//
void
CLastError::Set(HRESULT hr)
{
DWORD idProcess = 1 ; //TODO: REMOVE!!!
if (idProcess) // The idProcess might be zero during the conversion process.
{
CProcessError* pProcessError = FindProcess(idProcess) ;
ASSERT(pProcessError) ;
// Set the fields.
pProcessError->m_hr = hr ;
pProcessError->m_processid = idProcess ;
}
}
///////////////////////////////////////////////////////////
//
// Get the error
//
void
CLastError::Get(HRESULT* hr)
{
DWORD idProcess = 1 ; //TODO: REMOVE!!!
if (idProcess)
{
CProcessError* pProcessError = FindProcess(idProcess) ;
ASSERT(pProcessError) ;
*hr = pProcessError->m_hr;
}
}
///////////////////////////////////////////////////////////
//
// Reset the error
//
void
CLastError::Reset()
{
DWORD idProcess = 1 ; //TODO: REMOVE!!!
if (idProcess)
{
CProcessError* pProcessError = FindProcess(idProcess) ;
ASSERT(pProcessError) ;
pProcessError->m_hr = E_FAIL ; // Only call if you have a NULL hwnd. S_OK ;
}
}
///////////////////////////////////////////////////////////
//
// Finish - The whole reason for this function is so we can clean
// things up in DLL process detach.
//
void
CLastError::Finish()
{
// Delete the array.
DeallocateArray(m_ProcessErrorArray) ;
// Set pointer to NULL.
m_ProcessErrorArray = NULL ;
// Reset the other variables.
m_maxindex = 0 ;
m_lastindex = 0 ;
// Just like starting all over.
}
///////////////////////////////////////////////////////////
//
// Internal Helpers
//
///////////////////////////////////////////////////////////
//
// FindProcess - Gets the index number for the process id ;
//
CProcessError*
CLastError::FindProcess(DWORD idProcess)
{
ASSERT( m_lastindex <= m_maxindex) ;
CProcessError* p = m_ProcessErrorArray ;
// Look for the process in the array.
for (int i = 0 ; i < m_lastindex ; i++)
{
if (p->m_processid == idProcess)
{
// Found it!
return p ;
}
p++ ;
}
// Okay, we didn't find the process id.
// Add it on to the end.
return AddProcess() ;
}
///////////////////////////////////////////////////////////
//
// AddProcess - adds a process structure to the array.
//
CProcessError*
CLastError::AddProcess()
{
CProcessError* p = NULL ;
if (m_lastindex < m_maxindex)
{
// Don't need to grow. Just add it to the existing array.
p = &m_ProcessErrorArray[m_lastindex] ;
}
else
{
// We have used up our slots, so we need to allocate more.
int newmaxindex = m_maxindex + c_GrowBy;
// Allocate a new array.
p = AllocateArray(newmaxindex) ;
// Copy existing entries.
for (int i = 0 ; i < m_maxindex ; i++)
{
// Copy the pointers
p[i] = m_ProcessErrorArray[i] ;
}
// Delete the original array.
DeallocateArray(m_ProcessErrorArray) ;
// Use the new array.
m_ProcessErrorArray = p;
// get the pointer.
p = &m_ProcessErrorArray[m_lastindex] ;
// reset the endpoint.
m_maxindex = newmaxindex ;
}
// Increment the index ;
m_lastindex++ ;
// Post condition.
ASSERT(p) ;
return p ;
}
///////////////////////////////////////////////////////////
//
// Allocate Array
//
CProcessError*
CLastError::AllocateArray(int elements)
{
return new CProcessError[elements] ;
}
///////////////////////////////////////////////////////////
//
// Deallocate Array
//
void
CLastError::DeallocateArray(CProcessError* p)
{
// For some reason the heap management code in hhctrl allows memory leaks,
// but doesn't allow global class variables to call delete in their constructors.
if (p)
{
delete [] p ;
}
}
///////////////////////////////////////////////////////////
//
// Public globals.
//
CLastError g_LastError ;
///////////////////////////////////////////////////////////
//
// Global Functions
//
///////////////////////////////////////////////////////////
//
// hhGetLastError
//
HRESULT hhGetLastError(HH_LAST_ERROR* pError)
{
if (!pError &&
IsBadReadPtr((void*) pError, sizeof(HH_LAST_ERROR)) &&
IsBadWritePtr((void*) pError, sizeof(HH_LAST_ERROR)) &&
pError->cbStruct >= sizeof(HH_LAST_ERROR))
{
return E_FAIL;
}
// Get the last error.
g_LastError.Get(&pError->hr) ;
// We got the error, now get the string to go with it.
GetStringFromHr(pError->hr, &pError->description) ;
return S_OK ;
}
///////////////////////////////////////////////////////////
//
// GetStringFromHr
//
HRESULT
GetStringFromHr(HRESULT hr, BSTR* pDescription)
{
// Get the stringid for this error code.
HRESULT hrReturn = E_FAIL ;
*pDescription = NULL ;
if (FAILED(hr))
{
// Currently we don't have any strings to return.
int stringid = ErrorStringId(hr) ;
if (stringid)
{
// Get the string from the resource table.
PCSTR pstr = GetStringResource(stringid) ;
if (pstr[0] != '\0')
{
// Convert to wide.
CWStr wstrError(pstr) ;
// Make it into a BSTR.
*pDescription = ::SysAllocString(wstrError) ;
hrReturn = S_OK ;
}
}
else
{
*pDescription = NULL ;
hrReturn = S_FALSE ;
}
}
// Only return a description if the call failed.
return hrReturn;
}
///////////////////////////////////////////////////////////
//
// ErrorStringId - returns the resource id for a HRESULT.
//
int
ErrorStringId(HRESULT hr)
{
int iReturn ;
switch(hr)
{
case HH_E_NOCONTEXTIDS:
iReturn = IDS_HH_E_NOCONTEXTIDS;
break ;
case HH_E_FILENOTFOUND:
iReturn = IDS_HH_E_FILENOTFOUND;
break ;
case HH_E_INVALIDHELPFILE:
iReturn = IDS_HH_E_INVALIDHELPFILE;
break ;
case HH_E_CONTEXTIDDOESNTEXIT:
iReturn = IDS_HH_E_CONTEXTIDDOESNTEXIT;
break ;
default:
iReturn = 0;
break ;
};
return iReturn ;
}