| /* |
| * ErrorInfo API |
| * |
| * Copyright 2000 Patrik Stridvall, Juergen Schmied |
| * |
| * |
| * The errorinfo is a per-thread object. The reference is stored in the |
| * TEB at offset 0xf80 |
| */ |
| |
| #include "debugtools.h" |
| #include "windef.h" |
| #include "heap.h" |
| #include "winerror.h" |
| #include "thread.h" |
| #include "debugtools.h" |
| #include "wine/obj_errorinfo.h" |
| |
| DEFAULT_DEBUG_CHANNEL(ole) |
| |
| typedef struct ErrorInfoImpl |
| { |
| ICOM_VTABLE(IErrorInfo) *lpvtei; |
| ICOM_VTABLE(ICreateErrorInfo) *lpvtcei; |
| ICOM_VTABLE(ISupportErrorInfo) *lpvtsei; |
| DWORD ref; |
| |
| const GUID *pGuid; |
| } ErrorInfoImpl; |
| |
| static ICOM_VTABLE(IErrorInfo) IErrorInfoImpl_VTable; |
| static ICOM_VTABLE(ICreateErrorInfo) ICreateErrorInfoImpl_VTable; |
| static ICOM_VTABLE(ISupportErrorInfo) ISupportErrorInfoImpl_VTable; |
| |
| /* |
| converts a objectpointer to This |
| */ |
| #define _IErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtei))) |
| #define _ICOM_THIS_From_IErrorInfo(class, name) class* This = (class*)(((char*)name)-_IErrorInfo_Offset); |
| |
| #define _ICreateErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtcei))) |
| #define _ICOM_THIS_From_ICreateErrorInfo(class, name) class* This = (class*)(((char*)name)-_ICreateErrorInfo_Offset); |
| |
| #define _ISupportErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtsei))) |
| #define _ICOM_THIS_From_ISupportErrorInfo(class, name) class* This = (class*)(((char*)name)-_ISupportErrorInfo_Offset); |
| |
| /* |
| converts This to a objectpointer |
| */ |
| #define _IErrorInfo_(This) (IErrorInfo*)&(This->lpvtei) |
| #define _ICreateErrorInfo_(This) (ICreateErrorInfo*)&(This->lpvtcei) |
| #define _ISupportErrorInfo_(This) (ISupportErrorInfo*)&(This->lpvtsei) |
| |
| IErrorInfo * IErrorInfoImpl_Constructor() |
| { |
| ErrorInfoImpl * ei = HeapAlloc(GetProcessHeap(), 0, sizeof(ErrorInfoImpl)); |
| if (ei) |
| { |
| ei->lpvtei = &IErrorInfoImpl_VTable; |
| ei->lpvtcei = &ICreateErrorInfoImpl_VTable; |
| ei->lpvtsei = &ISupportErrorInfoImpl_VTable; |
| ei->ref = 1; |
| } |
| return (IErrorInfo *)ei; |
| } |
| |
| |
| static HRESULT WINAPI IErrorInfoImpl_QueryInterface( |
| IErrorInfo* iface, |
| REFIID riid, |
| VOID** ppvoid) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvoid); |
| |
| *ppvoid = NULL; |
| |
| if(IsEqualIID(riid, &IID_IErrorInfo)) |
| { |
| *ppvoid = _IErrorInfo_(This); |
| } |
| else if(IsEqualIID(riid, &IID_ICreateErrorInfo)) |
| { |
| *ppvoid = _ICreateErrorInfo_(This); |
| } |
| else if(IsEqualIID(riid, &IID_ISupportErrorInfo)) |
| { |
| *ppvoid = _ISupportErrorInfo_(This); |
| } |
| |
| if(*ppvoid) |
| { |
| IUnknown_AddRef( (IUnknown*)*ppvoid ); |
| TRACE("-- Interface: (%p)->(%p)\n",ppvoid,*ppvoid); |
| return S_OK; |
| } |
| TRACE("-- Interface: E_NOINTERFACE\n"); |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI IErrorInfoImpl_AddRef( |
| IErrorInfo* iface) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)->(count=%lu)\n",This,This->ref); |
| return InterlockedIncrement(&This->ref); |
| } |
| |
| static ULONG WINAPI IErrorInfoImpl_Release( |
| IErrorInfo* iface) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)->(count=%lu)\n",This,This->ref); |
| |
| if (!InterlockedDecrement(&This->ref)) |
| { |
| TRACE("-- destroying IErrorInfo(%p)\n",This); |
| HeapFree(GetProcessHeap(),0,This); |
| return 0; |
| } |
| return This->ref; |
| } |
| |
| static HRESULT WINAPI IErrorInfoImpl_GetTypeInfoCount( |
| IErrorInfo* iface, |
| unsigned int* pctinfo) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI IErrorInfoImpl_GetTypeInfo( |
| IErrorInfo* iface, |
| UINT iTInfo, |
| LCID lcid, |
| ITypeInfo** ppTInfo) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI IErrorInfoImpl_GetIDsOfNames( |
| IErrorInfo* iface, |
| REFIID riid, |
| LPOLESTR* rgszNames, |
| UINT cNames, |
| LCID lcid, |
| DISPID* rgDispId) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI IErrorInfoImpl_Invoke( |
| IErrorInfo* iface, |
| DISPID dispIdMember, |
| REFIID riid, |
| LCID lcid, |
| WORD wFlags, |
| DISPPARAMS* pDispParams, |
| VARIANT* pVarResult, |
| EXCEPINFO* pExepInfo, |
| UINT* puArgErr) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| /* FIXME: is this OK? Original is GUID* pGUID! This can't work! (js) */ |
| static HRESULT WINAPI IErrorInfoImpl_GetGUID( |
| IErrorInfo* iface, |
| GUID const ** pGUID) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p) check function prototype\n", This); |
| |
| if(!pGUID || !*pGUID)return E_INVALIDARG; |
| *pGUID = This->pGuid; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI IErrorInfoImpl_GetSource( |
| IErrorInfo* iface, |
| BSTR *pBstrSource) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI IErrorInfoImpl_GetDescription( |
| IErrorInfo* iface, |
| BSTR *pBstrDescription) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI IErrorInfoImpl_GetHelpFile( |
| IErrorInfo* iface, |
| BSTR *pBstrHelpFile) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI IErrorInfoImpl_GetHelpContext( |
| IErrorInfo* iface, |
| DWORD *pdwHelpContext) |
| { |
| _ICOM_THIS_From_IErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static ICOM_VTABLE(IErrorInfo) IErrorInfoImpl_VTable = |
| { |
| ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE |
| IErrorInfoImpl_QueryInterface, |
| IErrorInfoImpl_AddRef, |
| IErrorInfoImpl_Release, |
| IErrorInfoImpl_GetTypeInfoCount, |
| IErrorInfoImpl_GetTypeInfo, |
| IErrorInfoImpl_GetIDsOfNames, |
| IErrorInfoImpl_Invoke, |
| |
| IErrorInfoImpl_GetGUID, |
| IErrorInfoImpl_GetSource, |
| IErrorInfoImpl_GetDescription, |
| IErrorInfoImpl_GetHelpFile, |
| IErrorInfoImpl_GetHelpContext |
| }; |
| |
| |
| static HRESULT WINAPI ICreateErrorInfoImpl_QueryInterface( |
| ICreateErrorInfo* iface, |
| REFIID riid, |
| VOID** ppvoid) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_QueryInterface(_IErrorInfo_(This), riid, ppvoid); |
| } |
| |
| static ULONG WINAPI ICreateErrorInfoImpl_AddRef( |
| ICreateErrorInfo* iface) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_AddRef(_IErrorInfo_(This)); |
| } |
| |
| static ULONG WINAPI ICreateErrorInfoImpl_Release( |
| ICreateErrorInfo* iface) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_Release(_IErrorInfo_(This)); |
| } |
| |
| static HRESULT WINAPI ICreateErrorInfoImpl_GetTypeInfoCount( |
| ICreateErrorInfo* iface, |
| unsigned int* pctinfo) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_GetTypeInfoCount(_IErrorInfo_(This), pctinfo); |
| } |
| |
| static HRESULT WINAPI ICreateErrorInfoImpl_GetTypeInfo( |
| ICreateErrorInfo* iface, |
| UINT iTInfo, |
| LCID lcid, |
| ITypeInfo** ppTInfo) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_GetTypeInfo(_IErrorInfo_(This),iTInfo,lcid,ppTInfo); |
| } |
| |
| static HRESULT WINAPI ICreateErrorInfoImpl_GetIDsOfNames( |
| ICreateErrorInfo* iface, |
| REFIID riid, |
| LPOLESTR* rgszNames, |
| UINT cNames, |
| LCID lcid, |
| DISPID* rgDispId) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_GetIDsOfNames(_IErrorInfo_(This),riid,rgszNames,cNames,lcid,rgDispId); |
| } |
| |
| static HRESULT WINAPI ICreateErrorInfoImpl_Invoke( |
| ICreateErrorInfo* iface, |
| DISPID dispIdMember, |
| REFIID riid, |
| LCID lcid, |
| WORD wFlags, |
| DISPPARAMS* pDispParams, |
| VARIANT* pVarResult, |
| EXCEPINFO* pExepInfo, |
| UINT* puArgErr) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_Invoke(_IErrorInfo_(This),dispIdMember,riid,lcid,wFlags,pDispParams, |
| pVarResult,pExepInfo,puArgErr); |
| } |
| |
| static HRESULT WINAPI ICreateErrorInfoImpl_SetGUID( |
| ICreateErrorInfo* iface, |
| REFGUID rguid) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)->(%s)\n", This, debugstr_guid(rguid)); |
| This->pGuid = rguid; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI ICreateErrorInfoImpl_SetSource( |
| ICreateErrorInfo* iface, |
| LPOLESTR szSource) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ICreateErrorInfoImpl_SetDescription( |
| ICreateErrorInfo* iface, |
| LPOLESTR szDescription) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ICreateErrorInfoImpl_SetHelpFile( |
| ICreateErrorInfo* iface, |
| LPOLESTR szHelpFile) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI ICreateErrorInfoImpl_SetHelpContext( |
| ICreateErrorInfo* iface, |
| DWORD dwHelpContext) |
| { |
| _ICOM_THIS_From_ICreateErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return E_NOTIMPL; |
| } |
| |
| static ICOM_VTABLE(ICreateErrorInfo) ICreateErrorInfoImpl_VTable = |
| { |
| ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE |
| ICreateErrorInfoImpl_QueryInterface, |
| ICreateErrorInfoImpl_AddRef, |
| ICreateErrorInfoImpl_Release, |
| |
| ICreateErrorInfoImpl_GetTypeInfoCount, |
| ICreateErrorInfoImpl_GetTypeInfo, |
| ICreateErrorInfoImpl_GetIDsOfNames, |
| ICreateErrorInfoImpl_Invoke, |
| |
| ICreateErrorInfoImpl_SetGUID, |
| ICreateErrorInfoImpl_SetSource, |
| ICreateErrorInfoImpl_SetDescription, |
| ICreateErrorInfoImpl_SetHelpFile, |
| ICreateErrorInfoImpl_SetHelpContext |
| }; |
| |
| static HRESULT WINAPI ISupportErrorInfoImpl_QueryInterface( |
| ISupportErrorInfo* iface, |
| REFIID riid, |
| VOID** ppvoid) |
| { |
| _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface); |
| FIXME("(%p)\n", This); |
| |
| return IErrorInfo_QueryInterface(_IErrorInfo_(This), riid, ppvoid); |
| } |
| |
| static ULONG WINAPI ISupportErrorInfoImpl_AddRef( |
| ISupportErrorInfo* iface) |
| { |
| _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_AddRef(_IErrorInfo_(This)); |
| } |
| |
| static ULONG WINAPI ISupportErrorInfoImpl_Release( |
| ISupportErrorInfo* iface) |
| { |
| _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_Release(_IErrorInfo_(This)); |
| } |
| |
| static HRESULT WINAPI ISupportErrorInfoImpl_GetTypeInfoCount( |
| ISupportErrorInfo* iface, |
| unsigned int* pctinfo) |
| { |
| _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_GetTypeInfoCount(_IErrorInfo_(This), pctinfo); |
| } |
| |
| static HRESULT WINAPI ISupportErrorInfoImpl_GetTypeInfo( |
| ISupportErrorInfo* iface, |
| UINT iTInfo, |
| LCID lcid, |
| ITypeInfo** ppTInfo) |
| { |
| _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_GetTypeInfo(_IErrorInfo_(This),iTInfo,lcid,ppTInfo); |
| } |
| |
| static HRESULT WINAPI ISupportErrorInfoImpl_GetIDsOfNames( |
| ISupportErrorInfo* iface, |
| REFIID riid, |
| LPOLESTR* rgszNames, |
| UINT cNames, |
| LCID lcid, |
| DISPID* rgDispId) |
| { |
| _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_GetIDsOfNames(_IErrorInfo_(This),riid,rgszNames,cNames,lcid,rgDispId); |
| } |
| |
| static HRESULT WINAPI ISupportErrorInfoImpl_Invoke( |
| ISupportErrorInfo* iface, |
| DISPID dispIdMember, |
| REFIID riid, |
| LCID lcid, |
| WORD wFlags, |
| DISPPARAMS* pDispParams, |
| VARIANT* pVarResult, |
| EXCEPINFO* pExepInfo, |
| UINT* puArgErr) |
| { |
| _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)\n", This); |
| return IErrorInfo_Invoke(_IErrorInfo_(This),dispIdMember,riid,lcid,wFlags,pDispParams, |
| pVarResult,pExepInfo,puArgErr); |
| } |
| |
| static HRESULT WINAPI ISupportErrorInfoImpl_InterfaceSupportsErrorInfo( |
| ISupportErrorInfo* iface, |
| REFIID riid) |
| { |
| _ICOM_THIS_From_ISupportErrorInfo(ErrorInfoImpl, iface); |
| TRACE("(%p)->(%s)\n", This, debugstr_guid(riid)); |
| return (riid == This->pGuid) ? S_OK : S_FALSE; |
| } |
| |
| static ICOM_VTABLE(ISupportErrorInfo) ISupportErrorInfoImpl_VTable = |
| { |
| ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE |
| ISupportErrorInfoImpl_QueryInterface, |
| ISupportErrorInfoImpl_AddRef, |
| ISupportErrorInfoImpl_Release, |
| |
| ISupportErrorInfoImpl_GetTypeInfoCount, |
| ISupportErrorInfoImpl_GetTypeInfo, |
| ISupportErrorInfoImpl_GetIDsOfNames, |
| ISupportErrorInfoImpl_Invoke, |
| |
| ISupportErrorInfoImpl_InterfaceSupportsErrorInfo |
| }; |
| /*********************************************************************** |
| * CreateErrorInfo |
| */ |
| HRESULT WINAPI CreateErrorInfo(ICreateErrorInfo **pperrinfo) |
| { |
| IErrorInfo * pei; |
| HRESULT res; |
| |
| TRACE("(%p): stub:\n", pperrinfo); |
| |
| if(! pperrinfo || !*pperrinfo) return E_INVALIDARG; |
| if(!(pei=IErrorInfoImpl_Constructor()))return E_OUTOFMEMORY; |
| |
| res = IErrorInfo_QueryInterface(pei, &IID_ICreateErrorInfo, (LPVOID*)pperrinfo); |
| IErrorInfo_Release(pei); |
| return res; |
| } |
| |
| /*********************************************************************** |
| * GetErrorInfo |
| */ |
| HRESULT WINAPI GetErrorInfo(ULONG dwReserved, IErrorInfo **pperrinfo) |
| { |
| TRACE("(%ld, %p): stub:\n", dwReserved, pperrinfo); |
| |
| if(! pperrinfo || !*pperrinfo) return E_INVALIDARG; |
| if(!(*pperrinfo = (IErrorInfo*)(NtCurrentTeb()->ErrorInfo))) return S_FALSE; |
| |
| /* clear thread error state */ |
| NtCurrentTeb()->ErrorInfo = NULL; |
| return S_OK; |
| } |
| |
| /*********************************************************************** |
| * SetErrorInfo |
| */ |
| HRESULT WINAPI SetErrorInfo(ULONG dwReserved, IErrorInfo *perrinfo) |
| { |
| IErrorInfo * pei; |
| TRACE("(%ld, %p): stub:\n", dwReserved, perrinfo); |
| |
| /* release old errorinfo */ |
| pei = (IErrorInfo*)NtCurrentTeb()->ErrorInfo; |
| if(pei) IErrorInfo_Release(pei); |
| |
| /* set to new value */ |
| NtCurrentTeb()->ErrorInfo = perrinfo; |
| if(perrinfo) IErrorInfo_AddRef(perrinfo); |
| return S_OK; |
| } |