/* 
 * 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 CHARS_IN_GUID 39

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

static inline RegistryPropertyBag *impl_from_IPropertyBag(IPropertyBag *iface)
{
    return CONTAINING_RECORD(iface, RegistryPropertyBag, IPropertyBag_iface);
}

static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_QueryInterface(IPropertyBag *iface,
    REFIID riid, void **ppv)
{
    RegistryPropertyBag *This = impl_from_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 = &This->IPropertyBag_iface;
    } else {
        *ppv = NULL;
        return E_NOINTERFACE;
    }

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

static ULONG WINAPI RegistryPropertyBag_IPropertyBag_AddRef(IPropertyBag *iface)
{
    RegistryPropertyBag *This = impl_from_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 = impl_from_IPropertyBag(iface);
    ULONG cRef;

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

    cRef = InterlockedDecrement(&This->m_cRef);

    if (cRef == 0) {
        TRACE("Destroying This=%p)\n", This);
        RegCloseKey(This->m_hInitPropertyBagKey);
        heap_free(This);
        SHDOCVW_UnlockModule();
    }

    return cRef;
}

static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_Read(IPropertyBag *iface,
    LPCOLESTR pwszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
{
    RegistryPropertyBag *This = impl_from_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->IPropertyBag_iface.lpVtbl = &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(&pRegistryPropertyBag->IPropertyBag_iface);
        hr = IPropertyBag_QueryInterface(&pRegistryPropertyBag->IPropertyBag_iface, riid, ppvObject);
        IPropertyBag_Release(&pRegistryPropertyBag->IPropertyBag_iface);
    }

    return hr;
}

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

static inline InstanceObjectFactory *impl_from_IClassFactory(IClassFactory *iface)
{
    return CONTAINING_RECORD(iface, InstanceObjectFactory, IClassFactory_iface);
}

static HRESULT WINAPI InstanceObjectFactory_IClassFactory_QueryInterface(IClassFactory *iface,
    REFIID riid, void **ppv)
{
    InstanceObjectFactory *This = impl_from_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 = &This->IClassFactory_iface;
    } else {
        *ppv = NULL;
        return E_NOINTERFACE;
    }

    IUnknown_AddRef((IUnknown*)*ppv);
    return S_OK;
}
    
static ULONG WINAPI InstanceObjectFactory_IClassFactory_AddRef(IClassFactory *iface)
{
    InstanceObjectFactory *This = impl_from_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 = impl_from_IClassFactory(iface);
    ULONG cRef;

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

    cRef = InterlockedDecrement(&This->m_cRef);

    if (cRef == 0) {
        IClassFactory_LockServer(iface, FALSE);
        IPropertyBag_Release(This->m_pPropertyBag);
        heap_free(This);
    }

    return cRef;
}

static HRESULT WINAPI InstanceObjectFactory_IClassFactory_CreateInstance(IClassFactory *iface,
    IUnknown *pUnkOuter, REFIID riid, LPVOID *ppvObj)
{
    InstanceObjectFactory *This = impl_from_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->IClassFactory_iface.lpVtbl = &InstanceObjectFactory_IClassFactoryVtbl;
        pInstanceObjectFactory->m_cRef = 0;
        pInstanceObjectFactory->m_clsidInstance = *rclsid;
        pInstanceObjectFactory->m_pPropertyBag = pPropertyBag;
        IPropertyBag_AddRef(pPropertyBag);

        IClassFactory_AddRef(&pInstanceObjectFactory->IClassFactory_iface);
        hr = IClassFactory_QueryInterface(&pInstanceObjectFactory->IClassFactory_iface,
                                          riid, ppvObject);
        IClassFactory_Release(&pInstanceObjectFactory->IClassFactory_iface);
    }

    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))
        return CLASS_E_CLASSNOTAVAILABLE;
    wszInstanceKey[5+CHARS_IN_GUID] = '\\'; /* Repair the null-termination. */
    if (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 (ERROR_SUCCESS != RegQueryValueExW(hInstanceKey, wszCLSID, NULL, &dwType, (LPBYTE)wszCLSIDInstance, &cbBytes) ||
        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;
}
