/* * ErrorInfo API * * Copyright 2000 Patrik Stridvall, Juergen Schmied * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define COBJMACROS #include "oleauto.h" #include "combase_private.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); struct error_info { IErrorInfo IErrorInfo_iface; ICreateErrorInfo ICreateErrorInfo_iface; ISupportErrorInfo ISupportErrorInfo_iface; LONG refcount; GUID guid; WCHAR *source; WCHAR *description; WCHAR *help_file; DWORD help_context; }; static struct error_info *impl_from_IErrorInfo(IErrorInfo *iface) { return CONTAINING_RECORD(iface, struct error_info, IErrorInfo_iface); } static struct error_info *impl_from_ICreateErrorInfo(ICreateErrorInfo *iface) { return CONTAINING_RECORD(iface, struct error_info, ICreateErrorInfo_iface); } static struct error_info *impl_from_ISupportErrorInfo(ISupportErrorInfo *iface) { return CONTAINING_RECORD(iface, struct error_info, ISupportErrorInfo_iface); } static HRESULT WINAPI errorinfo_QueryInterface(IErrorInfo *iface, REFIID riid, void **obj) { struct error_info *error_info = impl_from_IErrorInfo(iface); TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj); *obj = NULL; if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IErrorInfo)) { *obj = &error_info->IErrorInfo_iface; } else if (IsEqualIID(riid, &IID_ICreateErrorInfo)) { *obj = &error_info->ICreateErrorInfo_iface; } else if (IsEqualIID(riid, &IID_ISupportErrorInfo)) { *obj = &error_info->ISupportErrorInfo_iface; } if (*obj) { IUnknown_AddRef((IUnknown *)*obj); return S_OK; } WARN("Unsupported interface %s.\n", debugstr_guid(riid)); return E_NOINTERFACE; } static ULONG WINAPI errorinfo_AddRef(IErrorInfo *iface) { struct error_info *error_info = impl_from_IErrorInfo(iface); ULONG refcount = InterlockedIncrement(&error_info->refcount); TRACE("%p, refcount %lu.\n", iface, refcount); return refcount; } static ULONG WINAPI errorinfo_Release(IErrorInfo *iface) { struct error_info *error_info = impl_from_IErrorInfo(iface); ULONG refcount = InterlockedDecrement(&error_info->refcount); TRACE("%p, refcount %lu.\n", iface, refcount); if (!refcount) { free(error_info->source); free(error_info->description); free(error_info->help_file); free(error_info); } return refcount; } static HRESULT WINAPI errorinfo_GetGUID(IErrorInfo *iface, GUID *guid) { struct error_info *error_info = impl_from_IErrorInfo(iface); TRACE("%p, %p.\n", iface, guid); if (!guid) return E_INVALIDARG; *guid = error_info->guid; return S_OK; } static HRESULT WINAPI errorinfo_GetSource(IErrorInfo* iface, BSTR *source) { struct error_info *error_info = impl_from_IErrorInfo(iface); TRACE("%p, %p.\n", iface, source); if (!source) return E_INVALIDARG; *source = SysAllocString(error_info->source); return S_OK; } static HRESULT WINAPI errorinfo_GetDescription(IErrorInfo *iface, BSTR *description) { struct error_info *error_info = impl_from_IErrorInfo(iface); TRACE("%p, %p.\n", iface, description); if (!description) return E_INVALIDARG; *description = SysAllocString(error_info->description); return S_OK; } static HRESULT WINAPI errorinfo_GetHelpFile(IErrorInfo *iface, BSTR *helpfile) { struct error_info *error_info = impl_from_IErrorInfo(iface); TRACE("%p, %p.\n", iface, helpfile); if (!helpfile) return E_INVALIDARG; *helpfile = SysAllocString(error_info->help_file); return S_OK; } static HRESULT WINAPI errorinfo_GetHelpContext(IErrorInfo *iface, DWORD *help_context) { struct error_info *error_info = impl_from_IErrorInfo(iface); TRACE("%p, %p.\n", iface, help_context); if (!help_context) return E_INVALIDARG; *help_context = error_info->help_context; return S_OK; } static const IErrorInfoVtbl errorinfo_vtbl = { errorinfo_QueryInterface, errorinfo_AddRef, errorinfo_Release, errorinfo_GetGUID, errorinfo_GetSource, errorinfo_GetDescription, errorinfo_GetHelpFile, errorinfo_GetHelpContext }; static HRESULT WINAPI create_errorinfo_QueryInterface(ICreateErrorInfo *iface, REFIID riid, void **obj) { struct error_info *error_info = impl_from_ICreateErrorInfo(iface); return IErrorInfo_QueryInterface(&error_info->IErrorInfo_iface, riid, obj); } static ULONG WINAPI create_errorinfo_AddRef(ICreateErrorInfo *iface) { struct error_info *error_info = impl_from_ICreateErrorInfo(iface); return IErrorInfo_AddRef(&error_info->IErrorInfo_iface); } static ULONG WINAPI create_errorinfo_Release(ICreateErrorInfo *iface) { struct error_info *error_info = impl_from_ICreateErrorInfo(iface); return IErrorInfo_Release(&error_info->IErrorInfo_iface); } static HRESULT WINAPI create_errorinfo_SetGUID(ICreateErrorInfo *iface, REFGUID guid) { struct error_info *error_info = impl_from_ICreateErrorInfo(iface); TRACE("%p, %s.\n", iface, debugstr_guid(guid)); error_info->guid = *guid; return S_OK; } static HRESULT WINAPI create_errorinfo_SetSource(ICreateErrorInfo *iface, LPOLESTR source) { struct error_info *error_info = impl_from_ICreateErrorInfo(iface); TRACE("%p, %s.\n", iface, debugstr_w(source)); free(error_info->source); error_info->source = wcsdup(source); return S_OK; } static HRESULT WINAPI create_errorinfo_SetDescription(ICreateErrorInfo *iface, LPOLESTR description) { struct error_info *error_info = impl_from_ICreateErrorInfo(iface); TRACE("%p, %s.\n", iface, debugstr_w(description)); free(error_info->description); error_info->description = wcsdup(description); return S_OK; } static HRESULT WINAPI create_errorinfo_SetHelpFile(ICreateErrorInfo *iface, LPOLESTR helpfile) { struct error_info *error_info = impl_from_ICreateErrorInfo(iface); TRACE("%p, %s.\n", iface, debugstr_w(helpfile)); free(error_info->help_file); error_info->help_file = wcsdup(helpfile); return S_OK; } static HRESULT WINAPI create_errorinfo_SetHelpContext(ICreateErrorInfo *iface, DWORD help_context) { struct error_info *error_info = impl_from_ICreateErrorInfo(iface); TRACE("%p, %#lx.\n", iface, help_context); error_info->help_context = help_context; return S_OK; } static const ICreateErrorInfoVtbl create_errorinfo_vtbl = { create_errorinfo_QueryInterface, create_errorinfo_AddRef, create_errorinfo_Release, create_errorinfo_SetGUID, create_errorinfo_SetSource, create_errorinfo_SetDescription, create_errorinfo_SetHelpFile, create_errorinfo_SetHelpContext }; static HRESULT WINAPI support_errorinfo_QueryInterface(ISupportErrorInfo *iface, REFIID riid, void **obj) { struct error_info *error_info = impl_from_ISupportErrorInfo(iface); return IErrorInfo_QueryInterface(&error_info->IErrorInfo_iface, riid, obj); } static ULONG WINAPI support_errorinfo_AddRef(ISupportErrorInfo *iface) { struct error_info *error_info = impl_from_ISupportErrorInfo(iface); return IErrorInfo_AddRef(&error_info->IErrorInfo_iface); } static ULONG WINAPI support_errorinfo_Release(ISupportErrorInfo *iface) { struct error_info *error_info = impl_from_ISupportErrorInfo(iface); return IErrorInfo_Release(&error_info->IErrorInfo_iface); } static HRESULT WINAPI support_errorinfo_InterfaceSupportsErrorInfo(ISupportErrorInfo *iface, REFIID riid) { struct error_info *error_info = impl_from_ISupportErrorInfo(iface); TRACE("%p, %s.\n", iface, debugstr_guid(riid)); return IsEqualIID(riid, &error_info->guid) ? S_OK : S_FALSE; } static const ISupportErrorInfoVtbl support_errorinfo_vtbl = { support_errorinfo_QueryInterface, support_errorinfo_AddRef, support_errorinfo_Release, support_errorinfo_InterfaceSupportsErrorInfo }; /*********************************************************************** * CreateErrorInfo (combase.@) */ HRESULT WINAPI CreateErrorInfo(ICreateErrorInfo **ret) { struct error_info *error_info; TRACE("%p.\n", ret); if (!ret) return E_INVALIDARG; if (!(error_info = malloc(sizeof(*error_info)))) return E_OUTOFMEMORY; error_info->IErrorInfo_iface.lpVtbl = &errorinfo_vtbl; error_info->ICreateErrorInfo_iface.lpVtbl = &create_errorinfo_vtbl; error_info->ISupportErrorInfo_iface.lpVtbl = &support_errorinfo_vtbl; error_info->refcount = 1; error_info->source = NULL; error_info->description = NULL; error_info->help_file = NULL; error_info->help_context = 0; *ret = &error_info->ICreateErrorInfo_iface; return S_OK; } /*********************************************************************** * GetErrorInfo (combase.@) */ HRESULT WINAPI GetErrorInfo(ULONG reserved, IErrorInfo **error_info) { struct tlsdata *tlsdata; HRESULT hr; TRACE("%lu, %p\n", reserved, error_info); if (reserved || !error_info) return E_INVALIDARG; if (FAILED(hr = com_get_tlsdata(&tlsdata))) return hr; if (!tlsdata->errorinfo) { *error_info = NULL; return S_FALSE; } *error_info = tlsdata->errorinfo; tlsdata->errorinfo = NULL; return S_OK; } /*********************************************************************** * SetErrorInfo (combase.@) */ HRESULT WINAPI SetErrorInfo(ULONG reserved, IErrorInfo *error_info) { struct tlsdata *tlsdata; HRESULT hr; TRACE("%lu, %p\n", reserved, error_info); if (reserved) return E_INVALIDARG; if (FAILED(hr = com_get_tlsdata(&tlsdata))) return hr; if (tlsdata->errorinfo) IErrorInfo_Release(tlsdata->errorinfo); tlsdata->errorinfo = error_info; if (error_info) IErrorInfo_AddRef(error_info); return S_OK; }