/* 
 * Shell Instance Objects - Add hot water and stir until dissolved.
 *
 * Copyright 2005 Michael Jung
 *
 * 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
 */

/* 'Shell Instance Objects' allow you to add a node to the shell namespace
 * (typically a shortcut to some location in the filesystem), just by setting
 * some registry entries. This feature was introduced with win2k. Please
 * search for 'Shell Instance Objects' on MSDN to get more information. */

#include <stdarg.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "objbase.h"
#include "oleauto.h"

#include "shdocvw.h"

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

WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);

#define ADJUST_THIS(c,m,p) ((c*)(((long)p)-(long)&(((c*)0)->lp##m##Vtbl)))
#define STATIC_CAST(i,p) ((i*)&p->lp##i##Vtbl)
#define CHARS_IN_GUID 39

/******************************************************************************
 * RegistryPropertyBag 
 *
 * Gives access to a registry key's values via the IPropertyBag interface.
 */
typedef struct _RegistryPropertyBag {
    const IPropertyBagVtbl *lpIPropertyBagVtbl;
    LONG                   m_cRef;
    HKEY                   m_hInitPropertyBagKey;
} RegistryPropertyBag;

static void RegistryPropertyBag_Destroy(RegistryPropertyBag *This) {
    TRACE("This=%p)\n", This);

    RegCloseKey(This->m_hInitPropertyBagKey);
    heap_free(This);
}

static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_QueryInterface(IPropertyBag *iface,
    REFIID riid, void **ppv)
{
    RegistryPropertyBag *This = ADJUST_THIS(RegistryPropertyBag, IPropertyBag, iface);

    TRACE("(iface=%p, riid=%s, ppv=%p)\n", iface, debugstr_guid(riid), ppv);

    if (!ppv)
        return E_INVALIDARG;

    if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPropertyBag, riid)) {
        *ppv = STATIC_CAST(IPropertyBag, This);
    } else {
        *ppv = NULL;
        return E_NOINTERFACE;
    }

    IUnknown_AddRef((IUnknown*)*ppv);
    return S_OK;
}

static ULONG WINAPI RegistryPropertyBag_IPropertyBag_AddRef(IPropertyBag *iface) {
    RegistryPropertyBag *This = ADJUST_THIS(RegistryPropertyBag, IPropertyBag, iface);
    ULONG cRef;

    TRACE("(iface=%p)\n", iface);

    cRef = InterlockedIncrement(&This->m_cRef);

    if (cRef == 1)
        SHDOCVW_LockModule();

    return cRef;
}

static ULONG WINAPI RegistryPropertyBag_IPropertyBag_Release(IPropertyBag *iface) {
    RegistryPropertyBag *This = ADJUST_THIS(RegistryPropertyBag, IPropertyBag, iface);
    ULONG cRef;

    TRACE("(iface=%p)\n", iface);

    cRef = InterlockedDecrement(&This->m_cRef);

    if (cRef == 0) { 
        RegistryPropertyBag_Destroy(This);
        SHDOCVW_UnlockModule();
    }

    return cRef;
}

static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_Read(IPropertyBag *iface,
    LPCOLESTR pwszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
{
    RegistryPropertyBag *This = ADJUST_THIS(RegistryPropertyBag, IPropertyBag, iface);
    WCHAR *pwszValue;
    DWORD dwType, cbData;
    LONG res;
    VARTYPE vtDst = V_VT(pVar);
    HRESULT hr = S_OK;

    TRACE("(iface=%p, pwszPropName=%s, pVar=%p, pErrorLog=%p)\n", iface, debugstr_w(pwszPropName), 
          pVar, pErrorLog);

    res = RegQueryValueExW(This->m_hInitPropertyBagKey, pwszPropName, NULL, &dwType, NULL, &cbData);
    if (res != ERROR_SUCCESS) 
        return E_INVALIDARG;

    pwszValue = heap_alloc(cbData);
    if (!pwszValue)
        return E_OUTOFMEMORY;
 
    res = RegQueryValueExW(This->m_hInitPropertyBagKey, pwszPropName, NULL, &dwType, 
                           (LPBYTE)pwszValue, &cbData);
    if (res != ERROR_SUCCESS) {
        heap_free(pwszValue);
        return E_INVALIDARG;
    }

    V_VT(pVar) = VT_BSTR;
    V_BSTR(pVar) = SysAllocString(pwszValue);
    heap_free(pwszValue);

    if (vtDst != VT_BSTR) {
        hr = VariantChangeTypeEx(pVar, pVar, LOCALE_SYSTEM_DEFAULT, 0, vtDst);
        if (FAILED(hr))
            SysFreeString(V_BSTR(pVar));
    }

    return hr;    
}

static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_Write(IPropertyBag *iface, 
    LPCOLESTR pwszPropName, VARIANT *pVar)
{
    FIXME("(iface=%p, pwszPropName=%s, pVar=%p) stub\n", iface, debugstr_w(pwszPropName), pVar);
    return E_NOTIMPL;
}

static const IPropertyBagVtbl RegistryPropertyBag_IPropertyBagVtbl = {
    RegistryPropertyBag_IPropertyBag_QueryInterface,
    RegistryPropertyBag_IPropertyBag_AddRef,
    RegistryPropertyBag_IPropertyBag_Release,
    RegistryPropertyBag_IPropertyBag_Read,
    RegistryPropertyBag_IPropertyBag_Write
};

static HRESULT RegistryPropertyBag_Constructor(HKEY hInitPropertyBagKey, REFIID riid, LPVOID *ppvObject) {
    HRESULT hr = E_FAIL;
    RegistryPropertyBag *pRegistryPropertyBag;

    TRACE("(hInitPropertyBagKey=%p, riid=%s, ppvObject=%p)\n", hInitPropertyBagKey, 
        debugstr_guid(riid), ppvObject);
    
    pRegistryPropertyBag = heap_alloc(sizeof(RegistryPropertyBag));
    if (pRegistryPropertyBag) {
        pRegistryPropertyBag->lpIPropertyBagVtbl = &RegistryPropertyBag_IPropertyBagVtbl;
        pRegistryPropertyBag->m_cRef = 0;
        pRegistryPropertyBag->m_hInitPropertyBagKey = hInitPropertyBagKey;

        /* The clasping AddRef/Release is for the case that QueryInterface fails, which will result
         * in a reference count of 0 in the Release call, which will result in object destruction.*/
        IPropertyBag_AddRef(STATIC_CAST(IPropertyBag, pRegistryPropertyBag));
        hr = IPropertyBag_QueryInterface(STATIC_CAST(IPropertyBag, pRegistryPropertyBag), riid, ppvObject);
        IPropertyBag_Release(STATIC_CAST(IPropertyBag, pRegistryPropertyBag));
    }

    return hr;
}

/******************************************************************************
 * InstanceObjectFactory
 * Builds Instance Objects and asks them to initialize themselves based on the
 * values of a PropertyBag.
 */
typedef struct _InstanceObjectFactory {
    const IClassFactoryVtbl *lpIClassFactoryVtbl;
    LONG                    m_cRef;
    CLSID                   m_clsidInstance; /* CLSID of the objects to create. */
    IPropertyBag            *m_pPropertyBag; /* PropertyBag to initialize those objects. */
} InstanceObjectFactory;

static void InstanceObjectFactory_Destroy(InstanceObjectFactory *This) {
    IPropertyBag_Release(This->m_pPropertyBag);
    heap_free(This);
}

static HRESULT WINAPI InstanceObjectFactory_IClassFactory_QueryInterface(IClassFactory *iface, 
    REFIID riid, LPVOID* ppv)
{
    InstanceObjectFactory *This = ADJUST_THIS(InstanceObjectFactory, IClassFactory, iface);

    TRACE("iface=%p, riid=%s, ppv=%p)\n", iface, debugstr_guid(riid), ppv);

    if (!ppv)
        return E_INVALIDARG;

    if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IClassFactory, riid)) {
        *ppv = STATIC_CAST(IClassFactory, This);
    } else {
        *ppv = NULL;
        return E_NOINTERFACE;
    }

    IUnknown_AddRef((IUnknown*)*ppv);
    return S_OK;
}
    
static ULONG WINAPI InstanceObjectFactory_IClassFactory_AddRef(IClassFactory *iface)
{
    InstanceObjectFactory *This = ADJUST_THIS(InstanceObjectFactory, IClassFactory, iface);
    ULONG cRef;

    TRACE("(iface=%p)\n", iface);

    cRef = InterlockedIncrement(&This->m_cRef);

    if (cRef == 1)
        IClassFactory_LockServer(iface, TRUE);

    return cRef;
}

static ULONG WINAPI InstanceObjectFactory_IClassFactory_Release(IClassFactory *iface)
{
    InstanceObjectFactory *This = ADJUST_THIS(InstanceObjectFactory, IClassFactory, iface);
    ULONG cRef;

    TRACE("(iface=%p)\n", iface);

    cRef = InterlockedDecrement(&This->m_cRef);

    if (cRef == 0) { 
        IClassFactory_LockServer(iface, FALSE);
        InstanceObjectFactory_Destroy(This);
    }

    return cRef;
}

static HRESULT WINAPI InstanceObjectFactory_IClassFactory_CreateInstance(IClassFactory *iface,
    IUnknown *pUnkOuter, REFIID riid, LPVOID *ppvObj)
{
    InstanceObjectFactory *This = ADJUST_THIS(InstanceObjectFactory, IClassFactory, iface);
    IPersistPropertyBag *pPersistPropertyBag;
    HRESULT hr;
        
    TRACE("(pUnkOuter=%p, riid=%s, ppvObj=%p)\n", pUnkOuter, debugstr_guid(riid), ppvObj);
    
    hr = CoCreateInstance(&This->m_clsidInstance, NULL, CLSCTX_INPROC_SERVER,
                          &IID_IPersistPropertyBag, (LPVOID*)&pPersistPropertyBag);
    if (FAILED(hr)) {
        TRACE("Failed to create instance of %s. hr = %08x\n",
              debugstr_guid(&This->m_clsidInstance), hr);
        return hr;
    }

    hr = IPersistPropertyBag_Load(pPersistPropertyBag, This->m_pPropertyBag, NULL);
    if (FAILED(hr)) {
        TRACE("Failed to initialize object from ProperyBag: hr = %08x\n", hr);
        IPersistPropertyBag_Release(pPersistPropertyBag);
        return hr;
    }

    hr = IPersistPropertyBag_QueryInterface(pPersistPropertyBag, riid, ppvObj);
    IPersistPropertyBag_Release(pPersistPropertyBag);

    return hr;
}

static HRESULT WINAPI InstanceObjectFactory_IClassFactory_LockServer(IClassFactory *iface, 
    BOOL fLock)
{
    TRACE("(iface=%p, fLock=%d) stub\n", iface, fLock);

    if (fLock)
        SHDOCVW_LockModule();
    else
        SHDOCVW_UnlockModule();

    return S_OK;        
}

static const IClassFactoryVtbl InstanceObjectFactory_IClassFactoryVtbl = {
    InstanceObjectFactory_IClassFactory_QueryInterface,
    InstanceObjectFactory_IClassFactory_AddRef,
    InstanceObjectFactory_IClassFactory_Release,
    InstanceObjectFactory_IClassFactory_CreateInstance,
    InstanceObjectFactory_IClassFactory_LockServer
};

static HRESULT InstanceObjectFactory_Constructor(REFCLSID rclsid, IPropertyBag *pPropertyBag,
                                                 REFIID riid, LPVOID *ppvObject)
{
    InstanceObjectFactory *pInstanceObjectFactory;
    HRESULT hr = E_FAIL;

    TRACE("(RegistryPropertyBag=%p, riid=%s, ppvObject=%p)\n", pPropertyBag,
        debugstr_guid(riid), ppvObject);

    pInstanceObjectFactory = heap_alloc(sizeof(InstanceObjectFactory));
    if (pInstanceObjectFactory) {
        pInstanceObjectFactory->lpIClassFactoryVtbl = &InstanceObjectFactory_IClassFactoryVtbl;
        pInstanceObjectFactory->m_cRef = 0;
        pInstanceObjectFactory->m_clsidInstance = *rclsid;
        pInstanceObjectFactory->m_pPropertyBag = pPropertyBag;
        IPropertyBag_AddRef(pPropertyBag);

        IClassFactory_AddRef(STATIC_CAST(IClassFactory, pInstanceObjectFactory));
        hr = IClassFactory_QueryInterface(STATIC_CAST(IClassFactory, pInstanceObjectFactory),
                                          riid, ppvObject);
        IClassFactory_Release(STATIC_CAST(IClassFactory, pInstanceObjectFactory));
    }

    return hr;
}

/******************************************************************************
 * SHDOCVW_GetShellInstanceObjectClassObject [Internal]
 *
 *  Figure if there is a 'Shell Instance Object' conformant registry entry for
 *  the given CLSID and if so create and return a corresponding ClassObject.
 *
 * PARAMS
 *  rclsid      [I] CLSID of the 'Shell Instance Object'.
 *  riid        [I] Desired interface. Only IClassFactory supported.
 *  ppvClassObj [O] The corresponding ClassObject.
 *
 * RETURNS
 *  Success: S_OK,
 *  Failure: CLASS_E_CLASSNOTAVAILABLE
 */
HRESULT SHDOCVW_GetShellInstanceObjectClassObject(REFCLSID rclsid, REFIID riid, 
    LPVOID *ppvClassObj)
{
    WCHAR wszInstanceKey[] = { 'C','L','S','I','D','\\','{','0','0','0','0','0','0','0','0','-',
        '0','0','0','0','-','0','0','0','0','-','0','0','0','0','-','0','0','0','0','0','0','0','0',
        '0','0','0','0','}','\\','I','n','s','t','a','n','c','e', 0 };
    const WCHAR wszCLSID[] = { 'C','L','S','I','D',0 };
    const WCHAR wszInitPropertyBag[] = 
        { 'I','n','i','t','P','r','o','p','e','r','t','y','B','a','g',0 };
    WCHAR wszCLSIDInstance[CHARS_IN_GUID];
    CLSID clsidInstance;
    HKEY hInstanceKey, hInitPropertyBagKey;
    DWORD dwType, cbBytes = sizeof(wszCLSIDInstance);
    IPropertyBag *pInitPropertyBag;
    HRESULT hr;
    LONG res;
        
    TRACE("(rclsid=%s, riid=%s, ppvClassObject=%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), 
          ppvClassObj);

    /* Figure if there is an 'Instance' subkey for the given CLSID and acquire a handle. */
    if (!StringFromGUID2(rclsid, wszInstanceKey + 6, CHARS_IN_GUID) ||
        !(wszInstanceKey[5+CHARS_IN_GUID]='\\') || /* Repair the null-termination. */
        ERROR_SUCCESS != RegOpenKeyExW(HKEY_CLASSES_ROOT, wszInstanceKey, 0, KEY_READ, &hInstanceKey))
    {
        /* If there is no 'Instance' subkey, then it's not a Shell Instance Object. */
        return CLASS_E_CLASSNOTAVAILABLE;
    }

    if (RegQueryValueExW(hInstanceKey, wszCLSID, NULL, &dwType, (LPBYTE)wszCLSIDInstance, &cbBytes)
        != ERROR_SUCCESS || FAILED(CLSIDFromString(wszCLSIDInstance, &clsidInstance)))
    {
        /* 'Instance' should have a 'CLSID' value with a well-formed clsid-string. */
        FIXME("Failed to infer instance CLSID! %s\n", debugstr_w(wszCLSIDInstance));
        RegCloseKey(hInstanceKey);
        return CLASS_E_CLASSNOTAVAILABLE;
    }

    /* Try to open the 'InitPropertyBag' subkey. */
    res = RegOpenKeyExW(hInstanceKey, wszInitPropertyBag, 0, KEY_READ, &hInitPropertyBagKey);
    RegCloseKey(hInstanceKey);
    if (res != ERROR_SUCCESS) {
        /* Besides 'InitPropertyBag's, shell instance objects might be initialized by streams.
         * So this case might not be an error. */
        TRACE("No InitPropertyBag key found!\n");
        return CLASS_E_CLASSNOTAVAILABLE;
    }

    /* If the construction succeeds, the new RegistryPropertyBag is responsible for closing 
     * hInitProperyBagKey. */
    hr = RegistryPropertyBag_Constructor(hInitPropertyBagKey, &IID_IPropertyBag, 
                                         (LPVOID*)&pInitPropertyBag);
    if (FAILED(hr)) {
        RegCloseKey(hInitPropertyBagKey);
        return hr;
    }

    /* Construct an Instance Object Factory, which creates objects of class 'clsidInstance'
     * and asks them to initialize themselves with the help of the 'pInitiPropertyBag' */
    hr = InstanceObjectFactory_Constructor(&clsidInstance, pInitPropertyBag, riid, ppvClassObj);
    IPropertyBag_Release(pInitPropertyBag); /* The factory will hold a reference the bag. */
        
    return hr;
}
