/* 
 * 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);
    shdocvw_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 = shdocvw_alloc(cbData);
    if (!pwszValue)
        return E_OUTOFMEMORY;
 
    res = RegQueryValueExW(This->m_hInitPropertyBagKey, pwszPropName, NULL, &dwType, 
                           (LPBYTE)pwszValue, &cbData);
    if (res != ERROR_SUCCESS) {
        shdocvw_free(pwszValue);
        return E_INVALIDARG;
    }

    V_VT(pVar) = VT_BSTR;
    V_BSTR(pVar) = SysAllocString(pwszValue);
    shdocvw_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 = shdocvw_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);
    shdocvw_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 = shdocvw_alloc(sizeof(InstanceObjectFactory));
    if (pInstanceObjectFactory) {
        pInstanceObjectFactory->lpIClassFactoryVtbl = &InstanceObjectFactory_IClassFactoryVtbl;
        pInstanceObjectFactory->m_cRef = 0;
        memcpy(&pInstanceObjectFactory->m_clsidInstance, rclsid, sizeof(CLSID));
        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;
}
