352 lines
7.5 KiB
C++
352 lines
7.5 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 ;
|
|
}
|
|
|
|
|
|
|
|
|