wine/dlls/combase/errorinfo.c
2022-12-07 13:51:37 +01:00

395 lines
10 KiB
C

/*
* 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
#define WINOLEAUTAPI
#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;
}