//////////////////////////////////////////////////////////////////////////////////////////////////////// // // Microsoft WMI OLE DB Provider // (C) Copyright 1999 Microsoft Corporation. All Rights Reserved. // // Error Routines // /////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef __ERROR_H__ #define __ERROR_H__ #include "headers.h" #include "classfac.h" /////////////////////////////////////////////////////////////////////////////////////////////////////// // Forward declarations ------------------------------------------------------ /////////////////////////////////////////////////////////////////////////////////////////////////////// class CErrorLookup; typedef CErrorLookup* PCERRORLOOKUP; class CImpIWMIErrorInfo; typedef CImpIWMIErrorInfo* PIMPIWMIERRORINFO; /////////////////////////////////////////////////////////////////////////////////////////////////////// //---------------------------------------------------------------------------- // MACROS AND INLINE FUNCTIONS //---------------------------------------------------------------------------- // The following macro takes the Data1 element of a guid and looks at the lower // byte. Taking this value and a particular base value that would will yield a // number between 1 and 32, we can determine what bit in the DWORD to set on. /////////////////////////////////////////////////////////////////////////////////////////////////////// #define PBIT(p1, base) (DWORD)(1 << (((p1) & 0x000000FF) & ~(base))) /////////////////////////////////////////////////////////////////////////////////////////////////////// const DWORD ERR_STATIC_STRING = 0x08000000; // NOTE: High Byte is reserved by IDENTIFIER_SDK_MASK const DWORD INITIAL_SIZE_FOR_ERRORSTUFF = 32; const DWORD INCREMENT_BY_FOR_ERRORSTUFF = 16; typedef struct tagERRORSTUFF { DWORD dwDynamicId; // Identification number for a set of errors UINT uStringId; // String id for standard error LONG lNative; // Native Error value HRESULT hr; // HRESULT WORD wLineNumber; // Batch/Procedue Line number WCHAR* pwszServer; // Server name WCHAR* pwszProcedure; // Procedure name WCHAR * pwszMessage; } ERRORSTUFF, *PERRORSTUFF; /////////////////////////////////////////////////////////////////////////////////////////////////////// // // Class that maintains error data until we generate error records via IErrorRecords::AddErrorRecord // /////////////////////////////////////////////////////////////////////////////////////////////////////// class CErrorData : public CFlexArray { private: WORD m_wStatus; public: CErrorData(); ~CErrorData(); WORD WGetStatus(WORD w) const { return m_wStatus & w; } void SetStatus(WORD w) { m_wStatus |= w; } void ClearStatus(WORD w) { m_wStatus &= ~w; } inline void GetLastError(PERRORSTUFF *ppErrorStuff) { assert(Size() > 0); *ppErrorStuff = (PERRORSTUFF) GetAt(Size()-1);} STDMETHODIMP InsertError( ULONG iInsert, // IN | index to insert the error UINT uStringId, // IN | string ID for error LONG lNative = 0 ); // IN | native error code void PeekError( DWORD *pdwStdError, // OUT | standard WMI error number (optional) LONG *plNativeError ); // OUT | native error number from WMI Server STDMETHODIMP PostStandardError( UINT uStringId, // IN | string ID for error HRESULT hrErr = S_OK, // IN | hresult to associate LONG lNative = 0 ); // IN | native eror code STDMETHODIMP PostWMIError( UINT uStringId, // IN | string ID for error LONG lNative, // IN | native error code WORD wLineNumber, // IN | batch/procedure line number LPCWSTR pwszError, // IN | error message LPCWSTR pwszServer, // IN | server name or NULL LPCWSTR pwszProcedure, // IN | procedure name or NULL HRESULT hrErr = S_OK // IN | associated hresult ); inline STDMETHODIMP PostWinError(UINT uStringId){ return PostStandardError(uStringId, S_OK, (LONG)::GetLastError()); } ULONG RemoveError( LONG lNativeError ); void XferErrors(CErrorData* pCError); enum EErrStatus { ERR_STATUS_OK = 0x0000, ERR_STATUS_OOM = 0x0001, // Out-of-memory error occurred ERR_STATUS_KEEP = 0x0002, }; ULONG SetPosError(HRESULT rc); void FreeErrors(); }; /////////////////////////////////////////////////////////////////////////////////////////////////////// class CImpISupportErrorInfo : public ISupportErrorInfo { private: ULONG m_cRef; IUnknown* m_pUnkOuter; GUID** m_rgpErrInt; ULONG m_cpErrInt; ULONG m_cAllocGuid; // Number of allocate GUIDs public: CImpISupportErrorInfo( IUnknown* pUnkOuter ); ~CImpISupportErrorInfo(); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv); STDMETHODIMP InterfaceSupportsErrorInfo(REFIID riid); HRESULT AddInterfaceID(REFIID riid); }; typedef CImpISupportErrorInfo* PIMPISUPPORTERRORINFO; /////////////////////////////////////////////////////////////////////////////////////////////////////// class CImpIErrorLookup : public IErrorLookup { private: ULONG m_cRef; PCERRORLOOKUP m_pCErrorLookup; public: CImpIErrorLookup(PCERRORLOOKUP pCErrorLookup){ DEBUGCODE(m_cRef = 0L); m_pCErrorLookup = pCErrorLookup; } ~CImpIErrorLookup() {} STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv); STDMETHODIMP GetErrorDescription(HRESULT hrError, DWORD dwLookupId, DISPPARAMS* pdispparams, LCID lcid, BSTR* ppwszSource, BSTR* ppwszDescription); STDMETHODIMP GetHelpInfo(HRESULT hrError, DWORD dwMinor, LCID lcid, BSTR* ppwszHelpFile, DWORD* pdwHelpContext); STDMETHODIMP ReleaseErrors(const DWORD dwDynamicErrorId); }; typedef CImpIErrorLookup* PIMPIERRORLOOKUP; /////////////////////////////////////////////////////////////////////////////////////////////////////// class CErrorLookup : public CBaseObj { friend class CImpIErrorLookup; protected: CImpIErrorLookup m_IErrorLookup; public: CErrorLookup(LPUNKNOWN pUnkOuter); ~CErrorLookup(void) {} STDMETHODIMP QueryInterface(REFIID, LPVOID *); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); }; //////////////////////////////////////////////////////////////////////////////////////////////////////// // // Routines to maintain the internal posting, viewing and removal of error information. // //////////////////////////////////////////////////////////////////////////////////////////////////////// class CError { private: ERRORINFO m_ErrorInfo; PERRORSTUFF* m_prgErrorDex; CCriticalSection* m_pcsErrors; ULONG m_cErrors; ULONG m_cErrorsUsed; ULONG m_ulNext; DWORD m_dwId; CFlexArray* m_pWMIErrorInfoCollection; private: HRESULT GetErrorInterfaces(IErrorInfo** ppIErrorInfo, IErrorRecords** ppIErrorRecords); public: CError(); ~CError(); HRESULT FInit(); HRESULT FindFreeDex(ULONG* pulDex); inline static void ClearErrorInfo(void) { SetErrorInfo(0, NULL); } inline int Size() { return m_pWMIErrorInfoCollection->Size(); } inline void SetAt(int n, void *p) { m_pWMIErrorInfoCollection->SetAt(n,p); } inline HRESULT AddToCollection(CImpIWMIErrorInfo* pWMIErrorInfo); inline void RemoveFromCollection(ULONG hObjCollection); HRESULT GetErrorDescription(ULONG ulDex, BSTR* ppwszDescription); void RemoveErrors(DWORD dwDynamicId); void FreeErrors(); HRESULT PostError(HRESULT hrErr, const IID* piid, DWORD dwIds, DISPPARAMS* pdispparams); HRESULT PostErrorMessage(HRESULT hrErr, const IID* piid, UINT uStringId, LPCWSTR pwszMessage); HRESULT PostHResult(HRESULT hrErr, const IID* piid); HRESULT PostWMIErrors( HRESULT hrErr, const IID* piid, CErrorData* pErrData); }; //////////////////////////////////////////////////////////////////////////////////////////////////////// class CImpIWMIErrorInfo { private: ULONG m_cRef; PERRORSTUFF m_pErrStuff; ULONG m_hObjCollection; public: CImpIWMIErrorInfo(PERRORSTUFF pErrStuff); ~CImpIWMIErrorInfo(); inline HRESULT FInit(); PERRORSTUFF GetErrorStuff(void) const { return m_pErrStuff; } STDMETHODIMP QueryInterface(REFIID, LPVOID *); STDMETHODIMP_(ULONG) AddRef(void); STDMETHODIMP_(ULONG) Release(void); STDMETHODIMP GetWMIInfo(BSTR* pbstrWMIInfo, LONG* plNativeError); }; //////////////////////////////////////////////////////////////////////////////////////////////////////// inline HRESULT CError::AddToCollection( CImpIWMIErrorInfo* pWMIErrorInfo ) { CAutoBlock Crit(m_pcsErrors); HRESULT hr = m_pWMIErrorInfoCollection->Add(pWMIErrorInfo); return hr; }; //////////////////////////////////////////////////////////////////////////////////////////////////////// inline void CError::RemoveFromCollection(ULONG hObjCollection) { CAutoBlock Crit(m_pcsErrors); m_pWMIErrorInfoCollection->RemoveAt(hObjCollection); } extern CError * g_pCError; //////////////////////////////////////////////////////////////////////////////////////////////////////// inline HRESULT CImpIWMIErrorInfo::FInit() { // For Abnormal Termination, add self to Collection if( g_pCError ){ return g_pCError->AddToCollection(this); } return -1; } #endif