/*
 * File System Bind Data object to use as parameter for the bind context to
 * IShellFolder_ParseDisplayName
 *
 * Copyright 2003 Rolf Kalbermatter
 *
 * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */
#include "config.h"
#include "wine/port.h"

#include <stdarg.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "winuser.h"
#include "shlobj.h"
#include "shell32_main.h"

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(pidl);

/***********************************************************************
 * IFileSystemBindData implementation
 */
typedef struct
{
    IFileSystemBindDataVtbl *lpVtbl;
    DWORD              ref;
    WIN32_FIND_DATAW findFile;
} IFileSystemBindDataImpl;

static HRESULT WINAPI IFileSystemBindData_fnQueryInterface(IFileSystemBindData *, REFIID, LPVOID*);
static ULONG WINAPI IFileSystemBindData_fnAddRef(IFileSystemBindData *);
static ULONG WINAPI IFileSystemBindData_fnRelease(IFileSystemBindData *);
static HRESULT WINAPI IFileSystemBindData_fnGetFindData(IFileSystemBindData *, WIN32_FIND_DATAW *);
static HRESULT WINAPI IFileSystemBindData_fnSetFindData(IFileSystemBindData *, const WIN32_FIND_DATAW *);

static struct IFileSystemBindDataVtbl sbvt =
{
    IFileSystemBindData_fnQueryInterface,
    IFileSystemBindData_fnAddRef,
    IFileSystemBindData_fnRelease,
    IFileSystemBindData_fnSetFindData,
    IFileSystemBindData_fnGetFindData,
};

static const WCHAR wFileSystemBindData[] = {
    'F','i','l','e',' ','S','y','s','t','e','m',' ','B','i','n','d','D','a','t','a',0};

HRESULT WINAPI IFileSystemBindData_Constructor(const WIN32_FIND_DATAW *pfd, LPBC *ppV)
{
    IFileSystemBindDataImpl *sb;
    HRESULT ret = E_OUTOFMEMORY;

    TRACE("%p, %p\n", pfd, ppV);

    if (!ppV)
       return E_INVALIDARG;

    *ppV = NULL;

    sb = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IFileSystemBindDataImpl));
    if (!sb)
        return ret;

    sb->lpVtbl = &sbvt;
    sb->ref = 1;
    IFileSystemBindData_fnSetFindData((IFileSystemBindData*)sb, pfd);

    ret = CreateBindCtx(0, ppV);
    if (SUCCEEDED(ret))
    {
        BIND_OPTS bindOpts;

        bindOpts.cbStruct = sizeof(BIND_OPTS);
        bindOpts.grfFlags = 0;
        bindOpts.grfMode = STGM_CREATE;
        bindOpts.dwTickCountDeadline = 0;
        IBindCtx_SetBindOptions(*ppV, &bindOpts);
        IBindCtx_RegisterObjectParam(*ppV, (LPOLESTR)wFileSystemBindData, (LPUNKNOWN)sb);

        IFileSystemBindData_Release((IFileSystemBindData*)sb);
    }
    else
        HeapFree(GetProcessHeap(), 0, sb);
    return ret;
}

HRESULT WINAPI FileSystemBindData_GetFindData(LPBC pbc, WIN32_FIND_DATAW *pfd)
{
    LPUNKNOWN pUnk;
    IFileSystemBindData *pfsbd = NULL;
    HRESULT ret;

    TRACE("%p, %p\n", pbc, pfd);

    if (!pfd)
        return E_INVALIDARG;

    ret = IBindCtx_GetObjectParam(pbc, (LPOLESTR)wFileSystemBindData, &pUnk);
    if (SUCCEEDED(ret))
    {
        ret = IUnknown_QueryInterface(pUnk, &IID_IFileSystemBindData, (LPVOID *)&pfsbd);
        if (SUCCEEDED(ret))
        {
            ret = IFileSystemBindData_GetFindData(pfsbd, pfd);
            IFileSystemBindData_Release(pfsbd);
        }
        IUnknown_Release(pUnk);
    }
    return ret;
}

HRESULT WINAPI FileSystemBindData_SetFindData(LPBC pbc, const WIN32_FIND_DATAW *pfd)
{
    LPUNKNOWN pUnk;
    IFileSystemBindData *pfsbd = NULL;
    HRESULT ret;
    
    TRACE("%p, %p\n", pbc, pfd);

    ret = IBindCtx_GetObjectParam(pbc, (LPOLESTR)wFileSystemBindData, &pUnk);
    if (SUCCEEDED(ret))
    {
        ret = IUnknown_QueryInterface(pUnk, &IID_IFileSystemBindData, (LPVOID *)&pfsbd);
        if (SUCCEEDED(ret))
        {
            ret = IFileSystemBindData_SetFindData(pfsbd, pfd);
            IFileSystemBindData_Release(pfsbd);
        }
        IUnknown_Release(pUnk);
    }
    return ret;
}

static HRESULT WINAPI IFileSystemBindData_fnQueryInterface(
                IFileSystemBindData *iface, REFIID riid, LPVOID *ppV)
{
    IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface;
    TRACE("(%p)->(\n\tIID:\t%s, %p)\n", This, debugstr_guid(riid), ppV);

    *ppV = NULL;

    if (IsEqualIID(riid, &IID_IUnknown))
        *ppV = This;
    else if (IsEqualIID(riid, &IID_IFileSystemBindData))
        *ppV = (IFileSystemBindData*)This;

    if (*ppV)
    {
        IUnknown_AddRef((IUnknown*)(*ppV));
        TRACE("-- Interface: (%p)->(%p)\n", ppV, *ppV);
        return S_OK;
    }
    TRACE("-- Interface: E_NOINTERFACE\n");
    return E_NOINTERFACE;
}

static ULONG WINAPI IFileSystemBindData_fnAddRef(IFileSystemBindData *iface)
{
    IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface;
    ULONG refCount = InterlockedIncrement(&This->ref);

    TRACE("(%p)->(count=%li)\n", This, refCount - 1);

    return refCount;
}

static ULONG WINAPI IFileSystemBindData_fnRelease(IFileSystemBindData *iface)
{
    IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface;
    ULONG refCount = InterlockedDecrement(&This->ref);
    
    TRACE("(%p)->(count=%li)\n", This, refCount + 1);

    if (!refCount)
    {
        TRACE(" destroying ISFBindPidl(%p)\n",This);
        HeapFree(GetProcessHeap(), 0, This);
    }
    return refCount;
}

static HRESULT WINAPI IFileSystemBindData_fnGetFindData(
               IFileSystemBindData *iface, WIN32_FIND_DATAW *pfd)
{
    IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface;
    TRACE("(%p), %p\n", This, pfd);

    if (!pfd)
        return E_INVALIDARG;

    memcpy(pfd, &This->findFile, sizeof(WIN32_FIND_DATAW));
    return NOERROR;
}

static HRESULT WINAPI IFileSystemBindData_fnSetFindData(
               IFileSystemBindData *iface, const WIN32_FIND_DATAW *pfd)
{
    IFileSystemBindDataImpl *This = (IFileSystemBindDataImpl *)iface;
    TRACE("(%p), %p\n", This, pfd);

    if (pfd)
        memcpy(&This->findFile, pfd, sizeof(WIN32_FIND_DATAW));
    else
        memset(&This->findFile, 0, sizeof(WIN32_FIND_DATAW));
    return NOERROR;
}
