/* * ItemMonikers 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 #define NONAMELESSSTRUCT #include "winerror.h" #include "windef.h" #include "winbase.h" #include "winuser.h" #include "winnls.h" #include "wine/debug.h" #include "ole2.h" #include "wine/unicode.h" #include "moniker.h" WINE_DEFAULT_DEBUG_CHANNEL(ole); /* ItemMoniker data structure */ typedef struct ItemMonikerImpl{ const IMonikerVtbl* lpvtbl1; /* VTable relative to the IMoniker interface.*/ /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether * two monikers are equal. That's whay IROTData interface is implemented by monikers. */ const IROTDataVtbl* lpvtbl2; /* VTable relative to the IROTData interface.*/ LONG ref; /* reference counter for this object */ LPOLESTR itemName; /* item name identified by this ItemMoniker */ LPOLESTR itemDelimiter; /* Delimiter string */ IUnknown *pMarshal; /* custom marshaler */ } ItemMonikerImpl; static inline IMoniker *impl_from_IROTData( IROTData *iface ) { return (IMoniker *)((char*)iface - FIELD_OFFSET(ItemMonikerImpl, lpvtbl2)); } static HRESULT ItemMonikerImpl_Destroy(ItemMonikerImpl* iface); /******************************************************************************* * ItemMoniker_QueryInterface *******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) { ItemMonikerImpl *This = (ItemMonikerImpl *)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; else if (IsEqualIID(&IID_IROTData, riid)) *ppvObject = &This->lpvtbl2; 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); } /* Check that we obtained an interface.*/ if ((*ppvObject)==0) return E_NOINTERFACE; /* Query Interface always increases the reference count by one when it is successful */ IMoniker_AddRef(iface); return S_OK; } /****************************************************************************** * ItemMoniker_AddRef ******************************************************************************/ static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface) { ItemMonikerImpl *This = (ItemMonikerImpl *)iface; TRACE("(%p)\n",This); return InterlockedIncrement(&This->ref); } /****************************************************************************** * ItemMoniker_Release ******************************************************************************/ static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface) { ItemMonikerImpl *This = (ItemMonikerImpl *)iface; ULONG ref; TRACE("(%p)\n",This); ref = InterlockedDecrement(&This->ref); /* destroy the object if there's no more reference on it */ if (ref == 0) ItemMonikerImpl_Destroy(This); return ref; } /****************************************************************************** * ItemMoniker_GetClassID ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID) { TRACE("(%p,%p)\n",iface,pClassID); if (pClassID==NULL) return E_POINTER; *pClassID = CLSID_ItemMoniker; return S_OK; } /****************************************************************************** * ItemMoniker_IsDirty ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_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; } /****************************************************************************** * ItemMoniker_Load ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm) { ItemMonikerImpl *This = (ItemMonikerImpl *)iface; HRESULT res; DWORD delimiterLength,nameLength,lenW; CHAR *itemNameA,*itemDelimiterA; ULONG bread; TRACE("\n"); /* for more details about data read by this function see comments of ItemMonikerImpl_Save function */ /* read item delimiter string length + 1 */ res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread); if (bread != sizeof(DWORD)) return E_FAIL; /* read item delimiter string */ if (!(itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength))) return E_OUTOFMEMORY; res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread); if (bread != delimiterLength) { HeapFree( GetProcessHeap(), 0, itemDelimiterA ); return E_FAIL; } lenW = MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, NULL, 0 ); This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,lenW*sizeof(WCHAR)); if (!This->itemDelimiter) { HeapFree( GetProcessHeap(), 0, itemDelimiterA ); return E_OUTOFMEMORY; } MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, This->itemDelimiter, lenW ); HeapFree( GetProcessHeap(), 0, itemDelimiterA ); /* read item name string length + 1*/ res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread); if (bread != sizeof(DWORD)) return E_FAIL; /* read item name string */ if (!(itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength))) return E_OUTOFMEMORY; res=IStream_Read(pStm,itemNameA,nameLength,&bread); if (bread != nameLength) { HeapFree( GetProcessHeap(), 0, itemNameA ); return E_FAIL; } lenW = MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, NULL, 0 ); This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,lenW*sizeof(WCHAR)); if (!This->itemName) { HeapFree( GetProcessHeap(), 0, itemNameA ); return E_OUTOFMEMORY; } MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, This->itemName, lenW ); HeapFree( GetProcessHeap(), 0, itemNameA ); return res; } /****************************************************************************** * ItemMoniker_Save ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm,/* pointer to the stream where the object is to be saved */ BOOL fClearDirty)/* Specifies whether to clear the dirty flag */ { ItemMonikerImpl *This = (ItemMonikerImpl *)iface; HRESULT res; CHAR *itemNameA,*itemDelimiterA; /* data written by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */ /* 2) String (type A): item delimiter string ('\0' included) */ /* 3) DWORD : size of item name string ('\0' included) */ /* 4) String (type A): item name string ('\0' included) */ DWORD nameLength = WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, NULL, 0, NULL, NULL); DWORD delimiterLength = WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, NULL, 0, NULL, NULL); itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength); itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength); WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL); WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL); TRACE("%p, %s\n", pStm, fClearDirty ? "TRUE" : "FALSE"); res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL); res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL); res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL); res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL); HeapFree(GetProcessHeap(), 0, itemNameA); HeapFree(GetProcessHeap(), 0, itemDelimiterA); return res; } /****************************************************************************** * ItemMoniker_GetSizeMax ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */ { ItemMonikerImpl *This = (ItemMonikerImpl *)iface; DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1; DWORD nameLength=lstrlenW(This->itemName)+1; TRACE("(%p,%p)\n",iface,pcbSize); if (!pcbSize) return E_POINTER; /* for more details see ItemMonikerImpl_Save comments */ pcbSize->u.LowPart = sizeof(DWORD) + /* DWORD which contains delimiter length */ delimiterLength*4 + /* item delimiter string */ sizeof(DWORD) + /* DWORD which contains item name length */ nameLength*4 + /* item name string */ 18; /* strange, but true */ pcbSize->u.HighPart=0; return S_OK; } /****************************************************************************** * ItemMoniker_BindToObject ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult) { ItemMonikerImpl *This = (ItemMonikerImpl *)iface; HRESULT res; IID refid=IID_IOleItemContainer; IOleItemContainer *poic=0; TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); if(ppvResult ==NULL) return E_POINTER; if(pmkToLeft==NULL) return E_INVALIDARG; *ppvResult=0; res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic); if (SUCCEEDED(res)){ res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult); IOleItemContainer_Release(poic); } return res; } /****************************************************************************** * ItemMoniker_BindToStorage ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult) { ItemMonikerImpl *This = (ItemMonikerImpl *)iface; HRESULT res; IOleItemContainer *poic=0; TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult); *ppvResult=0; if(pmkToLeft==NULL) return E_INVALIDARG; res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic); if (SUCCEEDED(res)){ res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult); IOleItemContainer_Release(poic); } return res; } /****************************************************************************** * ItemMoniker_Reduce ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_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; ItemMonikerImpl_AddRef(iface); *ppmkReduced=iface; return MK_S_REDUCED_TO_SELF; } /****************************************************************************** * ItemMoniker_ComposeWith ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_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,%p,%d,%p)\n",iface,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; } /****************************************************************************** * ItemMoniker_Enum ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_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; } /****************************************************************************** * ItemMoniker_IsEqual ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker) { CLSID clsid; LPOLESTR dispName1,dispName2; IBindCtx* bind; HRESULT res = S_FALSE; TRACE("(%p,%p)\n",iface,pmkOtherMoniker); if (!pmkOtherMoniker) return S_FALSE; /* check if both are ItemMoniker */ if(FAILED (IMoniker_GetClassID(pmkOtherMoniker,&clsid))) return S_FALSE; if(!IsEqualCLSID(&clsid,&CLSID_ItemMoniker)) return S_FALSE; /* check if both displaynames are the same */ if(SUCCEEDED ((res = CreateBindCtx(0,&bind)))) { if(SUCCEEDED (IMoniker_GetDisplayName(iface,bind,NULL,&dispName1))) { if(SUCCEEDED (IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2))) { if(lstrcmpW(dispName1,dispName2)==0) res = S_OK; CoTaskMemFree(dispName2); } CoTaskMemFree(dispName1); } } return res; } /****************************************************************************** * ItemMoniker_Hash ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash) { ItemMonikerImpl *This = (ItemMonikerImpl *)iface; DWORD h = 0; int i,len; int off = 0; LPOLESTR val; if (pdwHash==NULL) return E_POINTER; val = This->itemName; len = lstrlenW(val); for (i = len ; i > 0; i--) h = (h * 3) ^ toupperW(val[off++]); *pdwHash=h; return S_OK; } /****************************************************************************** * ItemMoniker_IsRunning ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning) { IRunningObjectTable* rot; HRESULT res; IOleItemContainer *poic=0; ItemMonikerImpl *This = (ItemMonikerImpl *)iface; TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning); /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */ /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running. */ if (pmkToLeft==NULL) if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK)) return S_OK; else { if (pbc==NULL) return E_INVALIDARG; res=IBindCtx_GetRunningObjectTable(pbc,&rot); if (FAILED(res)) return res; res = IRunningObjectTable_IsRunning(rot,iface); IRunningObjectTable_Release(rot); } else{ /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter, */ /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/ /* passing the string contained within this moniker. */ res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic); if (SUCCEEDED(res)){ res=IOleItemContainer_IsRunning(poic,This->itemName); IOleItemContainer_Release(poic); } } return res; } /****************************************************************************** * ItemMoniker_GetTimeOfLastChange ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pItemTime) { IRunningObjectTable* rot; HRESULT res; IMoniker *compositeMk; TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime); if (pItemTime==NULL) return E_INVALIDARG; /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */ if (pmkToLeft==NULL) return MK_E_NOTBINDABLE; else { /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */ /* the time of last change. If the object is not in the ROT, the method calls */ /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */ res=CreateGenericComposite(pmkToLeft,iface,&compositeMk); res=IBindCtx_GetRunningObjectTable(pbc,&rot); if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK) res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime); IMoniker_Release(compositeMk); } return res; } /****************************************************************************** * ItemMoniker_Inverse ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk) { TRACE("(%p,%p)\n",iface,ppmk); if (ppmk==NULL) return E_POINTER; return CreateAntiMoniker(ppmk); } /****************************************************************************** * ItemMoniker_CommonPrefixWith ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) { DWORD mkSys; TRACE("(%p,%p)\n", pmkOther, ppmkPrefix); IMoniker_IsSystemMoniker(pmkOther,&mkSys); /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */ /* to this moniker and returns MK_S_US */ if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){ *ppmkPrefix=iface; IMoniker_AddRef(iface); return MK_S_US; } else /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */ /* the case where the other moniker is a generic composite. */ return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix); } /****************************************************************************** * ItemMoniker_RelativePathTo ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) { TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath); if (ppmkRelPath==NULL) return E_POINTER; *ppmkRelPath=0; return MK_E_NOTBINDABLE; } /****************************************************************************** * ItemMoniker_GetDisplayName ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName) { ItemMonikerImpl *This = (ItemMonikerImpl *)iface; TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName); if (ppszDisplayName==NULL) return E_POINTER; if (pmkToLeft!=NULL){ return E_INVALIDARG; } *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1)); if (*ppszDisplayName==NULL) return E_OUTOFMEMORY; lstrcpyW(*ppszDisplayName,This->itemDelimiter); lstrcatW(*ppszDisplayName,This->itemName); TRACE("-- %s\n", debugstr_w(*ppszDisplayName)); return S_OK; } /****************************************************************************** * ItemMoniker_ParseDisplayName ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut) { IOleItemContainer* poic=0; IParseDisplayName* ppdn=0; LPOLESTR displayName; HRESULT res; ItemMonikerImpl *This = (ItemMonikerImpl *)iface; TRACE("%s\n", debugstr_w(pszDisplayName)); /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */ if (pmkToLeft==NULL) return MK_E_SYNTAX; else{ /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */ /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */ /* name to IParseDisplayName::ParseDisplayName */ res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic); if (SUCCEEDED(res)){ res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn); res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName); res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut); IOleItemContainer_Release(poic); IParseDisplayName_Release(ppdn); } } return res; } /****************************************************************************** * ItemMoniker_IsSystemMoniker ******************************************************************************/ static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) { TRACE("(%p,%p)\n",iface,pwdMksys); if (!pwdMksys) return E_POINTER; (*pwdMksys)=MKSYS_ITEMMONIKER; return S_OK; } /******************************************************************************* * ItemMonikerIROTData_QueryInterface *******************************************************************************/ static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject) { IMoniker *This = impl_from_IROTData(iface); TRACE("(%p,%p,%p)\n",iface,riid,ppvObject); return ItemMonikerImpl_QueryInterface(This, riid, ppvObject); } /*********************************************************************** * ItemMonikerIROTData_AddRef */ static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface) { IMoniker *This = impl_from_IROTData(iface); TRACE("(%p)\n",iface); return ItemMonikerImpl_AddRef(This); } /*********************************************************************** * ItemMonikerIROTData_Release */ static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface) { IMoniker *This = impl_from_IROTData(iface); TRACE("(%p)\n",iface); return ItemMonikerImpl_Release(This); } /****************************************************************************** * ItemMonikerIROTData_GetComparisonData ******************************************************************************/ static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface, BYTE* pbData, ULONG cbMax, ULONG* pcbData) { IMoniker *This = impl_from_IROTData(iface); ItemMonikerImpl *This1 = (ItemMonikerImpl *)This; int len = (strlenW(This1->itemName)+1); int i; LPWSTR pszItemName; LPWSTR pszItemDelimiter; TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData); *pcbData = sizeof(CLSID) + sizeof(WCHAR) + len * sizeof(WCHAR); if (cbMax < *pcbData) return E_OUTOFMEMORY; /* write CLSID */ memcpy(pbData, &CLSID_ItemMoniker, sizeof(CLSID)); /* write delimiter */ pszItemDelimiter = (LPWSTR)(pbData+sizeof(CLSID)); *pszItemDelimiter = *This1->itemDelimiter; /* write name */ pszItemName = pszItemDelimiter + 1; for (i = 0; i < len; i++) pszItemName[i] = toupperW(This1->itemName[i]); return S_OK; } /********************************************************************************/ /* Virtual function table for the ItemMonikerImpl class which include IPersist,*/ /* IPersistStream and IMoniker functions. */ static const IMonikerVtbl VT_ItemMonikerImpl = { ItemMonikerImpl_QueryInterface, ItemMonikerImpl_AddRef, ItemMonikerImpl_Release, ItemMonikerImpl_GetClassID, ItemMonikerImpl_IsDirty, ItemMonikerImpl_Load, ItemMonikerImpl_Save, ItemMonikerImpl_GetSizeMax, ItemMonikerImpl_BindToObject, ItemMonikerImpl_BindToStorage, ItemMonikerImpl_Reduce, ItemMonikerImpl_ComposeWith, ItemMonikerImpl_Enum, ItemMonikerImpl_IsEqual, ItemMonikerImpl_Hash, ItemMonikerImpl_IsRunning, ItemMonikerImpl_GetTimeOfLastChange, ItemMonikerImpl_Inverse, ItemMonikerImpl_CommonPrefixWith, ItemMonikerImpl_RelativePathTo, ItemMonikerImpl_GetDisplayName, ItemMonikerImpl_ParseDisplayName, ItemMonikerImpl_IsSystemMoniker }; /********************************************************************************/ /* Virtual function table for the IROTData class. */ static const IROTDataVtbl VT_ROTDataImpl = { ItemMonikerROTDataImpl_QueryInterface, ItemMonikerROTDataImpl_AddRef, ItemMonikerROTDataImpl_Release, ItemMonikerROTDataImpl_GetComparisonData }; /****************************************************************************** * ItemMoniker_Construct (local function) *******************************************************************************/ static HRESULT ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem) { int sizeStr1=lstrlenW(lpszItem), sizeStr2; static const OLECHAR emptystr[1]; LPCOLESTR delim; TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszDelim),debugstr_w(lpszItem)); /* Initialize the virtual function table. */ This->lpvtbl1 = &VT_ItemMonikerImpl; This->lpvtbl2 = &VT_ROTDataImpl; This->ref = 0; This->pMarshal = NULL; This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1)); if (!This->itemName) return E_OUTOFMEMORY; lstrcpyW(This->itemName,lpszItem); if (!lpszDelim) FIXME("lpszDelim is NULL. Using empty string which is possibly wrong.\n"); delim = lpszDelim ? lpszDelim : emptystr; sizeStr2=lstrlenW(delim); This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1)); if (!This->itemDelimiter) { HeapFree(GetProcessHeap(),0,This->itemName); return E_OUTOFMEMORY; } lstrcpyW(This->itemDelimiter,delim); return S_OK; } /****************************************************************************** * ItemMoniker_Destroy (local function) *******************************************************************************/ static HRESULT ItemMonikerImpl_Destroy(ItemMonikerImpl* This) { TRACE("(%p)\n",This); if (This->pMarshal) IUnknown_Release(This->pMarshal); HeapFree(GetProcessHeap(),0,This->itemName); HeapFree(GetProcessHeap(),0,This->itemDelimiter); HeapFree(GetProcessHeap(),0,This); return S_OK; } /****************************************************************************** * CreateItemMoniker [OLE32.@] ******************************************************************************/ HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk) { ItemMonikerImpl* newItemMoniker; HRESULT hr; TRACE("(%s,%s,%p)\n",debugstr_w(lpszDelim),debugstr_w(lpszItem),ppmk); newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl)); if (!newItemMoniker) return STG_E_INSUFFICIENTMEMORY; hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem); if (FAILED(hr)){ HeapFree(GetProcessHeap(),0,newItemMoniker); return hr; } return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&IID_IMoniker,(void**)ppmk); } static HRESULT WINAPI ItemMonikerCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppv) { *ppv = NULL; if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory)) { *ppv = iface; IUnknown_AddRef(iface); return S_OK; } return E_NOINTERFACE; } static ULONG WINAPI ItemMonikerCF_AddRef(LPCLASSFACTORY iface) { return 2; /* non-heap based object */ } static ULONG WINAPI ItemMonikerCF_Release(LPCLASSFACTORY iface) { return 1; /* non-heap based object */ } static HRESULT WINAPI ItemMonikerCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) { ItemMonikerImpl* newItemMoniker; HRESULT hr; static const WCHAR wszEmpty[] = { 0 }; TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv); *ppv = NULL; if (pUnk) return CLASS_E_NOAGGREGATION; newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl)); if (!newItemMoniker) return E_OUTOFMEMORY; hr = ItemMonikerImpl_Construct(newItemMoniker, wszEmpty, wszEmpty); if (SUCCEEDED(hr)) hr = ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker, riid, ppv); if (FAILED(hr)) HeapFree(GetProcessHeap(),0,newItemMoniker); return hr; } static HRESULT WINAPI ItemMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) { FIXME("(%d), stub!\n",fLock); return S_OK; } static const IClassFactoryVtbl ItemMonikerCFVtbl = { ItemMonikerCF_QueryInterface, ItemMonikerCF_AddRef, ItemMonikerCF_Release, ItemMonikerCF_CreateInstance, ItemMonikerCF_LockServer }; static const IClassFactoryVtbl *ItemMonikerCF = &ItemMonikerCFVtbl; HRESULT ItemMonikerCF_Create(REFIID riid, LPVOID *ppv) { return IClassFactory_QueryInterface((IClassFactory *)&ItemMonikerCF, riid, ppv); }