|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Microsoft WMI OLE DB Provider
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
// Error Routines
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
#include "headers.h"
#define ERROR_GUID_ARRAYSIZE 5
// NTRaid : 111781
// 06/13/00
#define ERROR_DESCRIPTION_SIZE 512
static const ULONG INITIAL_ERROR_QUEUE_SIZE = 10;
CImpISupportErrorInfo::CImpISupportErrorInfo( IUnknown* pUnkOuter) { m_cRef = 0L; m_pUnkOuter = pUnkOuter; m_cpErrInt = 0; m_rgpErrInt = NULL; m_cAllocGuid = 0; }
CImpISupportErrorInfo::~CImpISupportErrorInfo() { SAFE_DELETE_ARRAY(m_rgpErrInt); }
//////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpISupportErrorInfo::AddRef(void) { InterlockedIncrement((long*)&m_cRef); return m_pUnkOuter->AddRef(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpISupportErrorInfo::Release(void) { InterlockedDecrement((long*)&m_cRef); return m_pUnkOuter->Release(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpISupportErrorInfo::QueryInterface( REFIID riid, LPVOID * ppv ) { return m_pUnkOuter->QueryInterface(riid, ppv); }
// Modifications done for
// NTRaid:111765
HRESULT CImpISupportErrorInfo::AddInterfaceID(REFIID riid) { HRESULT hr = S_OK;
if(m_rgpErrInt == NULL) { m_rgpErrInt = new GUID*[ERROR_GUID_ARRAYSIZE];
if(m_rgpErrInt) { m_cAllocGuid = ERROR_GUID_ARRAYSIZE; } else { hr = E_OUTOFMEMORY; } } else if(m_cpErrInt >= m_cAllocGuid) { GUID **pTemp = m_rgpErrInt; m_rgpErrInt = NULL;
m_rgpErrInt = new GUID*[m_cAllocGuid + ERROR_GUID_ARRAYSIZE]; if(m_rgpErrInt) { memset(m_rgpErrInt ,0, (m_cAllocGuid + ERROR_GUID_ARRAYSIZE) * sizeof(GUID*)); memcpy(m_rgpErrInt ,pTemp, m_cAllocGuid * sizeof(GUID*)); m_cAllocGuid += ERROR_GUID_ARRAYSIZE; SAFE_DELETE_ARRAY(pTemp); } else { m_rgpErrInt = pTemp; hr = E_OUTOFMEMORY; } } if(m_rgpErrInt && SUCCEEDED(hr)) { m_rgpErrInt[m_cpErrInt++] = (GUID *)&riid; hr = S_OK; }
return hr; }
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Indicates whether a OLE DB Interface can return OLE DB error objects
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpISupportErrorInfo::InterfaceSupportsErrorInfo( REFIID riid ) { ULONG ul; HRESULT hr = S_FALSE;
//==========================================================================
// See if the interface asked about, actually creates an error object.
//==========================================================================
for(ul=0; ul<m_cpErrInt; ul++){
if ( (*(m_rgpErrInt[ul])) == riid ) { hr = S_OK; break; } } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constructor for this class
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma warning (disable:4355)
CErrorLookup::CErrorLookup( LPUNKNOWN pUnkOuter ) : m_IErrorLookup(this), CBaseObj(BOT_ERROR,pUnkOuter) { } #pragma warning (default:4355)
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns a pointer to a specified interface. Callers use QueryInterface to determine which interfaces
// the called object supports.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CErrorLookup::QueryInterface( REFIID riid, LPVOID * ppv) { if ( ppv == NULL ) return E_INVALIDARG; //=========================================================
// This is the non-delegating IUnknown implementation
//=========================================================
if ( riid == IID_IUnknown ) *ppv = (LPVOID)this; else if ( riid == IID_IErrorLookup ) *ppv = (LPVOID)&m_IErrorLookup; else{ *ppv = NULL; return E_NOINTERFACE; }
((LPUNKNOWN)*ppv)->AddRef(); return S_OK; } ///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Increments a persistence count for the object
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CErrorLookup::AddRef(void) { ULONG cRef = InterlockedIncrement( (long*) &m_cRef); return cRef; } ///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Decrements a persistence count for the object and if persistence count is 0, the object destroys
// itself.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CErrorLookup::Release (void) { ULONG cRef = InterlockedDecrement( (long*) &m_cRef); if ( !cRef ){ delete this; return 0; } return cRef; }
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Increments a reference count for the object.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpIErrorLookup::AddRef(void) { InterlockedIncrement((long*)&m_cRef); return m_pCErrorLookup->AddRef(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Decrement the object's reference count and deletes the object when the new reference count is zero.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpIErrorLookup::Release(void) { InterlockedDecrement((long*)&m_cRef); return m_pCErrorLookup->Release(); } ///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns a pointer to a specified interface. Callers use QueryInterface to determine which interfaces
// the called object supports.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIErrorLookup::QueryInterface( REFIID riid, LPVOID * ppv) { return m_pCErrorLookup->QueryInterface(riid, ppv); } ///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Retrieve the error message and source based on the HRESULT and the provider specific error number
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIErrorLookup::GetErrorDescription( HRESULT hrError, DWORD dwLookupId, DISPPARAMS* pdispparams, LCID lcid, BSTR* ppwszSource, BSTR* ppwszDescription ) { HRESULT hr = NOERROR; int cchBuffer; // NTRaid : 111781
// 06/13/00
WCHAR wszBuffer[ERROR_DESCRIPTION_SIZE];
//=========================================================
// Check the Arguments
//=========================================================
if ( !ppwszSource || !ppwszDescription ) { hr = E_INVALIDARG; } else { //=========================================================
// Initialize return values
//=========================================================
*ppwszSource = NULL; *ppwszDescription = NULL;
// Check the Locale
// if ( lcid != GetSystemDefaultLCID() )
// return DB_E_NOLOCALE;
wcscpy(wszBuffer,L""); WMIOledb_LoadStringW(IDS_WMIOLEDBDES,wszBuffer,ERROR_DESCRIPTION_SIZE); //=========================================================
// Store source name
//=========================================================
*ppwszSource = Wmioledb_SysAllocString(wszBuffer); if ( *ppwszSource == NULL ) { hr = E_OUTOFMEMORY; } else //=========================================================
// If the lookup id was to be looked up in the resource dll
// of the error collection, make sure we just return NULL
// for the error description.
//=========================================================
if ( (dwLookupId &= ~IDENTIFIER_SDK_MASK) == 0 ) { hr = S_OK; } else //=========================================================
// After this point make sure to exit to goto
// the FAILED(hr) code or drop through to the return hr,
// as to make sure memory is freed if need be.
// Determine if it is a static or dynamic string
//=========================================================
if ( dwLookupId & ERR_STATIC_STRING ) { wcscpy(wszBuffer,L""); // NTRaid : 111781
// 06/13/00
// cchBuffer = LoadStringW(g_hInstance, (UINT)(dwLookupId & ~(ERR_STATIC_STRING)), wszBuffer,ERROR_DESCRIPTION_SIZE);
cchBuffer = WMIOledb_LoadStringW( (UINT)(dwLookupId & ~(ERR_STATIC_STRING)), wszBuffer,ERROR_DESCRIPTION_SIZE);
//=====================================================
// Convert to a BSTR
//=====================================================
if (cchBuffer) { *ppwszDescription = Wmioledb_SysAllocString(wszBuffer); if ( *ppwszDescription == NULL ) { hr = E_OUTOFMEMORY; } } } else { hr = g_pCError->GetErrorDescription(dwLookupId, ppwszDescription); }
if ( FAILED(hr) ) {
//=====================================================
// If allocation done, make sure that it is freed
//=====================================================
if ( ppwszSource ) { SysFreeString(*ppwszSource); *ppwszSource = NULL; } if ( ppwszDescription ) { SysFreeString(*ppwszDescription); *ppwszDescription = NULL; } }
} // else for if(check valid parameters)
return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Retrieve the error message and source based on the HRESULT and the provider specific error number
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIErrorLookup::GetHelpInfo( HRESULT hrError,DWORD dwLookupId, LCID lcid, BSTR* ppwszHelpFile, DWORD* pdwHelpContext ) { HRESULT hr = S_OK; //=====================================================
// Check the Arguments
//=====================================================
if ( !ppwszHelpFile || !pdwHelpContext ) { hr = E_INVALIDARG; } else {
//=====================================================
// Initialize return values
//=====================================================
*ppwszHelpFile = NULL; *pdwHelpContext = 0;
//=====================================================
// Check the Locale
//=====================================================
if ( lcid != GetSystemDefaultLCID() ) { hr = DB_E_NOLOCALE; } }
//=====================================================
// We currently can't return any help file context or
// names. So, we will just return S_OK.
//=====================================================
return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Method to be called to release non static error messages.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIErrorLookup::ReleaseErrors( const DWORD dwDynamicErrorID ) { HRESULT hr = S_OK; //=====================================================
// Check the Arguments
//=====================================================
if ( dwDynamicErrorID == 0 ) { hr = E_INVALIDARG; } else { g_pCError->RemoveErrors(dwDynamicErrorID); } return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constructor for this class
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma warning (disable:4355)
CImpIWMIErrorInfo::CImpIWMIErrorInfo( PERRORSTUFF pErrStuff ) {
//=====================================================
// Initialize simple member vars
//=====================================================
m_cRef = 0L; m_hObjCollection = ULONG(-1); //=====================================================
// Store values
//=====================================================
m_pErrStuff = pErrStuff;
//=====================================================
// Since the memory is created and owned by WMIoledb,
// we need to make sure that this DLL is not unloaded,
// else we will clean up the handed out pointer
//=====================================================
InterlockedIncrement(&g_cObj); } #pragma warning (default:4355)
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Destructor for this class
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
CImpIWMIErrorInfo::~CImpIWMIErrorInfo (void) { //=====================================================
// For Abnormal Termination,Remove self from Collection
//=====================================================
g_pCError->RemoveFromCollection(m_hObjCollection);
//=====================================================
// If this object has been released, we can now
// decrement our object count
//=====================================================
InterlockedDecrement(&g_cObj); }
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Returns a pointer to a specified interface. Callers use QueryInterface to determine which interfaces
// the called object supports.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIWMIErrorInfo::QueryInterface( REFIID riid, LPVOID * ppv) { HRESULT hr = E_NOINTERFACE;
if ( ppv == NULL ){ hr = E_INVALIDARG; } else //=====================================================
// This is the non-delegating IUnknown implementation
//=====================================================
if ( (riid == IID_IUnknown) || (riid == IID_IErrorInfo) ){ *ppv = (LPVOID)this; } else{ *ppv = NULL; }
//=====================================================
// If we're going to return an interface, AddRef first
//=====================================================
if (*ppv){ ((LPUNKNOWN)*ppv)->AddRef(); hr = S_OK; }
return hr; }
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Increments a persistence count for the object
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpIWMIErrorInfo::AddRef(void) { ULONG cRef = InterlockedIncrement( (long*) &m_cRef); return cRef; }
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Decrements a persistence count for the object and if persistence count is 0,object destroys itself.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP_(ULONG) CImpIWMIErrorInfo::Release (void) { ULONG cRef = InterlockedDecrement( (long*) &m_cRef); if ( !cRef ){ delete this; return 0; } return cRef; }
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Return the WMIstate associated with this custom error object.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CImpIWMIErrorInfo::GetWMIInfo( BSTR* pbstrMsg, LONG* plNativeError ) { HRESULT hr = S_OK; //=====================================================
// Check arguments
//=====================================================
if ( !pbstrMsg || !plNativeError) { hr = E_INVALIDARG; } else {
//=====================================================
// Initialize return values
//=====================================================
*pbstrMsg = Wmioledb_SysAllocString(NULL); *plNativeError = 0;
//=====================================================
// Handle WMIState
//=====================================================
if ( wcslen(m_pErrStuff->pwszMessage) > 0 ) { //=================================================
// If string is not NULL,then we can allocate it
//=================================================
*pbstrMsg = Wmioledb_SysAllocString(m_pErrStuff->pwszMessage); if ( *pbstrMsg == NULL ) { hr = E_OUTOFMEMORY; } }
//=====================================================
// Handle Native Error Code.
//=====================================================
*plNativeError = m_pErrStuff->lNative; }
return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////////
CError::CError( ) { //=====================================================
// Note that this is NOT a first-class object: it is
// NOT given away outside this DLL. So we do not want
// to alter global object count.
//=====================================================
// Clear variables
m_pWMIErrorInfoCollection = NULL; m_prgErrorDex = NULL; m_cErrorsUsed = 0; m_dwId = 0; m_ulNext = 1;
//=====================================================
// Initialize ErrorInfo with constant information
//=====================================================
m_ErrorInfo.clsid = CLSID_WMIOLEDB; m_ErrorInfo.dispid = NULL;
m_pcsErrors = new CCriticalSection(TRUE); } ///////////////////////////////////////////////////////////////////////////////////////////////////////
CError::~CError() { ULONG iElems; ULONG cElems; ULONG ul; PIMPIWMIERRORINFO pIWMIErrorInfo;
m_pcsErrors->Enter();
//=====================================================
// Release the general Object
//=====================================================
if ( m_pWMIErrorInfoCollection ){
cElems = m_pWMIErrorInfoCollection->Size();
//=================================================
// Loop through stored object handles and release.
//=================================================
for(iElems=0; iElems<cElems; iElems++){
pIWMIErrorInfo = (PIMPIWMIERRORINFO )m_pWMIErrorInfoCollection->GetAt(iElems); if ( pIWMIErrorInfo != NULL ) { delete pIWMIErrorInfo; } } delete m_pWMIErrorInfoCollection; }
//=====================================================
// Cleanup and error information hanging off the
// pointer array
//=====================================================
if ( m_prgErrorDex ){
for(ul=0; ul<m_cErrors; ul++){
if ( m_prgErrorDex[ul] ){
delete[] m_prgErrorDex[ul]; m_prgErrorDex[ul] = NULL; } } delete[] m_prgErrorDex; } m_pcsErrors->Leave();
SAFE_DELETE_PTR(m_pcsErrors); } ///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// If this initialization routine fails, it is the callers responsibility to delete this object.
// The destructor will then clean up any allocated resources
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CError::FInit() { HRESULT hr = S_OK;
//=============================================================
// Create array of pointers into the heap
//=============================================================
m_prgErrorDex = new PERRORSTUFF[INITIAL_SIZE_FOR_ERRORSTUFF];
if ( NULL == m_prgErrorDex ) { hr = E_OUTOFMEMORY; } else { m_cErrors = INITIAL_SIZE_FOR_ERRORSTUFF; memset(m_prgErrorDex, 0, INITIAL_SIZE_FOR_ERRORSTUFF * sizeof(PERRORSTUFF));
//=============================================================
// Create WMI Error Object Collection
//=============================================================
m_pWMIErrorInfoCollection = new CFlexArray;
if ( NULL == m_pWMIErrorInfoCollection ) { hr = E_OUTOFMEMORY; }
} return hr; } ///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Remove the Error Information for a particular DynamicId. This could be one or more elements of the
// ERRORSTUFF array and their associated pwszMessages on the Heap.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
void CError::RemoveErrors( DWORD dwDynamicId ) { ULONG ul;
//=============================================================
// At the creation of the CAutoBlock object a critical section
// is entered. This is because the method manipulates shared
// structures access to which must be serialized .
// The criticalsection is left when this method terminate
// and the destructor for CAutoBlock is called.
//=============================================================
CAutoBlock Crit(m_pcsErrors);
for(ul=0; ul<m_cErrors; ul++){
if ( m_prgErrorDex[ul] && m_prgErrorDex[ul]->dwDynamicId == dwDynamicId ){
delete[] m_prgErrorDex[ul]; m_prgErrorDex[ul] = NULL; m_cErrorsUsed--;
//=====================================================
// For each error description that we cache, we have
// up'd the object count to make sure that we stay
// alive while there is a possibility the error
// collection could call back into us for this desc.
// Here is where we decrement that count upon
// release of the error message.
//=====================================================
InterlockedDecrement(&g_cObj); } } }
////////////////////////////////////////////////////////////////////////////////////////////
//
// Retrieve the WMI Server Error Message from the cache
//
////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CError::GetErrorDescription(ULONG ulDex, BSTR* ppwszDescription ) {
HRESULT hr = S_OK;
//======================================================
// Enter critical section
//======================================================
CAutoBlock Crit(m_pcsErrors);
//======================================================
//
//======================================================
if (ulDex < m_cErrors && m_prgErrorDex[ulDex]){
PERRORSTUFF pErrorStuff = m_prgErrorDex[ulDex]; if (wcslen(pErrorStuff->pwszMessage) > 0 ){
//======================================================
// return the message from WMI
//======================================================
*ppwszDescription = Wmioledb_SysAllocString(pErrorStuff->pwszMessage); if (*ppwszDescription == NULL){ hr = E_OUTOFMEMORY; } } else{
//======================================================
// return the standard error
//======================================================
WCHAR rgwchBuff[MAX_PATH+1]; WCHAR *pwsz = rgwchBuff; int cwch = LoadStringW(g_hInstance, pErrorStuff->uStringId, rgwchBuff, NUMELEM(rgwchBuff)); *ppwszDescription = Wmioledb_SysAllocString(pwsz); if (*ppwszDescription == NULL){ hr = E_OUTOFMEMORY; } } } else{ *ppwszDescription = NULL; hr = DB_E_BADLOOKUPID; }
return hr; }
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Retrieve the IErrorInfo and IErrorRecords pointers whether from automation or from creating a new
// instance
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CError::GetErrorInterfaces( IErrorInfo** ppIErrorInfo, IErrorRecords** ppIErrorRecords ) { HRESULT hr = S_OK;
*ppIErrorInfo = NULL; *ppIErrorRecords = NULL; //=============================================================
//Obtain the error object or create a new one if none exists
//=============================================================
// NTRaid:111806
// 06/07/00
hr = GetErrorInfo(0, ppIErrorInfo); if (SUCCEEDED(hr) && !*ppIErrorInfo){
hr = g_pErrClassFact->CreateInstance(NULL, IID_IErrorInfo, (LPVOID*)ppIErrorInfo); } if(SUCCEEDED(hr)) { //=============================================================
// Obtain the IErrorRecord Interface
//=============================================================
hr = (*ppIErrorInfo)->QueryInterface(IID_IErrorRecords, (LPVOID*)ppIErrorRecords);
//=============================================================
// On a failure retrieving IErrorRecords, we need to release
// the IErrorInfo interface
//=============================================================
if ( FAILED(hr) ){ (*ppIErrorInfo)->Release(); *ppIErrorInfo = NULL; } } return hr; } /////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Determine the next free index of the PERRORSTUFF array.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CError::FindFreeDex( ULONG* ulDex ) { PERRORSTUFF* pNew = NULL; HRESULT hr = S_OK;
//===========================================================================
// Check if we need to expand the buffer
// Since we do not use element 0, we need to reallocate when at m_cErrors - 1
//===========================================================================
if ( m_cErrorsUsed == (m_cErrors - 1)) { try { pNew = new PERRORSTUFF[m_cErrors + INCREMENT_BY_FOR_ERRORSTUFF]; } catch(...) { SAFE_DELETE_PTR(pNew); throw; } if ( pNew ) {
//===================================================================
// Copy old pointers to new array
//===================================================================
memcpy(pNew, m_prgErrorDex, m_cErrors * sizeof(PERRORSTUFF)); memset((pNew + m_cErrors), 0, INCREMENT_BY_FOR_ERRORSTUFF * sizeof(PERRORSTUFF));
//===================================================================
// Set the new array size
//===================================================================
m_ulNext = m_cErrors; m_cErrors += INCREMENT_BY_FOR_ERRORSTUFF; delete[] m_prgErrorDex; m_prgErrorDex = pNew; } else { *ulDex = 0; hr = E_OUTOFMEMORY; } } if(SUCCEEDED(hr)) { //===========================================================================
// Loop through looking for unused index
//===========================================================================
while( 1 ){
//=======================================================================
// If we are at the top of our buffer rap back to the begining
//=======================================================================
if (m_ulNext == m_cErrors) { m_ulNext = 1; } else if (NULL == m_prgErrorDex[m_ulNext]) { m_cErrorsUsed++; *ulDex = m_ulNext++; break; } else { m_ulNext++; } } } return hr; } ////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Creates error records for the WMI errors encountered. The WMIState and Native error code are
// stored in a custom interface, where as the description is returned by the standard IErrorInfo
// interface.
//
////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CError::PostWMIErrors( HRESULT hrErr, const IID* piid, CErrorData* pErrData ) {
HRESULT hr = S_OK; IErrorInfo* pIErrorInfo = NULL; IErrorRecords* pIErrorRecords = NULL; PIMPIWMIERRORINFO pWMIError = NULL; ULONG iElems; ULONG cElems; PERRORSTUFF pErrStuff; DWORD dwDex;
//===========================================================================
// Enter critical section
//===========================================================================
CAutoBlock Crit(m_pcsErrors);
//===========================================================================
// We cannot Init the Datasource object without this pointer being set, so it
// should exist at this point
// Get the # errors
//===========================================================================
cElems = pErrData->Size(); if (0 == cElems){ if (FAILED(hrErr)) g_pCError->PostHResult(hrErr, piid); hr = S_OK; } else{
//=======================================================================
// Obtain the error object or create a new one if none exists
//=======================================================================
if ( SUCCEEDED(hr = GetErrorInterfaces(&pIErrorInfo, &pIErrorRecords)) ){
//===================================================================
// Assign static information across each error record added
//===================================================================
m_ErrorInfo.hrError = hrErr; m_ErrorInfo.iid = *piid; m_ErrorInfo.dispid = NULL;
//===================================================================
// Increment Dynamic Id;
//===================================================================
m_dwId++;
//===================================================================
// Loop through an array of indexes into the error array
//===================================================================
for (iElems=0; iElems<cElems; iElems++){
//===============================================================
// Get the error stuff
//===============================================================
pErrData->SetAt(iElems,(void**)&pErrStuff);
//===============================================================
// Save the dynamic id
//===============================================================
pErrStuff->dwDynamicId = m_dwId;
//===============================================================
// Save WMI Server error code
//===============================================================
m_ErrorInfo.dwMinor = DWORD(pErrStuff->lNative);
//===============================================================
// Determine index to store heap pointer
//===============================================================
if ( SUCCEEDED(hr = FindFreeDex(&dwDex)) ){
try { //===========================================================
// Create the custom error object
//===========================================================
pWMIError = new CImpIWMIErrorInfo(pErrStuff); } catch(...) { SAFE_DELETE_PTR(pWMIError); throw; } if ( pWMIError == NULL ){ hr = E_OUTOFMEMORY; } else{ pWMIError->AddRef(); if ( SUCCEEDED(hr = pWMIError->FInit()) ){
//===================================================
// Add the record to the Error Service Object
//===================================================
hr = pIErrorRecords->AddErrorRecord(&m_ErrorInfo, dwDex, NULL,(IUnknown*) pWMIError, m_dwId); if ( SUCCEEDED(hr) ){
//===============================================
// Release the custom Error Object
//===============================================
pWMIError->Release(); pWMIError = NULL;
//===============================================
// Save the pointer to the error stuff
//===============================================
m_prgErrorDex[dwDex] = pErrStuff;
//===============================================
// For each error description that we cache, we
// have up'd the the object count to make sure
// that we stay alive while there is a
// possibility the errorcollection could call back
// into us for this description. Here is where we
// increment that count.
//===============================================
InterlockedIncrement(&g_cObj); } } } } //================================================================
// Pass the error object to the Ole Automation DLL
//================================================================
hr = SetErrorInfo(0, pIErrorInfo); } } }
//============================================================================
// Release the interfaces to transfer ownership to the Ole Automation DLL
//============================================================================
SAFE_RELEASE_PTR(pWMIError); SAFE_RELEASE_PTR(pIErrorRecords); SAFE_RELEASE_PTR(pIErrorInfo);
//============================================================================
// Free the error data
//============================================================================
pErrData->FreeErrors(); return hr; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This method is used to post an HRESULT that is to be looked up in the resource fork of the error collection
// object.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CError::PostHResult( HRESULT hrErr, const IID* piid ) { HRESULT hr = S_OK; IErrorInfo* pIErrorInfo = NULL; IErrorRecords* pIErrorRecords = NULL;
//==================================================================
// Enter critical section
//==================================================================
CAutoBlock Crit(m_pcsErrors);
//==================================================================
// Obtain the error object or create a new one if none exists
//==================================================================
if ( SUCCEEDED(hr = GetErrorInterfaces(&pIErrorInfo, &pIErrorRecords)) ) { //==================================================================
// Assign static information across each error record added
//==================================================================
m_ErrorInfo.hrError = hrErr; m_ErrorInfo.iid = *piid; m_ErrorInfo.dispid = NULL; m_ErrorInfo.dwMinor = 0;
//==================================================================
// Add the record to the Error Service Object
//==================================================================
hr = pIErrorRecords->AddErrorRecord(&m_ErrorInfo,IDENTIFIER_SDK_ERROR,NULL,(IUnknown*)NULL,0); if ( SUCCEEDED(hr) ) { //==================================================================
// Pass the error object to the Ole Automation DLL
//==================================================================
hr = SetErrorInfo(0, pIErrorInfo); } }
//==================================================================
// Release the interfaces to transfer ownership to the Ole Automation DLL
//==================================================================
SAFE_RELEASE_PTR(pIErrorRecords); SAFE_RELEASE_PTR(pIErrorInfo);
return hrErr; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// This method is used to post static strings to the error objects. The static strings are stored in the
// resource fork, and thus an id needs to be specified.
//
// @devnote If the error object is not our implementation of IID_IErrorInfo, we will not be able to load
// IErrorRecord and add our records.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CError::PostError( HRESULT hrErr, const IID* piid, DWORD dwIds, DISPPARAMS* pdispparams ) { HRESULT hr = S_OK; IErrorInfo* pIErrorInfo = NULL; IErrorRecords* pIErrorRecords = NULL;
//====================================================================
// Enter critical section
//====================================================================
CAutoBlock Crit(m_pcsErrors);
//====================================================================
// Obtain the error object or create a new one if none exists
//====================================================================
if ( SUCCEEDED(hr = GetErrorInterfaces(&pIErrorInfo, &pIErrorRecords)) ) { //====================================================================
// Assign static information across each error record added
//====================================================================
m_ErrorInfo.hrError = hrErr; m_ErrorInfo.iid = *piid; m_ErrorInfo.dispid = NULL; m_ErrorInfo.dwMinor = 0;
//====================================================================
// Add the record to the Error Service Object
//====================================================================
hr = pIErrorRecords->AddErrorRecord(&m_ErrorInfo, (dwIds | ERR_STATIC_STRING), pdispparams, NULL, 0); if ( SUCCEEDED(hr) ) { //====================================================================
// Pass the error object to the Ole Automation DLL
//====================================================================
hr = SetErrorInfo(0, pIErrorInfo); }
} //====================================================================
// Release the interfaces to transfer ownership to the Ole Automation DLL
//====================================================================
SAFE_RELEASE_PTR(pIErrorRecords); SAFE_RELEASE_PTR(pIErrorInfo);
return hr; } ////////////////////////////////////////////////////////////////////////////////////////////////
//
// This method is used to post static strings to the error objects.
//
////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CError::PostErrorMessage( HRESULT hrErr, const IID* piid, UINT uStringId, LPCWSTR pwszMessage ) {
PERRORSTUFF pErrStuff = NULL; ULONG cwch = wcslen(pwszMessage); HRESULT hr = S_OK; IErrorInfo* pIErrorInfo = NULL; IErrorRecords* pIErrorRecords = NULL; PIMPIWMIERRORINFO pWMIError = NULL; DWORD dwDex;
//==========================================================
// CS because the method manipulates shared structures
// access to which must be serialized .
//==========================================================
CAutoBlock Crit(m_pcsErrors); try { pErrStuff = (PERRORSTUFF) new BYTE[sizeof(ERRORSTUFF)+(cwch+2)*sizeof(WCHAR)]; } catch(...) { SAFE_DELETE_ARRAY(pErrStuff); throw; } if (!pErrStuff) { hr = E_OUTOFMEMORY; } else { //==========================================================
// Initialize error stuff
//==========================================================
pErrStuff->dwDynamicId = 0; pErrStuff->uStringId = uStringId; pErrStuff->hr = S_OK; pErrStuff->lNative = 0; pErrStuff->wLineNumber = 0;
AllocateAndCopy(pErrStuff->pwszMessage, (unsigned short*)pwszMessage); //==========================================================
// We cannot Init the Datasource object without this pointer
// being set, so it should exist at this point
// Obtain the error object or create new one if none exists
//==========================================================
if ( SUCCEEDED(hr = GetErrorInterfaces(&pIErrorInfo, &pIErrorRecords)) ) { //==========================================================
// Assign static information across each error record added
//==========================================================
m_ErrorInfo.hrError = hrErr; m_ErrorInfo.iid = *piid; m_ErrorInfo.dispid = NULL; m_ErrorInfo.dwMinor = 0;
//==========================================================
// Increment Dynamic Id and save it
//==========================================================
pErrStuff->dwDynamicId = ++m_dwId;
//==========================================================
// Determine index to store heap pointer
//==========================================================
if ( SUCCEEDED(hr = FindFreeDex(&dwDex)) ) { try { //==========================================================
// Create the custom error object
//==========================================================
pWMIError = new CImpIWMIErrorInfo(pErrStuff); } catch(...) { SAFE_DELETE_ARRAY(pErrStuff); SAFE_DELETE_PTR(pErrStuff); throw; }
if ( pWMIError == NULL ){ hr = E_OUTOFMEMORY; } else { //==========================================================
// Give the object existence
//==========================================================
pWMIError->AddRef(); if ( SUCCEEDED(hr = pWMIError->FInit()) ) { //==========================================================
// Add the record to the Error Service Object
//==========================================================
if(SUCCEEDED(hr = pIErrorRecords->AddErrorRecord(&m_ErrorInfo, dwDex, NULL, (IUnknown*)pWMIError, m_dwId))) { //==========================================================
// Release the custom Error Object
//==========================================================
pWMIError->Release(); pWMIError = NULL;
//==========================================================
// Save the pointer to the error stuff
//==========================================================
m_prgErrorDex[dwDex] = pErrStuff;
//==========================================================
// For each error description that we cache, we have up'd the
// the object count to make sure that we stay alive while there is
// a possibility the errorcollection could call back into us for
// this description. Here is where we increment that count.
//==========================================================
InterlockedIncrement(&g_cObj); //==========================================================
// Pass the error object to the Ole Automation DLL
//==========================================================
hr = SetErrorInfo(0, pIErrorInfo); } // if Succeeded(AddErrorRecord(())
} // if (succeeded(pWMIError->FInit))
} // if allocation of pWMIError is successful
} // if(succeeded(FindFreeDex))
} // if succeeded(GetErrorInterfaces)
} // if propert allocation
//==========================================================
// Release the interfaces to transfer ownership to
//==========================================================
SAFE_DELETE_ARRAY(pErrStuff); SAFE_DELETE_PTR(pErrStuff); SAFE_RELEASE_PTR(pWMIError); SAFE_RELEASE_PTR(pIErrorRecords); SAFE_RELEASE_PTR(pIErrorInfo);
return hr; }
////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Frees error information and empties the array
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CError::FreeErrors() { ULONG iElems; ULONG cElems; BYTE* pb;
cElems = Size();
for (iElems=0; iElems<cElems; iElems++){
pb = (BYTE*) m_pWMIErrorInfoCollection->GetAt(iElems); if (pb){ delete[] pb; } } m_pWMIErrorInfoCollection->Empty(); } //**********************************************************************************************************
//
//**********************************************************************************************************
////////////////////////////////////////////////////////////////////////////////////////////////////////////
CErrorData::CErrorData() { //
} ////////////////////////////////////////////////////////////////////////////////////////////////////////////
CErrorData::~CErrorData() { FreeErrors(); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////
void CErrorData::FreeErrors() {
}
|