| /* | |
| * Pointer Moniker Implementation | |
| * | |
| * Copyright 1999 Noomen Hamza | |
| * Copyright 2008 Robert Shearman (for CodeWeavers) | |
| * | |
| * 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 <stdarg.h> | |
| #include <string.h> | |
| #define COBJMACROS | |
| #define NONAMELESSUNION | |
| #include "windef.h" | |
| #include "winbase.h" | |
| #include "winerror.h" | |
| #include "winuser.h" | |
| #include "objbase.h" | |
| #include "oleidl.h" | |
| #include "wine/debug.h" | |
| #include "moniker.h" | |
| WINE_DEFAULT_DEBUG_CHANNEL(ole); | |
| /* PointerMoniker data structure */ | |
| typedef struct PointerMonikerImpl{ | |
| IMoniker IMoniker_iface; | |
| LONG ref; /* reference counter for this object */ | |
| IUnknown *pObject; /* custom marshaler */ | |
| } PointerMonikerImpl; | |
| static inline PointerMonikerImpl *impl_from_IMoniker(IMoniker *iface) | |
| { | |
| return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface); | |
| } | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) | |
| { | |
| PointerMonikerImpl *This = impl_from_IMoniker(iface); | |
| TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject); | |
| /* Perform a sanity check on the parameters.*/ | |
| if ( (This==0) || (ppvObject==0) ) | |
| return E_INVALIDARG; | |
| /* Initialize the return parameter */ | |
| *ppvObject = 0; | |
| /* Compare the riid with the interface IDs implemented by this object.*/ | |
| if (IsEqualIID(&IID_IUnknown, riid) || | |
| IsEqualIID(&IID_IPersist, riid) || | |
| IsEqualIID(&IID_IPersistStream, riid) || | |
| IsEqualIID(&IID_IMoniker, riid)) | |
| *ppvObject = iface; | |
| /* Check that we obtained an interface.*/ | |
| if ((*ppvObject)==0) | |
| return E_NOINTERFACE; | |
| /* always increase the reference count by one when it is successful */ | |
| IMoniker_AddRef(iface); | |
| return S_OK; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_AddRef | |
| ******************************************************************************/ | |
| static ULONG WINAPI | |
| PointerMonikerImpl_AddRef(IMoniker* iface) | |
| { | |
| PointerMonikerImpl *This = impl_from_IMoniker(iface); | |
| TRACE("(%p)\n",This); | |
| return InterlockedIncrement(&This->ref); | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_Release | |
| ******************************************************************************/ | |
| static ULONG WINAPI | |
| PointerMonikerImpl_Release(IMoniker* iface) | |
| { | |
| PointerMonikerImpl *This = impl_from_IMoniker(iface); | |
| ULONG ref; | |
| TRACE("(%p)\n",This); | |
| ref = InterlockedDecrement(&This->ref); | |
| /* destroy the object if there are no more references on it */ | |
| if (ref == 0) | |
| { | |
| if (This->pObject) IUnknown_Release(This->pObject); | |
| HeapFree(GetProcessHeap(),0,This); | |
| } | |
| return ref; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_GetClassID | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID) | |
| { | |
| TRACE("(%p,%p)\n",iface,pClassID); | |
| if (pClassID==NULL) | |
| return E_POINTER; | |
| *pClassID = CLSID_PointerMoniker; | |
| return S_OK; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_IsDirty | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_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; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_Load | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_Load(IMoniker* iface,IStream* pStm) | |
| { | |
| TRACE("(%p)\n", pStm); | |
| return E_NOTIMPL; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_Save | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty) | |
| { | |
| TRACE("(%p, %d)\n", pStm, fClearDirty); | |
| return E_NOTIMPL; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_GetSizeMax | |
| * | |
| * PARAMS | |
| * pcbSize [out] Pointer to size of stream needed to save object | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize) | |
| { | |
| TRACE("(%p,%p)\n",iface,pcbSize); | |
| if (!pcbSize) | |
| return E_POINTER; | |
| pcbSize->u.LowPart = 0; | |
| pcbSize->u.HighPart = 0; | |
| return E_NOTIMPL; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_BindToObject | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, | |
| REFIID riid, VOID** ppvResult) | |
| { | |
| PointerMonikerImpl *This = impl_from_IMoniker(iface); | |
| TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); | |
| if (!This->pObject) | |
| return E_UNEXPECTED; | |
| return IUnknown_QueryInterface(This->pObject, riid, ppvResult); | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_BindToStorage | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, | |
| REFIID riid, VOID** ppvResult) | |
| { | |
| PointerMonikerImpl *This = impl_from_IMoniker(iface); | |
| TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); | |
| if (!This->pObject) | |
| return E_UNEXPECTED; | |
| return IUnknown_QueryInterface(This->pObject, riid, ppvResult); | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_Reduce | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_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; | |
| PointerMonikerImpl_AddRef(iface); | |
| *ppmkReduced=iface; | |
| return MK_S_REDUCED_TO_SELF; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_ComposeWith | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight, | |
| BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite) | |
| { | |
| HRESULT res=S_OK; | |
| DWORD mkSys,mkSys2; | |
| IEnumMoniker* penumMk=0; | |
| IMoniker *pmostLeftMk=0; | |
| IMoniker* tempMkComposite=0; | |
| TRACE("(%p,%d,%p)\n", pmkRight, fOnlyIfNotGeneric, ppmkComposite); | |
| if ((ppmkComposite==NULL)||(pmkRight==NULL)) | |
| return E_POINTER; | |
| *ppmkComposite=0; | |
| IMoniker_IsSystemMoniker(pmkRight,&mkSys); | |
| /* If pmkRight is an anti-moniker, the returned moniker is NULL */ | |
| if(mkSys==MKSYS_ANTIMONIKER) | |
| return res; | |
| else | |
| /* if pmkRight is a composite whose leftmost component is an anti-moniker, */ | |
| /* the returned moniker is the composite after the leftmost anti-moniker is removed. */ | |
| if(mkSys==MKSYS_GENERICCOMPOSITE){ | |
| res=IMoniker_Enum(pmkRight,TRUE,&penumMk); | |
| if (FAILED(res)) | |
| return res; | |
| res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL); | |
| IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2); | |
| if(mkSys2==MKSYS_ANTIMONIKER){ | |
| IMoniker_Release(pmostLeftMk); | |
| tempMkComposite=iface; | |
| IMoniker_AddRef(iface); | |
| while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){ | |
| res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite); | |
| IMoniker_Release(tempMkComposite); | |
| IMoniker_Release(pmostLeftMk); | |
| tempMkComposite=*ppmkComposite; | |
| IMoniker_AddRef(tempMkComposite); | |
| } | |
| return res; | |
| } | |
| else | |
| return CreateGenericComposite(iface,pmkRight,ppmkComposite); | |
| } | |
| /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic | |
| composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns | |
| a NULL moniker and a return value of MK_E_NEEDGENERIC */ | |
| else | |
| if (!fOnlyIfNotGeneric) | |
| return CreateGenericComposite(iface,pmkRight,ppmkComposite); | |
| else | |
| return MK_E_NEEDGENERIC; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_Enum | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_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; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_IsEqual | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) | |
| { | |
| PointerMonikerImpl *This = impl_from_IMoniker(iface); | |
| DWORD mkSys; | |
| TRACE("(%p,%p)\n",iface,pmkOtherMoniker); | |
| if (pmkOtherMoniker==NULL) | |
| return S_FALSE; | |
| IMoniker_IsSystemMoniker(pmkOtherMoniker,&mkSys); | |
| if (mkSys==MKSYS_POINTERMONIKER) | |
| { | |
| PointerMonikerImpl *pOtherMoniker = impl_from_IMoniker(pmkOtherMoniker); | |
| return This->pObject == pOtherMoniker->pObject ? S_OK : S_FALSE; | |
| } | |
| else | |
| return S_FALSE; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_Hash | |
| ******************************************************************************/ | |
| static HRESULT WINAPI PointerMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) | |
| { | |
| PointerMonikerImpl *This = impl_from_IMoniker(iface); | |
| if (pdwHash==NULL) | |
| return E_POINTER; | |
| *pdwHash = PtrToUlong(This->pObject); | |
| return S_OK; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_IsRunning | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, | |
| IMoniker* pmkNewlyRunning) | |
| { | |
| TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning); | |
| return S_OK; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_GetTimeOfLastChange | |
| ******************************************************************************/ | |
| static HRESULT WINAPI PointerMonikerImpl_GetTimeOfLastChange(IMoniker* iface, | |
| IBindCtx* pbc, | |
| IMoniker* pmkToLeft, | |
| FILETIME* pAntiTime) | |
| { | |
| TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime); | |
| return E_NOTIMPL; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_Inverse | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) | |
| { | |
| TRACE("(%p,%p)\n",iface,ppmk); | |
| return CreateAntiMoniker(ppmk); | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_CommonPrefixWith | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) | |
| { | |
| TRACE("(%p, %p)\n", pmkOther, ppmkPrefix); | |
| *ppmkPrefix = NULL; | |
| if (PointerMonikerImpl_IsEqual(iface, pmkOther)) | |
| { | |
| IMoniker_AddRef(iface); | |
| *ppmkPrefix=iface; | |
| return MK_S_US; | |
| } | |
| else | |
| return MK_E_NOPREFIX; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_RelativePathTo | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) | |
| { | |
| TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath); | |
| if (ppmkRelPath==NULL) | |
| return E_POINTER; | |
| *ppmkRelPath = NULL; | |
| return E_NOTIMPL; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_GetDisplayName | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc, | |
| IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName) | |
| { | |
| TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName); | |
| if (ppszDisplayName==NULL) | |
| return E_POINTER; | |
| *ppszDisplayName = NULL; | |
| return E_NOTIMPL; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_ParseDisplayName | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, | |
| IMoniker* pmkToLeft, LPOLESTR pszDisplayName, | |
| ULONG* pchEaten, IMoniker** ppmkOut) | |
| { | |
| PointerMonikerImpl *This = impl_from_IMoniker(iface); | |
| HRESULT hr; | |
| IParseDisplayName *pPDN; | |
| TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut); | |
| if (pmkToLeft) | |
| return MK_E_SYNTAX; | |
| if (!This->pObject) | |
| return E_UNEXPECTED; | |
| hr = IUnknown_QueryInterface(This->pObject, &IID_IParseDisplayName, (void **)&pPDN); | |
| if (FAILED(hr)) | |
| return hr; | |
| hr = IParseDisplayName_ParseDisplayName(pPDN, pbc, pszDisplayName, pchEaten, ppmkOut); | |
| IParseDisplayName_Release(pPDN); | |
| return hr; | |
| } | |
| /****************************************************************************** | |
| * PointerMoniker_IsSystemMoniker | |
| ******************************************************************************/ | |
| static HRESULT WINAPI | |
| PointerMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) | |
| { | |
| TRACE("(%p,%p)\n",iface,pwdMksys); | |
| if (!pwdMksys) | |
| return E_POINTER; | |
| *pwdMksys = MKSYS_POINTERMONIKER; | |
| return S_OK; | |
| } | |
| /********************************************************************************/ | |
| /* Virtual function table for the PointerMonikerImpl class which include IPersist,*/ | |
| /* IPersistStream and IMoniker functions. */ | |
| static const IMonikerVtbl VT_PointerMonikerImpl = | |
| { | |
| PointerMonikerImpl_QueryInterface, | |
| PointerMonikerImpl_AddRef, | |
| PointerMonikerImpl_Release, | |
| PointerMonikerImpl_GetClassID, | |
| PointerMonikerImpl_IsDirty, | |
| PointerMonikerImpl_Load, | |
| PointerMonikerImpl_Save, | |
| PointerMonikerImpl_GetSizeMax, | |
| PointerMonikerImpl_BindToObject, | |
| PointerMonikerImpl_BindToStorage, | |
| PointerMonikerImpl_Reduce, | |
| PointerMonikerImpl_ComposeWith, | |
| PointerMonikerImpl_Enum, | |
| PointerMonikerImpl_IsEqual, | |
| PointerMonikerImpl_Hash, | |
| PointerMonikerImpl_IsRunning, | |
| PointerMonikerImpl_GetTimeOfLastChange, | |
| PointerMonikerImpl_Inverse, | |
| PointerMonikerImpl_CommonPrefixWith, | |
| PointerMonikerImpl_RelativePathTo, | |
| PointerMonikerImpl_GetDisplayName, | |
| PointerMonikerImpl_ParseDisplayName, | |
| PointerMonikerImpl_IsSystemMoniker | |
| }; | |
| /****************************************************************************** | |
| * PointerMoniker_Construct (local function) | |
| *******************************************************************************/ | |
| static void PointerMonikerImpl_Construct(PointerMonikerImpl* This, IUnknown *punk) | |
| { | |
| TRACE("(%p)\n",This); | |
| /* Initialize the virtual function table. */ | |
| This->IMoniker_iface.lpVtbl = &VT_PointerMonikerImpl; | |
| This->ref = 1; | |
| if (punk) | |
| IUnknown_AddRef(punk); | |
| This->pObject = punk; | |
| } | |
| /*********************************************************************** | |
| * CreatePointerMoniker (OLE32.@) | |
| * | |
| * Creates a moniker which represents a pointer. | |
| * | |
| * PARAMS | |
| * punk [I] Pointer to the object to represent. | |
| * ppmk [O] Address that receives the pointer to the created moniker. | |
| * | |
| * RETURNS | |
| * Success: S_OK. | |
| * Failure: Any HRESULT code. | |
| */ | |
| HRESULT WINAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER *ppmk) | |
| { | |
| PointerMonikerImpl *This; | |
| TRACE("(%p, %p)\n", punk, ppmk); | |
| if (!ppmk) | |
| return E_INVALIDARG; | |
| This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); | |
| if (!This) | |
| { | |
| *ppmk = NULL; | |
| return E_OUTOFMEMORY; | |
| } | |
| PointerMonikerImpl_Construct(This, punk); | |
| *ppmk = &This->IMoniker_iface; | |
| return S_OK; | |
| } | |
| HRESULT WINAPI PointerMoniker_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 = CreatePointerMoniker(NULL, &pMoniker); | |
| if (FAILED(hr)) | |
| return hr; | |
| hr = IMoniker_QueryInterface(pMoniker, riid, ppv); | |
| if (FAILED(hr)) | |
| IMoniker_Release(pMoniker); | |
| return hr; | |
| } |