mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1236 lines
31 KiB
1236 lines
31 KiB
//+-------------------------------------------------------------------
|
|
//
|
|
// File: cerror.cxx
|
|
//
|
|
// Contents: Implements COM extended error information.
|
|
//
|
|
// Classes: CErrorObject - Implements the COM error object.
|
|
//
|
|
// Functions: CoCreateErrorInfo = CreateErrorInfo
|
|
// CoGetErrorInfo = GetErrorInfo
|
|
// CoSetErrorInfo = SetErrorInfo
|
|
//
|
|
// History:
|
|
// 20-Jun-96 MikeHill Added more OleAut32 wrappers.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
#include <ole2int.h>
|
|
#include <oleauto.h>
|
|
#include <channelb.hxx>
|
|
#include <chock.hxx>
|
|
#include <privoa.h> // PrivSys* routines
|
|
|
|
HRESULT NdrStringRead(IStream *pStream, LPWSTR *psz);
|
|
ULONG NdrStringSize(LPCWSTR psz);
|
|
HRESULT NdrStringWrite(IStream *pStream, LPCWSTR psz);
|
|
|
|
struct ErrorObjectData
|
|
{
|
|
DWORD dwVersion;
|
|
DWORD dwHelpContext;
|
|
IID iid;
|
|
};
|
|
|
|
class CErrorObject : public IErrorInfo, public ICreateErrorInfo, public IMarshal
|
|
{
|
|
private:
|
|
long _refCount;
|
|
ErrorObjectData _data;
|
|
LPWSTR _pszSource;
|
|
LPWSTR _pszDescription;
|
|
LPWSTR _pszHelpFile;
|
|
|
|
~CErrorObject();
|
|
|
|
public:
|
|
CErrorObject();
|
|
|
|
/*** IUnknown methods ***/
|
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
|
/* [in] */ REFIID riid,
|
|
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppv);
|
|
|
|
ULONG STDMETHODCALLTYPE AddRef( void);
|
|
|
|
ULONG STDMETHODCALLTYPE Release( void);
|
|
|
|
/*** IMarshal methods ***/
|
|
HRESULT STDMETHODCALLTYPE GetUnmarshalClass(
|
|
/* [in] */ REFIID riid,
|
|
/* [unique][in] */ void __RPC_FAR *pv,
|
|
/* [in] */ DWORD dwDestContext,
|
|
/* [unique][in] */ void __RPC_FAR *pvDestContext,
|
|
/* [in] */ DWORD mshlflags,
|
|
/* [out] */ CLSID __RPC_FAR *pCid);
|
|
|
|
HRESULT STDMETHODCALLTYPE GetMarshalSizeMax(
|
|
/* [in] */ REFIID riid,
|
|
/* [unique][in] */ void __RPC_FAR *pv,
|
|
/* [in] */ DWORD dwDestContext,
|
|
/* [unique][in] */ void __RPC_FAR *pvDestContext,
|
|
/* [in] */ DWORD mshlflags,
|
|
/* [out] */ DWORD __RPC_FAR *pSize);
|
|
|
|
HRESULT STDMETHODCALLTYPE MarshalInterface(
|
|
/* [unique][in] */ IStream __RPC_FAR *pStm,
|
|
/* [in] */ REFIID riid,
|
|
/* [unique][in] */ void __RPC_FAR *pv,
|
|
/* [in] */ DWORD dwDestContext,
|
|
/* [unique][in] */ void __RPC_FAR *pvDestContext,
|
|
/* [in] */ DWORD mshlflags);
|
|
|
|
HRESULT STDMETHODCALLTYPE UnmarshalInterface(
|
|
/* [unique][in] */ IStream __RPC_FAR *pStm,
|
|
/* [in] */ REFIID riid,
|
|
/* [out] */ void __RPC_FAR *__RPC_FAR *ppv);
|
|
|
|
HRESULT STDMETHODCALLTYPE ReleaseMarshalData(
|
|
/* [unique][in] */ IStream __RPC_FAR *pStm);
|
|
|
|
HRESULT STDMETHODCALLTYPE DisconnectObject(
|
|
/* [in] */ DWORD dwReserved);
|
|
|
|
/*** IErrorInfo methods ***/
|
|
HRESULT STDMETHODCALLTYPE GetGUID(
|
|
/* [out] */ GUID __RPC_FAR *pGUID);
|
|
|
|
HRESULT STDMETHODCALLTYPE GetSource(
|
|
/* [out] */ BSTR __RPC_FAR *pBstrSource);
|
|
|
|
HRESULT STDMETHODCALLTYPE GetDescription(
|
|
/* [out] */ BSTR __RPC_FAR *pBstrDescription);
|
|
|
|
HRESULT STDMETHODCALLTYPE GetHelpFile(
|
|
/* [out] */ BSTR __RPC_FAR *pBstrHelpFile);
|
|
|
|
HRESULT STDMETHODCALLTYPE GetHelpContext(
|
|
/* [out] */ DWORD __RPC_FAR *pdwHelpContext);
|
|
|
|
/*** ICreateErrorInfo methods ***/
|
|
HRESULT STDMETHODCALLTYPE SetGUID(
|
|
/* [in] */ REFGUID rguid);
|
|
|
|
HRESULT STDMETHODCALLTYPE SetSource(
|
|
/* [in] */ LPOLESTR szSource);
|
|
|
|
HRESULT STDMETHODCALLTYPE SetDescription(
|
|
/* [in] */ LPOLESTR szDescription);
|
|
|
|
HRESULT STDMETHODCALLTYPE SetHelpFile(
|
|
/* [in] */ LPOLESTR szHelpFile);
|
|
|
|
HRESULT STDMETHODCALLTYPE SetHelpContext(
|
|
/* [in] */ DWORD dwHelpContext);
|
|
|
|
};
|
|
|
|
HINSTANCE hOleAut32 = 0;
|
|
|
|
SYS_ALLOC_STRING *pfnSysAllocString = LoadSysAllocString;
|
|
SYS_FREE_STRING *pfnSysFreeString = LoadSysFreeString;
|
|
SYS_REALLOC_STRING_LEN *pfnSysReAllocStringLen = LoadSysReAllocStringLen;
|
|
SYS_STRING_BYTE_LEN *pfnSysStringByteLen = LoadSysStringByteLen;
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: LoadSysAllocString
|
|
//
|
|
// Synopsis: Loads oleaut32.dll and calls SysAllocString.
|
|
//
|
|
// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
|
|
//
|
|
// Notes: If successful, this function will save a pointer
|
|
// to the SysAllocString function. Subsequent calls
|
|
// will go directly to SysAllocString.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BSTR STDAPICALLTYPE
|
|
LoadSysAllocString(OLECHAR FAR* pwsz)
|
|
{
|
|
BSTR bstr = NULL;
|
|
|
|
if(!hOleAut32)
|
|
{
|
|
hOleAut32 = LoadLibraryA("oleaut32");
|
|
}
|
|
|
|
if(hOleAut32 != 0)
|
|
{
|
|
void *pfn = GetProcAddress(hOleAut32, "SysAllocString");
|
|
if(pfn != NULL)
|
|
{
|
|
pfnSysAllocString = (SYS_ALLOC_STRING *) pfn;
|
|
bstr = (*pfnSysAllocString)(pwsz);
|
|
}
|
|
}
|
|
|
|
return bstr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: LoadSysFreeString
|
|
//
|
|
// Synopsis: Loads oleaut32.dll and calls SysFreeString.
|
|
//
|
|
// Returns: None.
|
|
//
|
|
// Notes: If successful, this function will save a pointer
|
|
// to the SysFreeString function. Subsequent calls
|
|
// will go directly to SysFreeString.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
VOID STDAPICALLTYPE
|
|
LoadSysFreeString(BSTR bstr)
|
|
{
|
|
if(!hOleAut32)
|
|
{
|
|
hOleAut32 = LoadLibraryA("oleaut32");
|
|
}
|
|
|
|
if(hOleAut32 != 0)
|
|
{
|
|
void *pfn = GetProcAddress(hOleAut32, "SysFreeString");
|
|
if(pfn != NULL)
|
|
{
|
|
pfnSysFreeString = (SYS_FREE_STRING *) pfn;
|
|
(*pfnSysFreeString)(bstr);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: LoadSysReAllocStringLen
|
|
//
|
|
// Synopsis: Loads oleaut32.dll and calls SysReAllocStringLen.
|
|
//
|
|
// Returns: TRUE if and only if successful.
|
|
//
|
|
// Notes: If successful, this function will save a pointer
|
|
// to the SysReAllocString function. Subsequent calls
|
|
// will go directly to SysReAllocStringLen.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
BOOL STDAPICALLTYPE
|
|
LoadSysReAllocStringLen(BSTR FAR *pbstr, OLECHAR FAR *pwsz, UINT cch)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
|
|
if(!hOleAut32)
|
|
{
|
|
hOleAut32 = LoadLibraryA("oleaut32");
|
|
}
|
|
|
|
if(hOleAut32 != 0)
|
|
{
|
|
void *pfn = GetProcAddress(hOleAut32, "SysReAllocStringLen");
|
|
if(pfn != NULL)
|
|
{
|
|
pfnSysReAllocStringLen = (SYS_REALLOC_STRING_LEN *) pfn;
|
|
fRet = (*pfnSysReAllocStringLen)(pbstr, pwsz, cch);
|
|
}
|
|
}
|
|
|
|
return( fRet );
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: LoadSysStringByteLen
|
|
//
|
|
// Synopsis: Loads oleaut32.dll and calls SysFreeString.
|
|
//
|
|
// Returns: The byte length of the string.
|
|
//
|
|
// Notes: If successful, this function will save a pointer
|
|
// to the SysStringByteLen function. Subsequent calls
|
|
// will go directly to SysStringByteLen.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
UINT STDAPICALLTYPE
|
|
LoadSysStringByteLen(BSTR bstr)
|
|
{
|
|
UINT uiLen = 0;
|
|
|
|
if(!hOleAut32)
|
|
{
|
|
hOleAut32 = LoadLibraryA("oleaut32");
|
|
}
|
|
|
|
if(hOleAut32 != 0)
|
|
{
|
|
void *pfn = GetProcAddress(hOleAut32, "SysStringByteLen");
|
|
if(pfn != NULL)
|
|
{
|
|
pfnSysStringByteLen = (SYS_STRING_BYTE_LEN *) pfn;
|
|
uiLen = (*pfnSysStringByteLen)(bstr);
|
|
}
|
|
}
|
|
|
|
return( uiLen );
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoCreateErrorInfo
|
|
//
|
|
// Synopsis: Creates a COM error object.
|
|
//
|
|
// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
WINOLEAPI
|
|
CoCreateErrorInfo(ICreateErrorInfo **ppCreateErrorInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CErrorObject *pTemp;
|
|
|
|
__try
|
|
{
|
|
*ppCreateErrorInfo = NULL;
|
|
|
|
pTemp = new CErrorObject;
|
|
|
|
if(pTemp != NULL)
|
|
{
|
|
*ppCreateErrorInfo = (ICreateErrorInfo *) pTemp;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoGetErrorInfo
|
|
//
|
|
// Synopsis: Gets the error object for the current thread.
|
|
//
|
|
// Returns: S_OK, S_FALSE, E_INVALIDARG, E_NOINTERFACE.
|
|
//
|
|
// Notes: If sucessful, this function clears the error object
|
|
// for the current thread.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
WINOLEAPI
|
|
CoGetErrorInfo(DWORD dwReserved, IErrorInfo ** ppErrorInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
COleTls tls(hr);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
//Could not access TLS.
|
|
return hr;
|
|
}
|
|
|
|
if(dwReserved != 0)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
__try
|
|
{
|
|
*ppErrorInfo = NULL;
|
|
|
|
if(tls->punkError != NULL)
|
|
{
|
|
hr = tls->punkError->QueryInterface(IID_IErrorInfo, (void **) ppErrorInfo);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
//Clear the error object.
|
|
tls->punkError->Release();
|
|
tls->punkError = NULL;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+-------------------------------------------------------------------
|
|
//
|
|
// Function: CoSetErrorInfo
|
|
//
|
|
// Synopsis: Sets the COM extended error information for the
|
|
// current thread.
|
|
//
|
|
// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
|
|
//
|
|
//--------------------------------------------------------------------
|
|
WINOLEAPI
|
|
CoSetErrorInfo(unsigned long dwReserved, IErrorInfo * pErrorInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
COleTls tls(hr);
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
//Could not access TLS.
|
|
return hr;
|
|
}
|
|
|
|
if(dwReserved != 0)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
__try
|
|
{
|
|
//AddRef the new error object.
|
|
if(pErrorInfo != NULL)
|
|
{
|
|
pErrorInfo->AddRef();
|
|
}
|
|
|
|
//Release the old error object.
|
|
if(tls->punkError != NULL)
|
|
{
|
|
tls->punkError->Release();
|
|
}
|
|
|
|
//Set the error object for the current thread.
|
|
tls->punkError = pErrorInfo;
|
|
hr = S_OK;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::CErrorObject
|
|
//
|
|
// Synopsis: Constructor for COM error object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CErrorObject::CErrorObject()
|
|
: _refCount(1),
|
|
_pszSource(NULL),
|
|
_pszDescription(NULL),
|
|
_pszHelpFile(NULL)
|
|
{
|
|
_data.dwVersion = 0;
|
|
_data.dwHelpContext = 0;
|
|
_data.iid = GUID_NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::~CErrorObject
|
|
//
|
|
// Synopsis: Destructor for COM error object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
CErrorObject::~CErrorObject()
|
|
{
|
|
if(_pszSource != NULL)
|
|
PrivMemFree(_pszSource);
|
|
|
|
if(_pszDescription != NULL)
|
|
PrivMemFree(_pszDescription);
|
|
|
|
if(_pszHelpFile != NULL)
|
|
PrivMemFree(_pszHelpFile);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::QueryInterface
|
|
//
|
|
// Synopsis: Gets a pointer to the specified interface. The error object
|
|
// supports the IErrorInfo, ICreateErrorInfo, IMarshal, and
|
|
// IUnknown interfaces.
|
|
//
|
|
// Returns: S_OK, E_NOINTERFACE, E_INVALIDARG.
|
|
//
|
|
// Notes: Bad parameters will raise an exception. The exception
|
|
// handler catches exceptions and returns E_INVALIDARG.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::QueryInterface(
|
|
/* [in] */ REFIID riid,
|
|
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppv)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
_try
|
|
{
|
|
*ppv = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IMarshal))
|
|
{
|
|
AddRef();
|
|
*ppv = (IMarshal *) this;
|
|
}
|
|
else if (IsEqualIID(riid, IID_IUnknown) ||
|
|
IsEqualIID(riid, IID_ICreateErrorInfo))
|
|
{
|
|
AddRef();
|
|
*ppv = (ICreateErrorInfo *) this;
|
|
}
|
|
else if(IsEqualIID(riid, IID_IErrorInfo))
|
|
{
|
|
AddRef();
|
|
*ppv = (IErrorInfo *) this;
|
|
}
|
|
else
|
|
{
|
|
hr = E_NOINTERFACE;
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::AddRef
|
|
//
|
|
// Synopsis: Increments the reference count.
|
|
//
|
|
// Returns: Reference count.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
ULONG STDMETHODCALLTYPE CErrorObject::AddRef()
|
|
{
|
|
Win4Assert(_refCount > 0);
|
|
|
|
InterlockedIncrement(&_refCount);
|
|
return _refCount;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::Release
|
|
//
|
|
// Synopsis: Decrements the reference count.
|
|
//
|
|
// Returns: Reference count.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
ULONG STDMETHODCALLTYPE CErrorObject::Release()
|
|
{
|
|
ULONG count = _refCount - 1;
|
|
|
|
Win4Assert(_refCount > 0);
|
|
|
|
if(0 == InterlockedDecrement(&_refCount))
|
|
{
|
|
delete this;
|
|
count = 0;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::GetUnmarshalClass
|
|
//
|
|
// Synopsis: Get the CLSID of the COM error object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::GetUnmarshalClass(
|
|
/* [in] */ REFIID riid,
|
|
/* [unique][in] */ void __RPC_FAR *pv,
|
|
/* [in] */ DWORD dwDestContext,
|
|
/* [unique][in] */ void __RPC_FAR *pvDestContext,
|
|
/* [in] */ DWORD mshlflags,
|
|
/* [out] */ CLSID __RPC_FAR *pClassID)
|
|
{
|
|
*pClassID = CLSID_ErrorObject;
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::GetMarshalSizeMax
|
|
//
|
|
// Synopsis: Get the size of the marshalled COM error object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::GetMarshalSizeMax(
|
|
/* [in] */ REFIID riid,
|
|
/* [unique][in] */ void __RPC_FAR *pv,
|
|
/* [in] */ DWORD dwDestContext,
|
|
/* [unique][in] */ void __RPC_FAR *pvDestContext,
|
|
/* [in] */ DWORD mshlflags,
|
|
/* [out] */ DWORD __RPC_FAR *pSize)
|
|
{
|
|
ULONG cb;
|
|
|
|
cb = sizeof(_data);
|
|
cb += NdrStringSize(_pszSource);
|
|
cb += NdrStringSize(_pszDescription);
|
|
cb += NdrStringSize(_pszHelpFile);
|
|
|
|
*pSize = cb;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::MarshalInterface
|
|
//
|
|
// Synopsis: Marshal the COM error object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::MarshalInterface(
|
|
/* [unique][in] */ IStream __RPC_FAR *pStream,
|
|
/* [in] */ REFIID riid,
|
|
/* [unique][in] */ void __RPC_FAR *pv,
|
|
/* [in] */ DWORD dwDestContext,
|
|
/* [unique][in] */ void __RPC_FAR *pvDestContext,
|
|
/* [in] */ DWORD mshlflags)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = pStream->Write(&_data, sizeof(_data), NULL);
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = NdrStringWrite(pStream, _pszSource);
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = NdrStringWrite(pStream, _pszDescription);
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = NdrStringWrite(pStream, _pszHelpFile);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::UnmarshalInterface
|
|
//
|
|
// Synopsis: Unmarshal the COM error object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::UnmarshalInterface(
|
|
/* [unique][in] */ IStream __RPC_FAR *pStream,
|
|
/* [in] */ REFIID riid,
|
|
/* [out] */ void __RPC_FAR *__RPC_FAR *ppv)
|
|
{
|
|
HRESULT hr;
|
|
|
|
*ppv = NULL;
|
|
|
|
//Clear the error object.
|
|
if(_pszSource != NULL)
|
|
{
|
|
PrivMemFree(_pszSource);
|
|
_pszSource = NULL;
|
|
}
|
|
|
|
if(_pszDescription != NULL)
|
|
{
|
|
PrivMemFree(_pszDescription);
|
|
_pszDescription = NULL;
|
|
}
|
|
|
|
if(_pszHelpFile != NULL)
|
|
{
|
|
PrivMemFree(_pszHelpFile);
|
|
_pszHelpFile = NULL;
|
|
}
|
|
|
|
hr = pStream->Read(&_data, sizeof(_data), NULL);
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = NdrStringRead(pStream, &_pszSource);
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = NdrStringRead(pStream, &_pszDescription);
|
|
|
|
if(SUCCEEDED(hr))
|
|
hr = NdrStringRead(pStream, &_pszHelpFile);
|
|
|
|
//Check the version.
|
|
if(_data.dwVersion > 0)
|
|
{
|
|
_data.dwVersion = 0;
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = QueryInterface(riid, ppv);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::ReleaseMarshalData
|
|
//
|
|
// Synopsis: Release a marshalled COM error object.
|
|
//
|
|
// Notes: Just seek to the end of the marshalled error object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::ReleaseMarshalData(
|
|
/* [unique][in] */ IStream __RPC_FAR *pStm)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::DisconnectObject
|
|
//
|
|
// Synopsis: Disconnect the object.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::DisconnectObject(
|
|
/* [in] */ DWORD dwReserved)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::GetDescription
|
|
//
|
|
// Synopsis: Gets a textual description of the error.
|
|
//
|
|
// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
|
|
//
|
|
// Notes: Not thread-safe.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::GetDescription(
|
|
/* [out] */ BSTR __RPC_FAR *pBstrDescription)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR pTemp;
|
|
|
|
__try
|
|
{
|
|
*pBstrDescription = NULL;
|
|
|
|
if(_pszDescription != NULL)
|
|
{
|
|
pTemp = PrivSysAllocString(_pszDescription);
|
|
if(pTemp != NULL)
|
|
{
|
|
*pBstrDescription = pTemp;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::GetGUID
|
|
//
|
|
// Synopsis: Gets the IID of the interface that defined the error.
|
|
//
|
|
// Returns: S_OK, E_INVALIDARG.
|
|
//
|
|
// Notes: Not thread-safe.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::GetGUID(
|
|
/* [out] */ GUID __RPC_FAR *pGUID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
__try
|
|
{
|
|
*pGUID = _data.iid;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::GetHelpContext
|
|
//
|
|
// Synopsis: Gets the Help context ID for the error.
|
|
//
|
|
// Returns: S_OK, E_INVALIDARG.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::GetHelpContext(
|
|
/* [out] */ DWORD __RPC_FAR *pdwHelpContext)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
__try
|
|
{
|
|
*pdwHelpContext = _data.dwHelpContext;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::GetHelpFile
|
|
//
|
|
// Synopsis: Gets the path of the help file that describes the error.
|
|
//
|
|
// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
|
|
//
|
|
// Notes: Not thread-safe.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::GetHelpFile(
|
|
/* [out] */ BSTR __RPC_FAR *pBstrHelpFile)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR pTemp;
|
|
|
|
__try
|
|
{
|
|
*pBstrHelpFile = NULL;
|
|
|
|
if(_pszHelpFile != NULL)
|
|
{
|
|
pTemp = PrivSysAllocString(_pszHelpFile);
|
|
if(pTemp != NULL)
|
|
{
|
|
*pBstrHelpFile = pTemp;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::GetSource
|
|
//
|
|
// Synopsis: Gets the ProgID of the class that is the source of the error.
|
|
//
|
|
// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
|
|
//
|
|
// Notes: Not thread-safe.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::GetSource(
|
|
/* [out] */ BSTR __RPC_FAR *pBstrSource)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR pTemp;
|
|
|
|
__try
|
|
{
|
|
*pBstrSource = NULL;
|
|
|
|
if(_pszSource != NULL)
|
|
{
|
|
pTemp = PrivSysAllocString(_pszSource);
|
|
if(pTemp != NULL)
|
|
{
|
|
*pBstrSource = pTemp;
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::SetDescription
|
|
//
|
|
// Synopsis: Sets the textual description of the error.
|
|
//
|
|
// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::SetDescription(
|
|
/* [in] */ LPOLESTR pszDescription)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPOLESTR pTemp = NULL;
|
|
ULONG cb;
|
|
|
|
__try
|
|
{
|
|
if(pszDescription != NULL)
|
|
{
|
|
cb = (wcslen(pszDescription) + 1) * sizeof(OLECHAR);
|
|
pTemp = (LPOLESTR) PrivMemAlloc(cb);
|
|
if(pTemp != NULL)
|
|
{
|
|
memcpy(pTemp, pszDescription, cb);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
pTemp = (LPOLESTR) InterlockedExchange((long *)&_pszDescription,
|
|
(long) pTemp);
|
|
if(pTemp != NULL)
|
|
{
|
|
PrivMemFree(pTemp);
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::SetGUID
|
|
//
|
|
// Synopsis: Sets the IID of the interface that defined the error.
|
|
//
|
|
// Returns: S_OK, E_INVALIDARG.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::SetGUID(
|
|
/* [in] */ REFGUID rguid)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
__try
|
|
{
|
|
_data.iid = rguid;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::SetHelpContext
|
|
//
|
|
// Synopsis: Sets the Help context ID for the error.
|
|
//
|
|
// Returns: S_OK.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::SetHelpContext(
|
|
/* [in] */ DWORD dwHelpContext)
|
|
{
|
|
_data.dwHelpContext = dwHelpContext;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::SetHelpFile
|
|
//
|
|
// Synopsis: Sets the path of the Help file that describes the error.
|
|
//
|
|
// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::SetHelpFile(
|
|
/* [in] */ LPOLESTR pszHelpFile)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPOLESTR pTemp = NULL;
|
|
ULONG cb;
|
|
|
|
__try
|
|
{
|
|
if(pszHelpFile != NULL)
|
|
{
|
|
cb = (wcslen(pszHelpFile) + 1) * sizeof(OLECHAR);
|
|
pTemp = (LPOLESTR) PrivMemAlloc(cb);
|
|
if(pTemp != NULL)
|
|
{
|
|
memcpy(pTemp, pszHelpFile, cb);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
pTemp = (LPOLESTR) InterlockedExchange((long *)&_pszHelpFile,
|
|
(long) pTemp);
|
|
if(pTemp != NULL)
|
|
{
|
|
PrivMemFree(pTemp);
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Method: CErrorObject::SetSource
|
|
//
|
|
// Synopsis: Sets the source of the error.
|
|
//
|
|
// Returns: S_OK, E_OUTOFMEMORY, E_INVALIDARG.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT STDMETHODCALLTYPE CErrorObject::SetSource(
|
|
/* [in] */ LPOLESTR pszSource)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPOLESTR pTemp = NULL;
|
|
ULONG cb;
|
|
|
|
__try
|
|
{
|
|
if(pszSource != NULL)
|
|
{
|
|
cb = (wcslen(pszSource) + 1) * sizeof(OLECHAR);
|
|
pTemp = (LPOLESTR) PrivMemAlloc(cb);
|
|
if(pTemp != NULL)
|
|
{
|
|
memcpy(pTemp, pszSource, cb);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
pTemp = (LPOLESTR) InterlockedExchange((long *)&_pszSource,
|
|
(long) pTemp);
|
|
if(pTemp != NULL)
|
|
{
|
|
PrivMemFree(pTemp);
|
|
}
|
|
}
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|
|
struct NdrStringHeader
|
|
{
|
|
DWORD dwMax;
|
|
DWORD dwOffset;
|
|
DWORD dwActual;
|
|
};
|
|
|
|
struct NdrStringPtrHeader
|
|
{
|
|
DWORD dwUnique;
|
|
DWORD dwMax;
|
|
DWORD dwOffset;
|
|
DWORD dwActual;
|
|
};
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: NdrStringRead
|
|
//
|
|
// Synopsis: Reads a string from a stream in NDR format.
|
|
//
|
|
// Notes: The NDR format of a string is the following.
|
|
// DWORD - Represents the unique pointer.
|
|
// DWORD - Maximum number of elements.
|
|
// DWORD - offset.
|
|
// DWORD - Actual number of elements.
|
|
// NULL terminated UNICODE string.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT NdrStringRead(IStream *pStream, LPWSTR *ppsz)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dwUnique = 0;
|
|
ULONG cbRead = 0;
|
|
|
|
*ppsz = NULL;
|
|
|
|
//Check for a NULL pointer.
|
|
hr = pStream->Read(&dwUnique, sizeof(dwUnique), &cbRead);
|
|
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
Win4Assert(sizeof(dwUnique) == cbRead);
|
|
|
|
if(dwUnique != 0)
|
|
{
|
|
LPWSTR pTemp = NULL;
|
|
NdrStringHeader hdr;
|
|
|
|
hr = pStream->Read(&hdr, sizeof(hdr), &cbRead);
|
|
|
|
if(FAILED(hr))
|
|
return hr;
|
|
|
|
Win4Assert(sizeof(hdr) == cbRead);
|
|
Win4Assert(hdr.dwMax >= hdr.dwOffset + hdr.dwActual);
|
|
Win4Assert(0 == hdr.dwOffset);
|
|
|
|
pTemp = (LPWSTR) PrivMemAlloc(hdr.dwMax * sizeof(WCHAR));
|
|
|
|
if(pTemp != NULL)
|
|
{
|
|
hr = pStream->Read(pTemp,
|
|
hdr.dwActual * sizeof(WCHAR),
|
|
&cbRead);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
Win4Assert(hdr.dwActual * sizeof(WCHAR) == cbRead);
|
|
*ppsz = pTemp;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: NdrStringSize
|
|
//
|
|
// Synopsis: Computes the size of a marshalled string.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
ULONG NdrStringSize(LPCWSTR psz)
|
|
{
|
|
ULONG cb;
|
|
|
|
if(psz != NULL)
|
|
{
|
|
cb = sizeof(NdrStringPtrHeader);
|
|
cb += (wcslen(psz) + 1) * sizeof(WCHAR);
|
|
}
|
|
else
|
|
{
|
|
cb = sizeof(DWORD);
|
|
}
|
|
|
|
return cb;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: NdrStringWrite
|
|
//
|
|
// Synopsis: Writes a string to a stream in NDR format.
|
|
//
|
|
// Notes: The NDR format of a string is shown below.
|
|
// DWORD - Represents the unique pointer.
|
|
// DWORD - Maximum number of elements.
|
|
// DWORD - offset.
|
|
// DWORD - Number of elements.
|
|
// NULL terminated UNICODE string.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
HRESULT NdrStringWrite(IStream *pStream, LPCWSTR psz)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG cbWritten;
|
|
|
|
//Check for a NULL pointer.
|
|
if(psz != NULL)
|
|
{
|
|
NdrStringPtrHeader hdr;
|
|
|
|
//Write the header.
|
|
hdr.dwUnique = 0xFFFFFFFF;
|
|
hdr.dwMax = wcslen(psz) + 1;
|
|
hdr.dwOffset = 0;
|
|
hdr.dwActual = hdr.dwMax;
|
|
hr = pStream->Write(&hdr, sizeof(hdr), &cbWritten);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pStream->Write(psz, hdr.dwActual * sizeof(WCHAR), &cbWritten);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DWORD dwUnique = 0;
|
|
|
|
//Write a NULL unique pointer.
|
|
hr = pStream->Write(&dwUnique, sizeof(dwUnique), &cbWritten);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
|