/*
 * Copyright 2009 Hans Leidekker for CodeWeavers
 *
 * 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 "config.h"
#include <stdarg.h>
#include <stdio.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "ole2.h"
#include "netfw.h"

#include "wine/debug.h"
#include "wine/unicode.h"
#include "hnetcfg_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(hnetcfg);

typedef struct fw_app
{
    INetFwAuthorizedApplication INetFwAuthorizedApplication_iface;
    LONG refs;
} fw_app;

static inline fw_app *impl_from_INetFwAuthorizedApplication( INetFwAuthorizedApplication *iface )
{
    return CONTAINING_RECORD(iface, fw_app, INetFwAuthorizedApplication_iface);
}

static ULONG WINAPI fw_app_AddRef(
    INetFwAuthorizedApplication *iface )
{
    fw_app *fw_app = impl_from_INetFwAuthorizedApplication( iface );
    return InterlockedIncrement( &fw_app->refs );
}

static ULONG WINAPI fw_app_Release(
    INetFwAuthorizedApplication *iface )
{
    fw_app *fw_app = impl_from_INetFwAuthorizedApplication( iface );
    LONG refs = InterlockedDecrement( &fw_app->refs );
    if (!refs)
    {
        TRACE("destroying %p\n", fw_app);
        HeapFree( GetProcessHeap(), 0, fw_app );
    }
    return refs;
}

static HRESULT WINAPI fw_app_QueryInterface(
    INetFwAuthorizedApplication *iface,
    REFIID riid,
    void **ppvObject )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );

    if ( IsEqualGUID( riid, &IID_INetFwAuthorizedApplication ) ||
         IsEqualGUID( riid, &IID_IDispatch ) ||
         IsEqualGUID( riid, &IID_IUnknown ) )
    {
        *ppvObject = iface;
    }
    else
    {
        FIXME("interface %s not implemented\n", debugstr_guid(riid));
        return E_NOINTERFACE;
    }
    INetFwAuthorizedApplication_AddRef( iface );
    return S_OK;
}

static HRESULT WINAPI fw_app_GetTypeInfoCount(
    INetFwAuthorizedApplication *iface,
    UINT *pctinfo )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    TRACE("%p %p\n", This, pctinfo);
    *pctinfo = 1;
    return S_OK;
}

static ITypeLib *typelib;
static ITypeInfo *typeinfo[last_tid];

static REFIID tid_id[] =
{
    &IID_INetFwAuthorizedApplication,
    &IID_INetFwAuthorizedApplications,
    &IID_INetFwMgr,
    &IID_INetFwPolicy,
    &IID_INetFwProfile
};

HRESULT get_typeinfo( enum type_id tid, ITypeInfo **ret )
{
    HRESULT hr;

    if (!typelib)
    {
        ITypeLib *lib;

        hr = LoadRegTypeLib( &LIBID_NetFwPublicTypeLib, 1, 0, LOCALE_SYSTEM_DEFAULT, &lib );
        if (FAILED(hr))
        {
            ERR("LoadRegTypeLib failed: %08x\n", hr);
            return hr;
        }
        if (InterlockedCompareExchangePointer( (void **)&typelib, lib, NULL ))
            ITypeLib_Release( lib );
    }
    if (!typeinfo[tid])
    {
        ITypeInfo *info;

        hr = ITypeLib_GetTypeInfoOfGuid( typelib, tid_id[tid], &info );
        if (FAILED(hr))
        {
            ERR("GetTypeInfoOfGuid(%s) failed: %08x\n", debugstr_guid(tid_id[tid]), hr);
            return hr;
        }
        if (InterlockedCompareExchangePointer( (void **)(typeinfo + tid), info, NULL ))
            ITypeInfo_Release( info );
    }
    *ret = typeinfo[tid];
    return S_OK;
}

static HRESULT WINAPI fw_app_GetTypeInfo(
    INetFwAuthorizedApplication *iface,
    UINT iTInfo,
    LCID lcid,
    ITypeInfo **ppTInfo )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    TRACE("%p %u %u %p\n", This, iTInfo, lcid, ppTInfo);
    return get_typeinfo( INetFwAuthorizedApplication_tid, ppTInfo );
}

static HRESULT WINAPI fw_app_GetIDsOfNames(
    INetFwAuthorizedApplication *iface,
    REFIID riid,
    LPOLESTR *rgszNames,
    UINT cNames,
    LCID lcid,
    DISPID *rgDispId )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );
    ITypeInfo *typeinfo;
    HRESULT hr;

    TRACE("%p %s %p %u %u %p\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);

    hr = get_typeinfo( INetFwAuthorizedApplication_tid, &typeinfo );
    if (SUCCEEDED(hr))
    {
        hr = ITypeInfo_GetIDsOfNames( typeinfo, rgszNames, cNames, rgDispId );
        ITypeInfo_Release( typeinfo );
    }
    return hr;
}

static HRESULT WINAPI fw_app_Invoke(
    INetFwAuthorizedApplication *iface,
    DISPID dispIdMember,
    REFIID riid,
    LCID lcid,
    WORD wFlags,
    DISPPARAMS *pDispParams,
    VARIANT *pVarResult,
    EXCEPINFO *pExcepInfo,
    UINT *puArgErr )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );
    ITypeInfo *typeinfo;
    HRESULT hr;

    TRACE("%p %d %s %d %d %p %p %p %p\n", This, dispIdMember, debugstr_guid(riid),
          lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);

    hr = get_typeinfo( INetFwAuthorizedApplication_tid, &typeinfo );
    if (SUCCEEDED(hr))
    {
        hr = ITypeInfo_Invoke( typeinfo, &This->INetFwAuthorizedApplication_iface, dispIdMember,
                               wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
        ITypeInfo_Release( typeinfo );
    }
    return hr;
}

static HRESULT WINAPI fw_app_get_Name(
    INetFwAuthorizedApplication *iface,
    BSTR *name )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %p\n", This, name);
    return E_NOTIMPL;
}

static HRESULT WINAPI fw_app_put_Name(
    INetFwAuthorizedApplication *iface,
    BSTR name )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %s\n", This, debugstr_w(name));
    return S_OK;
}

static HRESULT WINAPI fw_app_get_ProcessImageFileName(
    INetFwAuthorizedApplication *iface,
    BSTR *imageFileName )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %p\n", This, imageFileName);
    return E_NOTIMPL;
}

static HRESULT WINAPI fw_app_put_ProcessImageFileName(
    INetFwAuthorizedApplication *iface,
    BSTR imageFileName )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %s\n", This, debugstr_w(imageFileName));
    return S_OK;
}

static HRESULT WINAPI fw_app_get_IpVersion(
    INetFwAuthorizedApplication *iface,
    NET_FW_IP_VERSION *ipVersion )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %p\n", This, ipVersion);
    return E_NOTIMPL;
}

static HRESULT WINAPI fw_app_put_IpVersion(
    INetFwAuthorizedApplication *iface,
    NET_FW_IP_VERSION ipVersion )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %u\n", This, ipVersion);
    return E_NOTIMPL;
}

static HRESULT WINAPI fw_app_get_Scope(
    INetFwAuthorizedApplication *iface,
    NET_FW_SCOPE *scope )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %p\n", This, scope);
    return E_NOTIMPL;
}

static HRESULT WINAPI fw_app_put_Scope(
    INetFwAuthorizedApplication *iface,
    NET_FW_SCOPE scope )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %u\n", This, scope);
    return S_OK;
}

static HRESULT WINAPI fw_app_get_RemoteAddresses(
    INetFwAuthorizedApplication *iface,
    BSTR *remoteAddrs )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %p\n", This, remoteAddrs);
    return E_NOTIMPL;
}

static HRESULT WINAPI fw_app_put_RemoteAddresses(
    INetFwAuthorizedApplication *iface,
    BSTR remoteAddrs )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %s\n", This, debugstr_w(remoteAddrs));
    return E_NOTIMPL;
}

static HRESULT WINAPI fw_app_get_Enabled(
    INetFwAuthorizedApplication *iface,
    VARIANT_BOOL *enabled )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %p\n", This, enabled);

    *enabled = VARIANT_FALSE;
    return S_OK;
}

static HRESULT WINAPI fw_app_put_Enabled(
    INetFwAuthorizedApplication *iface,
    VARIANT_BOOL enabled )
{
    fw_app *This = impl_from_INetFwAuthorizedApplication( iface );

    FIXME("%p, %d\n", This, enabled);
    return S_OK;
}

static const struct INetFwAuthorizedApplicationVtbl fw_app_vtbl =
{
    fw_app_QueryInterface,
    fw_app_AddRef,
    fw_app_Release,
    fw_app_GetTypeInfoCount,
    fw_app_GetTypeInfo,
    fw_app_GetIDsOfNames,
    fw_app_Invoke,
    fw_app_get_Name,
    fw_app_put_Name,
    fw_app_get_ProcessImageFileName,
    fw_app_put_ProcessImageFileName,
    fw_app_get_IpVersion,
    fw_app_put_IpVersion,
    fw_app_get_Scope,
    fw_app_put_Scope,
    fw_app_get_RemoteAddresses,
    fw_app_put_RemoteAddresses,
    fw_app_get_Enabled,
    fw_app_put_Enabled
};

HRESULT NetFwAuthorizedApplication_create( IUnknown *pUnkOuter, LPVOID *ppObj )
{
    fw_app *fa;

    TRACE("(%p,%p)\n", pUnkOuter, ppObj);

    fa = HeapAlloc( GetProcessHeap(), 0, sizeof(*fa) );
    if (!fa) return E_OUTOFMEMORY;

    fa->INetFwAuthorizedApplication_iface.lpVtbl = &fw_app_vtbl;
    fa->refs = 1;

    *ppObj = &fa->INetFwAuthorizedApplication_iface;

    TRACE("returning iface %p\n", *ppObj);
    return S_OK;
}
typedef struct fw_apps
{
    INetFwAuthorizedApplications INetFwAuthorizedApplications_iface;
    LONG refs;
} fw_apps;

static inline fw_apps *impl_from_INetFwAuthorizedApplications( INetFwAuthorizedApplications *iface )
{
    return CONTAINING_RECORD(iface, fw_apps, INetFwAuthorizedApplications_iface);
}

static ULONG WINAPI fw_apps_AddRef(
    INetFwAuthorizedApplications *iface )
{
    fw_apps *fw_apps = impl_from_INetFwAuthorizedApplications( iface );
    return InterlockedIncrement( &fw_apps->refs );
}

static ULONG WINAPI fw_apps_Release(
    INetFwAuthorizedApplications *iface )
{
    fw_apps *fw_apps = impl_from_INetFwAuthorizedApplications( iface );
    LONG refs = InterlockedDecrement( &fw_apps->refs );
    if (!refs)
    {
        TRACE("destroying %p\n", fw_apps);
        HeapFree( GetProcessHeap(), 0, fw_apps );
    }
    return refs;
}

static HRESULT WINAPI fw_apps_QueryInterface(
    INetFwAuthorizedApplications *iface,
    REFIID riid,
    void **ppvObject )
{
    fw_apps *This = impl_from_INetFwAuthorizedApplications( iface );

    TRACE("%p %s %p\n", This, debugstr_guid( riid ), ppvObject );

    if ( IsEqualGUID( riid, &IID_INetFwAuthorizedApplications ) ||
         IsEqualGUID( riid, &IID_IDispatch ) ||
         IsEqualGUID( riid, &IID_IUnknown ) )
    {
        *ppvObject = iface;
    }
    else
    {
        FIXME("interface %s not implemented\n", debugstr_guid(riid));
        return E_NOINTERFACE;
    }
    INetFwAuthorizedApplications_AddRef( iface );
    return S_OK;
}

static HRESULT WINAPI fw_apps_GetTypeInfoCount(
    INetFwAuthorizedApplications *iface,
    UINT *pctinfo )
{
    fw_apps *This = impl_from_INetFwAuthorizedApplications( iface );

    FIXME("%p %p\n", This, pctinfo);
    return E_NOTIMPL;
}

static HRESULT WINAPI fw_apps_GetTypeInfo(
    INetFwAuthorizedApplications *iface,
    UINT iTInfo,
    LCID lcid,
    ITypeInfo **ppTInfo )
{
    fw_apps *This = impl_from_INetFwAuthorizedApplications( iface );

    TRACE("%p %u %u %p\n", This, iTInfo, lcid, ppTInfo);
    return get_typeinfo( INetFwAuthorizedApplications_tid, ppTInfo );
}

static HRESULT WINAPI fw_apps_GetIDsOfNames(
    INetFwAuthorizedApplications *iface,
    REFIID riid,
    LPOLESTR *rgszNames,
    UINT cNames,
    LCID lcid,
    DISPID *rgDispId )
{
    fw_apps *This = impl_from_INetFwAuthorizedApplications( iface );
    ITypeInfo *typeinfo;
    HRESULT hr;

    TRACE("%p %s %p %u %u %p\n", This, debugstr_guid(riid), rgszNames, cNames, lcid, rgDispId);

    hr = get_typeinfo( INetFwAuthorizedApplications_tid, &typeinfo );
    if (SUCCEEDED(hr))
    {
        hr = ITypeInfo_GetIDsOfNames( typeinfo, rgszNames, cNames, rgDispId );
        ITypeInfo_Release( typeinfo );
    }
    return hr;
}

static HRESULT WINAPI fw_apps_Invoke(
    INetFwAuthorizedApplications *iface,
    DISPID dispIdMember,
    REFIID riid,
    LCID lcid,
    WORD wFlags,
    DISPPARAMS *pDispParams,
    VARIANT *pVarResult,
    EXCEPINFO *pExcepInfo,
    UINT *puArgErr )
{
    fw_apps *This = impl_from_INetFwAuthorizedApplications( iface );
    ITypeInfo *typeinfo;
    HRESULT hr;

    TRACE("%p %d %s %d %d %p %p %p %p\n", This, dispIdMember, debugstr_guid(riid),
          lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);

    hr = get_typeinfo( INetFwAuthorizedApplications_tid, &typeinfo );
    if (SUCCEEDED(hr))
    {
        hr = ITypeInfo_Invoke( typeinfo, &This->INetFwAuthorizedApplications_iface, dispIdMember,
                               wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr );
        ITypeInfo_Release( typeinfo );
    }
    return hr;
}

static HRESULT WINAPI fw_apps_get_Count(
    INetFwAuthorizedApplications *iface,
    LONG *count )
{
    fw_apps *This = impl_from_INetFwAuthorizedApplications( iface );

    FIXME("%p, %p\n", This, count);
    return E_NOTIMPL;
}

static HRESULT WINAPI fw_apps_Add(
    INetFwAuthorizedApplications *iface,
    INetFwAuthorizedApplication *app )
{
    fw_apps *This = impl_from_INetFwAuthorizedApplications( iface );

    FIXME("%p, %p\n", This, app);
    return S_OK;
}

static HRESULT WINAPI fw_apps_Remove(
    INetFwAuthorizedApplications *iface,
    BSTR imageFileName )
{
    fw_apps *This = impl_from_INetFwAuthorizedApplications( iface );

    FIXME("%p, %s\n", This, debugstr_w(imageFileName));
    return S_OK;
}

static HRESULT WINAPI fw_apps_Item(
    INetFwAuthorizedApplications *iface,
    BSTR imageFileName,
    INetFwAuthorizedApplication **app )
{
    fw_apps *This = impl_from_INetFwAuthorizedApplications( iface );

    TRACE("%p, %s, %p\n", This, debugstr_w(imageFileName), app);
    return NetFwAuthorizedApplication_create( NULL, (void **)app );
}

static HRESULT WINAPI fw_apps_get__NewEnum(
    INetFwAuthorizedApplications *iface,
    IUnknown **newEnum )
{
    fw_apps *This = impl_from_INetFwAuthorizedApplications( iface );

    FIXME("%p, %p\n", This, newEnum);
    return E_NOTIMPL;
}

static const struct INetFwAuthorizedApplicationsVtbl fw_apps_vtbl =
{
    fw_apps_QueryInterface,
    fw_apps_AddRef,
    fw_apps_Release,
    fw_apps_GetTypeInfoCount,
    fw_apps_GetTypeInfo,
    fw_apps_GetIDsOfNames,
    fw_apps_Invoke,
    fw_apps_get_Count,
    fw_apps_Add,
    fw_apps_Remove,
    fw_apps_Item,
    fw_apps_get__NewEnum
};

HRESULT NetFwAuthorizedApplications_create( IUnknown *pUnkOuter, LPVOID *ppObj )
{
    fw_apps *fa;

    TRACE("(%p,%p)\n", pUnkOuter, ppObj);

    fa = HeapAlloc( GetProcessHeap(), 0, sizeof(*fa) );
    if (!fa) return E_OUTOFMEMORY;

    fa->INetFwAuthorizedApplications_iface.lpVtbl = &fw_apps_vtbl;
    fa->refs = 1;

    *ppObj = &fa->INetFwAuthorizedApplications_iface;

    TRACE("returning iface %p\n", *ppObj);
    return S_OK;
}
