wine-wine/dlls/ole32/antimoniker.c

673 lines
20 KiB
C

/*
* AntiMonikers implementation
*
* Copyright 1999 Noomen Hamza
*
* 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
*/
#include <assert.h>
#include <stdarg.h>
#include <string.h>
#define COBJMACROS
#define NONAMELESSUNION
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "objbase.h"
#include "wine/debug.h"
#include "wine/heap.h"
#include "moniker.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
/* AntiMoniker data structure */
typedef struct AntiMonikerImpl{
IMoniker IMoniker_iface;
IROTData IROTData_iface;
LONG refcount;
IUnknown *pMarshal; /* custom marshaler */
DWORD count;
} AntiMonikerImpl;
static inline AntiMonikerImpl *impl_from_IMoniker(IMoniker *iface)
{
return CONTAINING_RECORD(iface, AntiMonikerImpl, IMoniker_iface);
}
static inline AntiMonikerImpl *impl_from_IROTData(IROTData *iface)
{
return CONTAINING_RECORD(iface, AntiMonikerImpl, IROTData_iface);
}
static AntiMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface);
BOOL is_anti_moniker(IMoniker *iface, DWORD *order)
{
AntiMonikerImpl *moniker = unsafe_impl_from_IMoniker(iface);
if (!moniker)
{
*order = 0;
return FALSE;
}
*order = moniker->count;
return TRUE;
}
/*******************************************************************************
* AntiMoniker_QueryInterface
*******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
{
AntiMonikerImpl *This = impl_from_IMoniker(iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
if ( ppvObject==0 )
return E_INVALIDARG;
*ppvObject = 0;
if (IsEqualIID(&IID_IUnknown, riid) ||
IsEqualIID(&IID_IPersist, riid) ||
IsEqualIID(&IID_IPersistStream, riid) ||
IsEqualIID(&IID_IMoniker, riid) ||
IsEqualGUID(&CLSID_AntiMoniker, riid))
{
*ppvObject = iface;
}
else if (IsEqualIID(&IID_IROTData, riid))
*ppvObject = &This->IROTData_iface;
else if (IsEqualIID(&IID_IMarshal, riid))
{
HRESULT hr = S_OK;
if (!This->pMarshal)
hr = MonikerMarshal_Create(iface, &This->pMarshal);
if (hr != S_OK)
return hr;
return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
}
if ((*ppvObject)==0)
return E_NOINTERFACE;
IMoniker_AddRef(iface);
return S_OK;
}
/******************************************************************************
* AntiMoniker_AddRef
******************************************************************************/
static ULONG WINAPI AntiMonikerImpl_AddRef(IMoniker *iface)
{
AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
ULONG refcount = InterlockedIncrement(&moniker->refcount);
TRACE("%p, refcount %u.\n", iface, refcount);
return refcount;
}
/******************************************************************************
* AntiMoniker_Release
******************************************************************************/
static ULONG WINAPI AntiMonikerImpl_Release(IMoniker *iface)
{
AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
ULONG refcount = InterlockedDecrement(&moniker->refcount);
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount)
{
if (moniker->pMarshal) IUnknown_Release(moniker->pMarshal);
heap_free(moniker);
}
return refcount;
}
/******************************************************************************
* AntiMoniker_GetClassID
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
{
TRACE("(%p,%p)\n",iface,pClassID);
if (pClassID==NULL)
return E_POINTER;
*pClassID = CLSID_AntiMoniker;
return S_OK;
}
/******************************************************************************
* AntiMoniker_IsDirty
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_IsDirty(IMoniker* iface)
{
/* Note that the OLE-provided implementations of the IPersistStream::IsDirty
method in the OLE-provided moniker interfaces always return S_FALSE because
their internal state never changes. */
TRACE("(%p)\n",iface);
return S_FALSE;
}
/******************************************************************************
* AntiMoniker_Load
******************************************************************************/
static HRESULT WINAPI AntiMonikerImpl_Load(IMoniker *iface, IStream *stream)
{
AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
DWORD count = 0;
HRESULT hr;
TRACE("%p, %p.\n", iface, stream);
if (FAILED(hr = IStream_Read(stream, &count, sizeof(count), NULL)))
return hr;
if (count > 0xfffff)
return E_INVALIDARG;
moniker->count = count;
return S_OK;
}
/******************************************************************************
* AntiMoniker_Save
******************************************************************************/
static HRESULT WINAPI AntiMonikerImpl_Save(IMoniker *iface, IStream *stream, BOOL clear_dirty)
{
AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
TRACE("%p, %p, %d.\n", iface, stream, clear_dirty);
return IStream_Write(stream, &moniker->count, sizeof(moniker->count), NULL);
}
/******************************************************************************
* AntiMoniker_GetSizeMax
*
* PARAMS
* pcbSize [out] Pointer to size of stream needed to save object
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
{
TRACE("(%p,%p)\n",iface,pcbSize);
if (!pcbSize)
return E_POINTER;
/* for more details see AntiMonikerImpl_Save comments */
/*
* Normally the sizemax must be sizeof DWORD, but
* I tested this function it usually return 16 bytes
* more than the number of bytes used by AntiMoniker::Save function
*/
pcbSize->u.LowPart = sizeof(DWORD)+16;
pcbSize->u.HighPart=0;
return S_OK;
}
/******************************************************************************
* AntiMoniker_BindToObject
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
REFIID riid, VOID** ppvResult)
{
TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
return E_NOTIMPL;
}
/******************************************************************************
* AntiMoniker_BindToStorage
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
REFIID riid, VOID** ppvResult)
{
TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
return E_NOTIMPL;
}
/******************************************************************************
* AntiMoniker_Reduce
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
{
TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
if (ppmkReduced==NULL)
return E_POINTER;
AntiMonikerImpl_AddRef(iface);
*ppmkReduced=iface;
return MK_S_REDUCED_TO_SELF;
}
/******************************************************************************
* AntiMoniker_ComposeWith
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
{
TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
if ((ppmkComposite==NULL)||(pmkRight==NULL))
return E_POINTER;
*ppmkComposite=0;
if (fOnlyIfNotGeneric)
return MK_E_NEEDGENERIC;
else
return CreateGenericComposite(iface,pmkRight,ppmkComposite);
}
/******************************************************************************
* AntiMoniker_Enum
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
{
TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
if (ppenumMoniker == NULL)
return E_POINTER;
*ppenumMoniker = NULL;
return S_OK;
}
/******************************************************************************
* AntiMoniker_IsEqual
******************************************************************************/
static HRESULT WINAPI AntiMonikerImpl_IsEqual(IMoniker *iface, IMoniker *other)
{
AntiMonikerImpl *moniker = impl_from_IMoniker(iface), *other_moniker;
TRACE("%p, %p.\n", iface, other);
if (!other)
return E_INVALIDARG;
other_moniker = unsafe_impl_from_IMoniker(other);
if (!other_moniker)
return S_FALSE;
return moniker->count == other_moniker->count ? S_OK : S_FALSE;
}
/******************************************************************************
* AntiMoniker_Hash
******************************************************************************/
static HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker *iface, DWORD *hash)
{
AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
TRACE("%p, %p.\n", iface, hash);
if (!hash)
return E_POINTER;
*hash = 0x80000000 | moniker->count;
return S_OK;
}
/******************************************************************************
* AntiMoniker_IsRunning
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
IMoniker* pmkNewlyRunning)
{
IRunningObjectTable* rot;
HRESULT res;
TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
if (pbc==NULL)
return E_INVALIDARG;
res=IBindCtx_GetRunningObjectTable(pbc,&rot);
if (FAILED(res))
return res;
res = IRunningObjectTable_IsRunning(rot,iface);
IRunningObjectTable_Release(rot);
return res;
}
/******************************************************************************
* AntiMoniker_GetTimeOfLastChange
******************************************************************************/
static HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
IBindCtx* pbc,
IMoniker* pmkToLeft,
FILETIME* pAntiTime)
{
TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime);
return E_NOTIMPL;
}
/******************************************************************************
* AntiMoniker_Inverse
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
{
TRACE("(%p,%p)\n",iface,ppmk);
if (ppmk==NULL)
return E_POINTER;
*ppmk=0;
return MK_E_NOINVERSE;
}
/******************************************************************************
* AntiMoniker_CommonPrefixWith
******************************************************************************/
static HRESULT WINAPI AntiMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *other, IMoniker **prefix)
{
AntiMonikerImpl *moniker = impl_from_IMoniker(iface), *other_moniker;
HRESULT hr;
TRACE("%p, %p, %p.\n", iface, other, prefix);
other_moniker = unsafe_impl_from_IMoniker(other);
if (other_moniker)
{
if (moniker->count <= other_moniker->count)
{
*prefix = iface;
hr = moniker->count == other_moniker->count ? MK_S_US : MK_S_ME;
}
else
{
*prefix = other;
hr = MK_S_HIM;
}
IMoniker_AddRef(*prefix);
return hr;
}
return MonikerCommonPrefixWith(iface, other, prefix);
}
/******************************************************************************
* AntiMoniker_RelativePathTo
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
{
TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
if (ppmkRelPath==NULL)
return E_POINTER;
IMoniker_AddRef(pmOther);
*ppmkRelPath=pmOther;
return MK_S_HIM;
}
/******************************************************************************
* AntiMoniker_GetDisplayName
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_GetDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, LPOLESTR *displayname)
{
AntiMonikerImpl *moniker = impl_from_IMoniker(iface);
static const WCHAR nameW[] = {'\\','.','.'};
WCHAR *ptrW;
int i;
TRACE("%p, %p, %p, %p.\n", iface, pbc, pmkToLeft, displayname);
if (!displayname)
return E_POINTER;
if (pmkToLeft!=NULL){
FIXME("() pmkToLeft!=NULL not implemented\n");
return E_NOTIMPL;
}
*displayname = ptrW = CoTaskMemAlloc((moniker->count * ARRAY_SIZE(nameW) + 1) * sizeof(WCHAR));
if (!*displayname)
return E_OUTOFMEMORY;
for (i = 0; i < moniker->count; ++i)
memcpy(ptrW + i * ARRAY_SIZE(nameW), nameW, sizeof(nameW));
ptrW[moniker->count * ARRAY_SIZE(nameW)] = 0;
return S_OK;
}
/******************************************************************************
* AntiMoniker_ParseDisplayName
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
IMoniker* pmkToLeft, LPOLESTR pszDisplayName,
ULONG* pchEaten, IMoniker** ppmkOut)
{
TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
return E_NOTIMPL;
}
/******************************************************************************
* AntiMoniker_IsSystemMoniker
******************************************************************************/
static HRESULT WINAPI
AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
{
TRACE("(%p,%p)\n",iface,pwdMksys);
if (!pwdMksys)
return E_POINTER;
(*pwdMksys)=MKSYS_ANTIMONIKER;
return S_OK;
}
/*******************************************************************************
* AntiMonikerIROTData_QueryInterface
*******************************************************************************/
static HRESULT WINAPI
AntiMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
{
AntiMonikerImpl *This = impl_from_IROTData(iface);
TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppvObject);
return AntiMonikerImpl_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
}
/***********************************************************************
* AntiMonikerIROTData_AddRef
*/
static ULONG WINAPI AntiMonikerROTDataImpl_AddRef(IROTData *iface)
{
AntiMonikerImpl *This = impl_from_IROTData(iface);
TRACE("(%p)\n",iface);
return AntiMonikerImpl_AddRef(&This->IMoniker_iface);
}
/***********************************************************************
* AntiMonikerIROTData_Release
*/
static ULONG WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface)
{
AntiMonikerImpl *This = impl_from_IROTData(iface);
TRACE("(%p)\n",iface);
return AntiMonikerImpl_Release(&This->IMoniker_iface);
}
/******************************************************************************
* AntiMonikerIROTData_GetComparisonData
******************************************************************************/
static HRESULT WINAPI
AntiMonikerROTDataImpl_GetComparisonData(IROTData *iface, BYTE *data, ULONG data_len, ULONG *data_req)
{
AntiMonikerImpl *moniker = impl_from_IROTData(iface);
TRACE("%p, %p, %u, %p.\n", iface, data, data_len, data_req);
*data_req = sizeof(CLSID) + sizeof(DWORD);
if (data_len < *data_req)
return E_OUTOFMEMORY;
memcpy(data, &CLSID_AntiMoniker, sizeof(CLSID));
memcpy(data + sizeof(CLSID), &moniker->count, sizeof(moniker->count));
return S_OK;
}
/********************************************************************************/
/* Virtual function table for the AntiMonikerImpl class which include IPersist,*/
/* IPersistStream and IMoniker functions. */
static const IMonikerVtbl VT_AntiMonikerImpl =
{
AntiMonikerImpl_QueryInterface,
AntiMonikerImpl_AddRef,
AntiMonikerImpl_Release,
AntiMonikerImpl_GetClassID,
AntiMonikerImpl_IsDirty,
AntiMonikerImpl_Load,
AntiMonikerImpl_Save,
AntiMonikerImpl_GetSizeMax,
AntiMonikerImpl_BindToObject,
AntiMonikerImpl_BindToStorage,
AntiMonikerImpl_Reduce,
AntiMonikerImpl_ComposeWith,
AntiMonikerImpl_Enum,
AntiMonikerImpl_IsEqual,
AntiMonikerImpl_Hash,
AntiMonikerImpl_IsRunning,
AntiMonikerImpl_GetTimeOfLastChange,
AntiMonikerImpl_Inverse,
AntiMonikerImpl_CommonPrefixWith,
AntiMonikerImpl_RelativePathTo,
AntiMonikerImpl_GetDisplayName,
AntiMonikerImpl_ParseDisplayName,
AntiMonikerImpl_IsSystemMoniker
};
static AntiMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface)
{
if (iface->lpVtbl != &VT_AntiMonikerImpl)
return NULL;
return CONTAINING_RECORD(iface, AntiMonikerImpl, IMoniker_iface);
}
/********************************************************************************/
/* Virtual function table for the IROTData class. */
static const IROTDataVtbl VT_ROTDataImpl =
{
AntiMonikerROTDataImpl_QueryInterface,
AntiMonikerROTDataImpl_AddRef,
AntiMonikerROTDataImpl_Release,
AntiMonikerROTDataImpl_GetComparisonData
};
HRESULT create_anti_moniker(DWORD order, IMoniker **ret)
{
AntiMonikerImpl *moniker;
moniker = heap_alloc_zero(sizeof(*moniker));
if (!moniker)
return E_OUTOFMEMORY;
moniker->IMoniker_iface.lpVtbl = &VT_AntiMonikerImpl;
moniker->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
moniker->refcount = 1;
moniker->count = order;
*ret = &moniker->IMoniker_iface;
return S_OK;
}
/******************************************************************************
* CreateAntiMoniker [OLE32.@]
******************************************************************************/
HRESULT WINAPI CreateAntiMoniker(IMoniker **moniker)
{
TRACE("%p.\n", moniker);
return create_anti_moniker(1, moniker);
}
HRESULT WINAPI AntiMoniker_CreateInstance(IClassFactory *iface,
IUnknown *pUnk, REFIID riid, void **ppv)
{
IMoniker *pMoniker;
HRESULT hr;
TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
*ppv = NULL;
if (pUnk)
return CLASS_E_NOAGGREGATION;
hr = CreateAntiMoniker(&pMoniker);
if (FAILED(hr))
return hr;
hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
IMoniker_Release(pMoniker);
return hr;
}