/*
 * WiaDevMgr functions
 *
 * Copyright 2009 Damjan Jovanovic
 *
 * 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 "objbase.h"
#include "wia_lh.h"

#include "wiaservc_private.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(wia);

static inline wiadevmgr *impl_from_WiaDevMgr(IWiaDevMgr *iface)
{
    return (wiadevmgr *)((char*)iface - FIELD_OFFSET(wiadevmgr, lpVtbl));
}

static HRESULT WINAPI wiadevmgr_QueryInterface(IWiaDevMgr *iface, REFIID riid, void **ppvObject)
{
    wiadevmgr *This = impl_from_WiaDevMgr(iface);

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

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

static ULONG WINAPI wiadevmgr_AddRef(IWiaDevMgr *iface)
{
    wiadevmgr *This = impl_from_WiaDevMgr(iface);
    return InterlockedIncrement(&This->ref);
}

static ULONG WINAPI wiadevmgr_Release(IWiaDevMgr *iface)
{
    ULONG ref;
    wiadevmgr *This = impl_from_WiaDevMgr(iface);

    ref = InterlockedDecrement(&This->ref);
    if (ref == 0)
        HeapFree(GetProcessHeap(), 0, This);
    return ref;
}

static HRESULT WINAPI wiadevmgr_EnumDeviceInfo(IWiaDevMgr *iface, LONG lFlag, IEnumWIA_DEV_INFO **ppIEnum)
{
    wiadevmgr *This = impl_from_WiaDevMgr(iface);
    FIXME("(%p, %d, %p): stub\n", This, lFlag, ppIEnum);
    return E_NOTIMPL;
}

static HRESULT WINAPI wiadevmgr_CreateDevice(IWiaDevMgr *iface, BSTR bstrDeviceID, IWiaItem **ppWiaItemRoot)
{
    wiadevmgr *This = impl_from_WiaDevMgr(iface);
    FIXME("(%p, %s, %p): stub\n", This, debugstr_w(bstrDeviceID), ppWiaItemRoot);
    return E_NOTIMPL;
}

static HRESULT WINAPI wiadevmgr_SelectDeviceDlg(IWiaDevMgr *iface, HWND hwndParent, LONG lDeviceType,
                                                LONG lFlags, BSTR *pbstrDeviceID, IWiaItem **ppItemRoot)
{
    wiadevmgr *This = impl_from_WiaDevMgr(iface);
    FIXME("(%p, %p, %d, 0x%x, %p, %p): stub\n", This, hwndParent, lDeviceType, lFlags, pbstrDeviceID, ppItemRoot);
    return E_NOTIMPL;
}

static HRESULT WINAPI wiadevmgr_SelectDeviceDlgID(IWiaDevMgr *iface, HWND hwndParent, LONG lDeviceType,
                                                  LONG lFlags, BSTR *pbstrDeviceID)
{
    wiadevmgr *This = impl_from_WiaDevMgr(iface);
    FIXME("(%p, %p, %d, 0x%x, %p): stub\n", This, hwndParent, lDeviceType, lFlags, pbstrDeviceID);
    return E_NOTIMPL;
}

static HRESULT WINAPI wiadevmgr_GetImageDlg(IWiaDevMgr *iface, HWND hwndParent, LONG lDeviceType,
                                            LONG lFlags, LONG lIntent, IWiaItem *pItemRoot,
                                            BSTR bstrFilename, GUID *pguidFormat)
{
    wiadevmgr *This = impl_from_WiaDevMgr(iface);
    FIXME("(%p, %p, %d, 0x%x, %d, %p, %s, %s): stub\n", This, hwndParent, lDeviceType, lFlags,
        lIntent, pItemRoot, debugstr_w(bstrFilename), debugstr_guid(pguidFormat));
    return E_NOTIMPL;
}

static HRESULT WINAPI wiadevmgr_RegisterEventCallbackProgram(IWiaDevMgr *iface, LONG lFlags, BSTR bstrDeviceID,
                                                             const GUID *pEventGUID, BSTR bstrCommandline,
                                                             BSTR bstrName, BSTR bstrDescription, BSTR bstrIcon)
{
    wiadevmgr *This = impl_from_WiaDevMgr(iface);
    FIXME("(%p, 0x%x, %s, %s, %s, %s, %s, %s): stub\n", This, lFlags, debugstr_w(bstrDeviceID),
        debugstr_guid(pEventGUID), debugstr_w(bstrCommandline), debugstr_w(bstrName),
        debugstr_w(bstrDescription), debugstr_w(bstrIcon));
    return E_NOTIMPL;
}

static HRESULT WINAPI wiadevmgr_RegisterEventCallbackInterface(IWiaDevMgr *iface, LONG lFlags, BSTR bstrDeviceID,
                                                               const GUID *pEventGUID, IWiaEventCallback *pIWiaEventCallback,
                                                               IUnknown **pEventObject)
{
    wiadevmgr *This = impl_from_WiaDevMgr(iface);
    FIXME("(%p, 0x%x, %s, %s, %p, %p): stub\n", This, lFlags, debugstr_w(bstrDeviceID),
        debugstr_guid(pEventGUID), pIWiaEventCallback, pEventObject);
    return E_NOTIMPL;
}

static HRESULT WINAPI wiadevmgr_RegisterEventCallbackCLSID(IWiaDevMgr *iface, LONG lFlags, BSTR bstrDeviceID,
                                                           const GUID *pEventGUID, const GUID *pClsID, BSTR bstrName,
                                                           BSTR bstrDescription, BSTR bstrIcon)
{
    wiadevmgr *This = impl_from_WiaDevMgr(iface);
    FIXME("(%p, 0x%x, %s, %s, %s, %s, %s, %s): stub\n", This, lFlags, debugstr_w(bstrDeviceID),
        debugstr_guid(pEventGUID), debugstr_guid(pClsID), debugstr_w(bstrName),
        debugstr_w(bstrDescription), debugstr_w(bstrIcon));
    return E_NOTIMPL;
}

static HRESULT WINAPI wiadevmgr_AddDeviceDlg(IWiaDevMgr *iface, HWND hwndParent, LONG lFlags)
{
    wiadevmgr *This = impl_from_WiaDevMgr(iface);
    FIXME("(%p, %p, 0x%x): stub\n", This, hwndParent, lFlags);
    return E_NOTIMPL;
}

static const IWiaDevMgrVtbl WIASERVC_IWiaDevMgr_Vtbl =
{
    wiadevmgr_QueryInterface,
    wiadevmgr_AddRef,
    wiadevmgr_Release,
    wiadevmgr_EnumDeviceInfo,
    wiadevmgr_CreateDevice,
    wiadevmgr_SelectDeviceDlg,
    wiadevmgr_SelectDeviceDlgID,
    wiadevmgr_GetImageDlg,
    wiadevmgr_RegisterEventCallbackProgram,
    wiadevmgr_RegisterEventCallbackInterface,
    wiadevmgr_RegisterEventCallbackCLSID,
    wiadevmgr_AddDeviceDlg
};

HRESULT wiadevmgr_Constructor(IUnknown *pUnkOuter, LPVOID *ppObj)
{
    wiadevmgr *This;
    TRACE("(%p,%p)\n", pUnkOuter, ppObj);
    This = HeapAlloc(GetProcessHeap(), 0, sizeof(wiadevmgr));
    if (This)
    {
        This->lpVtbl = &WIASERVC_IWiaDevMgr_Vtbl;
        This->ref = 1;
        *ppObj = This;
        return S_OK;
    }
    *ppObj = NULL;
    return E_OUTOFMEMORY;
}
