/* OLE DB ErrorInfo
 *
 * Copyright 2013 Alistair Leslie-Hughes
 *
 * 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
 */
#include <stdarg.h>
#include <string.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "oleauto.h"
#include "winerror.h"
#include "oledb.h"
#include "oledberr.h"

#include "oledb_private.h"

#include "wine/unicode.h"
#include "wine/list.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(oledb);

struct ErrorEntry
{
    ERRORINFO       info;
    DISPPARAMS      dispparams;
    IUnknown        *custom_error;
    DWORD           lookupID;
};

typedef struct errorrecords
{
    IErrorInfo     IErrorInfo_iface;
    IErrorRecords  IErrorRecords_iface;
    LONG ref;

    struct ErrorEntry *records;
    unsigned int allocated;
    unsigned int count;
} errorrecords;

static inline errorrecords *impl_from_IErrorInfo( IErrorInfo *iface )
{
    return CONTAINING_RECORD(iface, errorrecords, IErrorInfo_iface);
}

static inline errorrecords *impl_from_IErrorRecords( IErrorRecords *iface )
{
    return CONTAINING_RECORD(iface, errorrecords, IErrorRecords_iface);
}

static HRESULT WINAPI errorrecords_QueryInterface(IErrorInfo* iface, REFIID riid, void **ppvoid)
{
    errorrecords *This = impl_from_IErrorInfo(iface);
    TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid),ppvoid);

    *ppvoid = NULL;

    if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IErrorInfo))
    {
      *ppvoid = &This->IErrorInfo_iface;
    }
    else if (IsEqualIID(riid, &IID_IErrorRecords))
    {
      *ppvoid = &This->IErrorRecords_iface;
    }

    if(*ppvoid)
    {
      IUnknown_AddRef( (IUnknown*)*ppvoid );
      return S_OK;
    }

    FIXME("interface %s not implemented\n", debugstr_guid(riid));
    return E_NOINTERFACE;
}

static ULONG WINAPI errorrecords_AddRef(IErrorInfo* iface)
{
    errorrecords *This = impl_from_IErrorInfo(iface);
    TRACE("(%p)->%u\n",This,This->ref);
    return InterlockedIncrement(&This->ref);
}

static ULONG WINAPI errorrecords_Release(IErrorInfo* iface)
{
    errorrecords *This = impl_from_IErrorInfo(iface);
    ULONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p)->%u\n",This,ref+1);

    if (!ref)
    {
        unsigned int i;

        for (i = 0; i < This->count; i++)
        {
            DISPPARAMS *dispparams = &This->records[i].dispparams;
            unsigned int j;

            if (This->records[i].custom_error)
                IUnknown_Release(This->records[i].custom_error);

            for (j = 0; j < dispparams->cArgs && dispparams->rgvarg; j++)
                VariantClear(&dispparams->rgvarg[i]);
            CoTaskMemFree(dispparams->rgvarg);
            CoTaskMemFree(dispparams->rgdispidNamedArgs);
        }
        heap_free(This->records);
        heap_free(This);
    }
    return ref;
}

static HRESULT WINAPI errorrecords_GetGUID(IErrorInfo* iface, GUID *guid)
{
    errorrecords *This = impl_from_IErrorInfo(iface);

    TRACE("(%p)->(%p)\n", This, guid);

    if (!guid)
        return E_INVALIDARG;

    *guid = GUID_NULL;

    return S_OK;
}

static HRESULT WINAPI errorrecords_GetSource(IErrorInfo* iface, BSTR *source)
{
    errorrecords *This = impl_from_IErrorInfo(iface);

    TRACE("(%p)->(%p)\n", This, source);

    if (!source)
        return E_INVALIDARG;

    *source = NULL;

    return E_FAIL;
}

static HRESULT WINAPI errorrecords_GetDescription(IErrorInfo* iface, BSTR *description)
{
    errorrecords *This = impl_from_IErrorInfo(iface);

    TRACE("(%p)->(%p)\n", This, description);

    if (!description)
        return E_INVALIDARG;

    *description = NULL;

    return E_FAIL;
}

static HRESULT WINAPI errorrecords_GetHelpFile(IErrorInfo* iface, BSTR *helpfile)
{
    errorrecords *This = impl_from_IErrorInfo(iface);

    TRACE("(%p)->(%p)\n", This, helpfile);

    if (!helpfile)
        return E_INVALIDARG;

    *helpfile = NULL;

    return E_FAIL;
}

static HRESULT WINAPI errorrecords_GetHelpContext(IErrorInfo* iface, DWORD *context)
{
    errorrecords *This = impl_from_IErrorInfo(iface);

    TRACE("(%p)->(%p)\n", This, context);

    if (!context)
        return E_INVALIDARG;

    *context = 0;

    return E_FAIL;
}

static const IErrorInfoVtbl ErrorInfoVtbl =
{
    errorrecords_QueryInterface,
    errorrecords_AddRef,
    errorrecords_Release,
    errorrecords_GetGUID,
    errorrecords_GetSource,
    errorrecords_GetDescription,
    errorrecords_GetHelpFile,
    errorrecords_GetHelpContext
};

static HRESULT WINAPI errorrec_QueryInterface(IErrorRecords *iface, REFIID riid, void **ppvObject)
{
    errorrecords *This = impl_from_IErrorRecords(iface);
    return IErrorInfo_QueryInterface(&This->IErrorInfo_iface, riid, ppvObject);
}

static ULONG WINAPI WINAPI errorrec_AddRef(IErrorRecords *iface)
{
    errorrecords *This = impl_from_IErrorRecords(iface);
    return IErrorInfo_AddRef(&This->IErrorInfo_iface);
}

static ULONG WINAPI WINAPI errorrec_Release(IErrorRecords *iface)
{
    errorrecords *This = impl_from_IErrorRecords(iface);
    return IErrorInfo_Release(&This->IErrorInfo_iface);
}

static HRESULT dup_dispparams(DISPPARAMS *src, DISPPARAMS *dest)
{
    unsigned int i;

    if (!src)
    {
        memset(dest, 0, sizeof(*dest));
        return S_OK;
    }

    *dest = *src;

    if (src->cArgs)
    {
        dest->rgvarg = CoTaskMemAlloc(dest->cArgs * sizeof(*dest->rgvarg));
        for (i = 0; i < src->cArgs; i++)
        {
            VariantInit(&dest->rgvarg[i]);
            VariantCopy(&dest->rgvarg[i], &src->rgvarg[i]);
        }
    }

    if (src->cNamedArgs)
    {
        dest->rgdispidNamedArgs = CoTaskMemAlloc(dest->cNamedArgs * sizeof(*dest->rgdispidNamedArgs));
        memcpy(dest->rgdispidNamedArgs, src->rgdispidNamedArgs, dest->cNamedArgs * sizeof(*dest->rgdispidNamedArgs));
    }

    return S_OK;
}

static HRESULT WINAPI errorrec_AddErrorRecord(IErrorRecords *iface, ERRORINFO *pErrorInfo,
        DWORD dwLookupID, DISPPARAMS *pdispparams, IUnknown *punkCustomError, DWORD dwDynamicErrorID)
{
    errorrecords *This = impl_from_IErrorRecords(iface);
    struct ErrorEntry *entry;
    HRESULT hr;

    TRACE("(%p)->(%p %d %p %p %d)\n", This, pErrorInfo, dwLookupID, pdispparams, punkCustomError, dwDynamicErrorID);

    if(!pErrorInfo)
        return E_INVALIDARG;

    if (!This->records)
    {
        const unsigned int initial_size = 16;
        if (!(This->records = heap_alloc(initial_size * sizeof(*This->records))))
            return E_OUTOFMEMORY;

        This->allocated = initial_size;
    }
    else if (This->count == This->allocated)
    {
        struct ErrorEntry *new_ptr;

        new_ptr = heap_realloc(This->records, 2 * This->allocated * sizeof(*This->records));
        if (!new_ptr)
            return E_OUTOFMEMORY;

        This->records = new_ptr;
        This->allocated *= 2;
    }

    entry = This->records + This->count;
    entry->info = *pErrorInfo;

    if (FAILED(hr = dup_dispparams(pdispparams, &entry->dispparams)))
        return hr;

    entry->custom_error = punkCustomError;
    if (entry->custom_error)
        IUnknown_AddRef(entry->custom_error);
    entry->lookupID = dwDynamicErrorID;

    This->count++;

    return S_OK;
}

static HRESULT WINAPI errorrec_GetBasicErrorInfo(IErrorRecords *iface, ULONG index, ERRORINFO *info)
{
    errorrecords *This = impl_from_IErrorRecords(iface);

    TRACE("(%p)->(%u %p)\n", This, index, info);

    if (!info)
        return E_INVALIDARG;

    if (index >= This->count)
        return DB_E_BADRECORDNUM;

    index = This->count - index - 1;
    *info = This->records[index].info;
    return S_OK;
}

static HRESULT WINAPI errorrec_GetCustomErrorObject(IErrorRecords *iface, ULONG index,
        REFIID riid, IUnknown **object)
{
    errorrecords *This = impl_from_IErrorRecords(iface);

    TRACE("(%p)->(%u %s %p)\n", This, index, debugstr_guid(riid), object);

    if (!object)
        return E_INVALIDARG;

    *object = NULL;

    if (index >= This->count)
        return DB_E_BADRECORDNUM;

    index = This->count - index - 1;
    if (This->records[index].custom_error)
        return IUnknown_QueryInterface(This->records[index].custom_error, riid, (void **)object);
    else
        return S_OK;
}

static HRESULT WINAPI errorrec_GetErrorInfo(IErrorRecords *iface, ULONG index,
        LCID lcid, IErrorInfo **ppErrorInfo)
{
    errorrecords *This = impl_from_IErrorRecords(iface);

    FIXME("(%p)->(%u %d, %p)\n", This, index, lcid, ppErrorInfo);

    if (!ppErrorInfo)
        return E_INVALIDARG;

    if (index >= This->count)
        return DB_E_BADRECORDNUM;

    return E_NOTIMPL;
}

static HRESULT WINAPI errorrec_GetErrorParameters(IErrorRecords *iface, ULONG index, DISPPARAMS *pdispparams)
{
    errorrecords *This = impl_from_IErrorRecords(iface);

    TRACE("(%p)->(%u %p)\n", This, index, pdispparams);

    if (!pdispparams)
        return E_INVALIDARG;

    if (index >= This->count)
        return DB_E_BADRECORDNUM;

    index = This->count - index - 1;
    return dup_dispparams(&This->records[index].dispparams, pdispparams);
}

static HRESULT WINAPI errorrec_GetRecordCount(IErrorRecords *iface, ULONG *count)
{
    errorrecords *This = impl_from_IErrorRecords(iface);

    TRACE("(%p)->(%p)\n", This, count);

    if(!count)
        return E_INVALIDARG;

    *count = This->count;

    TRACE("<--(%u)\n", *count);

    return S_OK;
}

static const IErrorRecordsVtbl ErrorRecordsVtbl =
{
    errorrec_QueryInterface,
    errorrec_AddRef,
    errorrec_Release,
    errorrec_AddErrorRecord,
    errorrec_GetBasicErrorInfo,
    errorrec_GetCustomErrorObject,
    errorrec_GetErrorInfo,
    errorrec_GetErrorParameters,
    errorrec_GetRecordCount
};

HRESULT create_error_info(IUnknown *outer, void **obj)
{
    errorrecords *This;

    TRACE("(%p, %p)\n", outer, obj);

    *obj = NULL;

    if(outer) return CLASS_E_NOAGGREGATION;

    This = heap_alloc(sizeof(*This));
    if(!This) return E_OUTOFMEMORY;

    This->IErrorInfo_iface.lpVtbl = &ErrorInfoVtbl;
    This->IErrorRecords_iface.lpVtbl = &ErrorRecordsVtbl;
    This->ref = 1;

    This->records = NULL;
    This->allocated = 0;
    This->count = 0;

    *obj = &This->IErrorInfo_iface;

    return S_OK;
}
