-/***************************************************************************************\r
- * ItemMonikers implementation\r
- *\r
- * Copyright 1999 Noomen Hamza\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- ***************************************************************************************/\r
-\r
-#include <assert.h>\r
-#include <stdarg.h>\r
-#include <string.h>\r
-\r
-#define COBJMACROS\r
-#define NONAMELESSUNION\r
-#define NONAMELESSSTRUCT\r
-\r
-#include "winerror.h"\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "winuser.h"\r
-#include "winnls.h"\r
-#include "wine/debug.h"\r
-#include "ole2.h"\r
-#include "wine/unicode.h"\r
-#include "moniker.h"\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
-\r
-const CLSID CLSID_ItemMoniker = {\r
- 0x304, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}\r
-};\r
-\r
-/* ItemMoniker data structure */\r
-typedef struct ItemMonikerImpl{\r
-\r
- IMonikerVtbl* lpvtbl1; /* VTable relative to the IMoniker interface.*/\r
-\r
- /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether\r
- * two monikers are equal. That's whay IROTData interface is implemented by monikers.\r
- */\r
- IROTDataVtbl* lpvtbl2; /* VTable relative to the IROTData interface.*/\r
-\r
- ULONG ref; /* reference counter for this object */\r
-\r
- LPOLESTR itemName; /* item name identified by this ItemMoniker */\r
-\r
- LPOLESTR itemDelimiter; /* Delimiter string */\r
-\r
- IUnknown *pMarshal; /* custom marshaler */\r
-} ItemMonikerImpl;\r
-\r
-/********************************************************************************/\r
-/* ItemMoniker prototype functions : */\r
-\r
-/* IUnknown prototype functions */\r
-static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);\r
-static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface);\r
-static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface);\r
-\r
-/* IPersist prototype functions */\r
-static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);\r
-\r
-/* IPersistStream prototype functions */\r
-static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface);\r
-static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface, IStream* pStm);\r
-static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);\r
-static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);\r
-\r
-/* IMoniker prototype functions */\r
-static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);\r
-static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);\r
-static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);\r
-static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);\r
-static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);\r
-static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);\r
-static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);\r
-static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);\r
-static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pItemTime);\r
-static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);\r
-static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);\r
-static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);\r
-static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);\r
-static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);\r
-static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);\r
-\r
-/* Local function used by ItemMoniker implementation */\r
-HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* iface, LPCOLESTR lpszDelim,LPCOLESTR lpszPathName);\r
-HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);\r
-\r
-/********************************************************************************/\r
-/* IROTData prototype functions */\r
-\r
-/* IUnknown prototype functions */\r
-static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);\r
-static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData* iface);\r
-static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface);\r
-\r
-/* IROTData prototype function */\r
-static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);\r
-\r
-/********************************************************************************/\r
-/* Virtual function table for the ItemMonikerImpl class which include IPersist,*/\r
-/* IPersistStream and IMoniker functions. */\r
-static IMonikerVtbl VT_ItemMonikerImpl =\r
- {\r
- ItemMonikerImpl_QueryInterface,\r
- ItemMonikerImpl_AddRef,\r
- ItemMonikerImpl_Release,\r
- ItemMonikerImpl_GetClassID,\r
- ItemMonikerImpl_IsDirty,\r
- ItemMonikerImpl_Load,\r
- ItemMonikerImpl_Save,\r
- ItemMonikerImpl_GetSizeMax,\r
- ItemMonikerImpl_BindToObject,\r
- ItemMonikerImpl_BindToStorage,\r
- ItemMonikerImpl_Reduce,\r
- ItemMonikerImpl_ComposeWith,\r
- ItemMonikerImpl_Enum,\r
- ItemMonikerImpl_IsEqual,\r
- ItemMonikerImpl_Hash,\r
- ItemMonikerImpl_IsRunning,\r
- ItemMonikerImpl_GetTimeOfLastChange,\r
- ItemMonikerImpl_Inverse,\r
- ItemMonikerImpl_CommonPrefixWith,\r
- ItemMonikerImpl_RelativePathTo,\r
- ItemMonikerImpl_GetDisplayName,\r
- ItemMonikerImpl_ParseDisplayName,\r
- ItemMonikerImpl_IsSystemMoniker\r
-};\r
-\r
-/********************************************************************************/\r
-/* Virtual function table for the IROTData class. */\r
-static IROTDataVtbl VT_ROTDataImpl =\r
-{\r
- ItemMonikerROTDataImpl_QueryInterface,\r
- ItemMonikerROTDataImpl_AddRef,\r
- ItemMonikerROTDataImpl_Release,\r
- ItemMonikerROTDataImpl_GetComparisonData\r
-};\r
-\r
-/*******************************************************************************\r
- * ItemMoniker_QueryInterface\r
- *******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)\r
-{\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
-\r
- TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);\r
-\r
- /* Perform a sanity check on the parameters.*/\r
- if ( (This==0) || (ppvObject==0) )\r
- return E_INVALIDARG;\r
-\r
- /* Initialize the return parameter */\r
- *ppvObject = 0;\r
-\r
- /* Compare the riid with the interface IDs implemented by this object.*/\r
- if (IsEqualIID(&IID_IUnknown, riid) ||\r
- IsEqualIID(&IID_IPersist, riid) ||\r
- IsEqualIID(&IID_IPersistStream, riid) ||\r
- IsEqualIID(&IID_IMoniker, riid)\r
- )\r
- *ppvObject = iface;\r
-\r
- else if (IsEqualIID(&IID_IROTData, riid))\r
- *ppvObject = (IROTData*)&(This->lpvtbl2);\r
- else if (IsEqualIID(&IID_IMarshal, riid))\r
- {\r
- HRESULT hr = S_OK;\r
- if (!This->pMarshal)\r
- hr = MonikerMarshal_Create(iface, &This->pMarshal);\r
- if (hr != S_OK)\r
- return hr;\r
- return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);\r
- }\r
-\r
- /* Check that we obtained an interface.*/\r
- if ((*ppvObject)==0)\r
- return E_NOINTERFACE;\r
-\r
- /* Query Interface always increases the reference count by one when it is successful */\r
- ItemMonikerImpl_AddRef(iface);\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_AddRef\r
- ******************************************************************************/\r
-ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface)\r
-{\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
-\r
- TRACE("(%p)\n",This);\r
-\r
- return InterlockedIncrement(&This->ref);\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_Release\r
- ******************************************************************************/\r
-ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface)\r
-{\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
- ULONG ref;\r
-\r
- TRACE("(%p)\n",This);\r
-\r
- ref = InterlockedDecrement(&This->ref);\r
-\r
- /* destroy the object if there's no more reference on it */\r
- if (ref == 0) ItemMonikerImpl_Destroy(This);\r
-\r
- return ref;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_GetClassID\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)\r
-{\r
- TRACE("(%p,%p)\n",iface,pClassID);\r
-\r
- if (pClassID==NULL)\r
- return E_POINTER;\r
-\r
- *pClassID = CLSID_ItemMoniker;\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_IsDirty\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface)\r
-{\r
- /* Note that the OLE-provided implementations of the IPersistStream::IsDirty\r
- method in the OLE-provided moniker interfaces always return S_FALSE because\r
- their internal state never changes. */\r
-\r
- TRACE("(%p)\n",iface);\r
-\r
- return S_FALSE;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_Load\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm)\r
-{\r
-\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
- HRESULT res;\r
- DWORD delimiterLength,nameLength,lenW;\r
- CHAR *itemNameA,*itemDelimiterA;\r
- ULONG bread;\r
-\r
- TRACE("\n");\r
-\r
- /* for more details about data read by this function see coments of ItemMonikerImpl_Save function */\r
-\r
- /* read item delimiter string length + 1 */\r
- res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread);\r
- if (bread != sizeof(DWORD))\r
- return E_FAIL;\r
-\r
- /* read item delimiter string */\r
- if (!(itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength)))\r
- return E_OUTOFMEMORY;\r
- res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);\r
- if (bread != delimiterLength)\r
- {\r
- HeapFree( GetProcessHeap(), 0, itemDelimiterA );\r
- return E_FAIL;\r
- }\r
-\r
- lenW = MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, NULL, 0 );\r
- This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,lenW*sizeof(WCHAR));\r
- if (!This->itemDelimiter)\r
- {\r
- HeapFree( GetProcessHeap(), 0, itemDelimiterA );\r
- return E_OUTOFMEMORY;\r
- }\r
- MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, This->itemDelimiter, lenW );\r
- HeapFree( GetProcessHeap(), 0, itemDelimiterA );\r
-\r
- /* read item name string length + 1*/\r
- res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread);\r
- if (bread != sizeof(DWORD))\r
- return E_FAIL;\r
-\r
- /* read item name string */\r
- if (!(itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength)))\r
- return E_OUTOFMEMORY;\r
- res=IStream_Read(pStm,itemNameA,nameLength,&bread);\r
- if (bread != nameLength)\r
- {\r
- HeapFree( GetProcessHeap(), 0, itemNameA );\r
- return E_FAIL;\r
- }\r
-\r
- lenW = MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, NULL, 0 );\r
- This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,lenW*sizeof(WCHAR));\r
- if (!This->itemName)\r
- {\r
- HeapFree( GetProcessHeap(), 0, itemNameA );\r
- return E_OUTOFMEMORY;\r
- }\r
- MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, This->itemName, lenW );\r
- HeapFree( GetProcessHeap(), 0, itemNameA );\r
-\r
- return res;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_Save\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface,\r
- IStream* pStm,/* pointer to the stream where the object is to be saved */\r
- BOOL fClearDirty)/* Specifies whether to clear the dirty flag */\r
-{\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
- HRESULT res;\r
- CHAR *itemNameA,*itemDelimiterA;\r
-\r
- /* data written by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */\r
- /* 2) String (type A): item delimiter string ('\0' included) */\r
- /* 3) DWORD : size of item name string ('\0' included) */\r
- /* 4) String (type A): item name string ('\0' included) */\r
-\r
- DWORD nameLength = WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, NULL, 0, NULL, NULL);\r
- DWORD delimiterLength = WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, NULL, 0, NULL, NULL);\r
- itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);\r
- itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);\r
- WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL);\r
- WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL);\r
-\r
- TRACE("%p, %s\n", pStm, fClearDirty ? "TRUE" : "FALSE");\r
-\r
- res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);\r
- res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);\r
- res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);\r
- res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL);\r
-\r
- return res;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_GetSizeMax\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface,\r
- ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */\r
-{\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
- DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;\r
- DWORD nameLength=lstrlenW(This->itemName)+1;\r
-\r
- TRACE("(%p,%p)\n",iface,pcbSize);\r
-\r
- if (!pcbSize)\r
- return E_POINTER;\r
-\r
- /* for more details see ItemMonikerImpl_Save coments */\r
-\r
- pcbSize->u.LowPart = sizeof(DWORD) + /* DWORD which contains delimiter length */\r
- delimiterLength*4 + /* item delimiter string */\r
- sizeof(DWORD) + /* DWORD which contains item name length */\r
- nameLength*4 + /* item name string */\r
- 18; /* strange, but true */\r
- pcbSize->u.HighPart=0;\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_Construct (local function)\r
- *******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem)\r
-{\r
-\r
- int sizeStr1=lstrlenW(lpszItem), sizeStr2;\r
- static const OLECHAR emptystr[1];\r
- LPCOLESTR delim;\r
-\r
- TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszDelim),debugstr_w(lpszItem));\r
-\r
- /* Initialize the virtual fgunction table. */\r
- This->lpvtbl1 = &VT_ItemMonikerImpl;\r
- This->lpvtbl2 = &VT_ROTDataImpl;\r
- This->ref = 0;\r
- This->pMarshal = NULL;\r
-\r
- This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));\r
- if (!This->itemName)\r
- return E_OUTOFMEMORY;\r
- lstrcpyW(This->itemName,lpszItem);\r
-\r
- if (!lpszDelim)\r
- FIXME("lpszDelim is NULL. Using empty string which is possibly wrong.\n");\r
-\r
- delim = lpszDelim ? lpszDelim : emptystr;\r
-\r
- sizeStr2=lstrlenW(delim);\r
- This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1));\r
- if (!This->itemDelimiter) {\r
- HeapFree(GetProcessHeap(),0,This->itemName);\r
- return E_OUTOFMEMORY;\r
- }\r
- lstrcpyW(This->itemDelimiter,delim);\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_Destroy (local function)\r
- *******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This)\r
-{\r
- TRACE("(%p)\n",This);\r
-\r
- if (This->pMarshal) IUnknown_Release(This->pMarshal);\r
- HeapFree(GetProcessHeap(),0,This->itemName);\r
- HeapFree(GetProcessHeap(),0,This->itemDelimiter);\r
- HeapFree(GetProcessHeap(),0,This);\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_BindToObject\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- REFIID riid,\r
- VOID** ppvResult)\r
-{\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
-\r
- HRESULT res;\r
- IID refid=IID_IOleItemContainer;\r
- IOleItemContainer *poic=0;\r
-\r
- TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);\r
-\r
- if(ppvResult ==NULL)\r
- return E_POINTER;\r
-\r
- if(pmkToLeft==NULL)\r
- return E_INVALIDARG;\r
-\r
- *ppvResult=0;\r
-\r
- res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic);\r
-\r
- if (SUCCEEDED(res)){\r
-\r
- res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult);\r
-\r
- IOleItemContainer_Release(poic);\r
- }\r
-\r
- return res;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_BindToStorage\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- REFIID riid,\r
- VOID** ppvResult)\r
-{\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
-\r
- HRESULT res;\r
- IOleItemContainer *poic=0;\r
-\r
- TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);\r
-\r
- *ppvResult=0;\r
-\r
- if(pmkToLeft==NULL)\r
- return E_INVALIDARG;\r
-\r
- res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);\r
-\r
- if (SUCCEEDED(res)){\r
-\r
- res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult);\r
-\r
- IOleItemContainer_Release(poic);\r
- }\r
-\r
- return res;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_Reduce\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,\r
- IBindCtx* pbc,\r
- DWORD dwReduceHowFar,\r
- IMoniker** ppmkToLeft,\r
- IMoniker** ppmkReduced)\r
-{\r
- TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);\r
-\r
- if (ppmkReduced==NULL)\r
- return E_POINTER;\r
-\r
- ItemMonikerImpl_AddRef(iface);\r
-\r
- *ppmkReduced=iface;\r
-\r
- return MK_S_REDUCED_TO_SELF;\r
-}\r
-/******************************************************************************\r
- * ItemMoniker_ComposeWith\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,\r
- IMoniker* pmkRight,\r
- BOOL fOnlyIfNotGeneric,\r
- IMoniker** ppmkComposite)\r
-{\r
- HRESULT res=S_OK;\r
- DWORD mkSys,mkSys2;\r
- IEnumMoniker* penumMk=0;\r
- IMoniker *pmostLeftMk=0;\r
- IMoniker* tempMkComposite=0;\r
-\r
- TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);\r
-\r
- if ((ppmkComposite==NULL)||(pmkRight==NULL))\r
- return E_POINTER;\r
-\r
- *ppmkComposite=0;\r
-\r
- IMoniker_IsSystemMoniker(pmkRight,&mkSys);\r
-\r
- /* If pmkRight is an anti-moniker, the returned moniker is NULL */\r
- if(mkSys==MKSYS_ANTIMONIKER)\r
- return res;\r
-\r
- else\r
- /* if pmkRight is a composite whose leftmost component is an anti-moniker, */\r
- /* the returned moniker is the composite after the leftmost anti-moniker is removed. */\r
-\r
- if(mkSys==MKSYS_GENERICCOMPOSITE){\r
-\r
- res=IMoniker_Enum(pmkRight,TRUE,&penumMk);\r
-\r
- if (FAILED(res))\r
- return res;\r
-\r
- res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);\r
-\r
- IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);\r
-\r
- if(mkSys2==MKSYS_ANTIMONIKER){\r
-\r
- IMoniker_Release(pmostLeftMk);\r
-\r
- tempMkComposite=iface;\r
- IMoniker_AddRef(iface);\r
-\r
- while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){\r
-\r
- res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);\r
-\r
- IMoniker_Release(tempMkComposite);\r
- IMoniker_Release(pmostLeftMk);\r
-\r
- tempMkComposite=*ppmkComposite;\r
- IMoniker_AddRef(tempMkComposite);\r
- }\r
- return res;\r
- }\r
- else\r
- return CreateGenericComposite(iface,pmkRight,ppmkComposite);\r
- }\r
- /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic\r
- composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns\r
- a NULL moniker and a return value of MK_E_NEEDGENERIC */\r
- else\r
- if (!fOnlyIfNotGeneric)\r
- return CreateGenericComposite(iface,pmkRight,ppmkComposite);\r
-\r
- else\r
- return MK_E_NEEDGENERIC;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_Enum\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)\r
-{\r
- TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);\r
-\r
- if (ppenumMoniker == NULL)\r
- return E_POINTER;\r
-\r
- *ppenumMoniker = NULL;\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_IsEqual\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)\r
-{\r
-\r
- CLSID clsid;\r
- LPOLESTR dispName1,dispName2;\r
- IBindCtx* bind;\r
- HRESULT res = S_FALSE;\r
-\r
- TRACE("(%p,%p)\n",iface,pmkOtherMoniker);\r
-\r
- if (!pmkOtherMoniker) return S_FALSE;\r
-\r
-\r
- /* check if both are ItemMoniker */\r
- if(FAILED (IMoniker_GetClassID(pmkOtherMoniker,&clsid))) return S_FALSE;\r
- if(!IsEqualCLSID(&clsid,&CLSID_ItemMoniker)) return S_FALSE;\r
-\r
- /* check if both displaynames are the same */\r
- if(SUCCEEDED ((res = CreateBindCtx(0,&bind)))) {\r
- if(SUCCEEDED (IMoniker_GetDisplayName(iface,bind,NULL,&dispName1))) {\r
- if(SUCCEEDED (IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2))) {\r
- if(lstrcmpW(dispName1,dispName2)==0) res = S_OK;\r
- CoTaskMemFree(dispName2);\r
- }\r
- CoTaskMemFree(dispName1);\r
- }\r
- }\r
- return res;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_Hash\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)\r
-{\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
-\r
- int h = 0,i,skip,len;\r
- int off = 0;\r
- LPOLESTR val;\r
-\r
- if (pdwHash==NULL)\r
- return E_POINTER;\r
-\r
- val = This->itemName;\r
- len = lstrlenW(val);\r
-\r
- if (len < 16) {\r
- for (i = len ; i > 0; i--) {\r
- h = (h * 37) + val[off++];\r
- }\r
- } else {\r
- /* only sample some characters */\r
- skip = len / 8;\r
- for (i = len ; i > 0; i -= skip, off += skip) {\r
- h = (h * 39) + val[off];\r
- }\r
- }\r
-\r
- *pdwHash=h;\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_IsRunning\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- IMoniker* pmkNewlyRunning)\r
-{\r
- IRunningObjectTable* rot;\r
- HRESULT res;\r
- IOleItemContainer *poic=0;\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
-\r
- TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);\r
-\r
- /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */\r
- /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running. */\r
- if (pmkToLeft==NULL)\r
- if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK))\r
- return S_OK;\r
- else {\r
- if (pbc==NULL)\r
- return E_POINTER;\r
-\r
- res=IBindCtx_GetRunningObjectTable(pbc,&rot);\r
-\r
- if (FAILED(res))\r
- return res;\r
-\r
- res = IRunningObjectTable_IsRunning(rot,iface);\r
-\r
- IRunningObjectTable_Release(rot);\r
- }\r
- else{\r
-\r
- /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter, */\r
- /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/\r
- /* passing the string contained within this moniker. */\r
-\r
- res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);\r
-\r
- if (SUCCEEDED(res)){\r
-\r
- res=IOleItemContainer_IsRunning(poic,This->itemName);\r
-\r
- IOleItemContainer_Release(poic);\r
- }\r
- }\r
-\r
- return res;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_GetTimeOfLastChange\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- FILETIME* pItemTime)\r
-{\r
- IRunningObjectTable* rot;\r
- HRESULT res;\r
- IMoniker *compositeMk;\r
-\r
- TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);\r
-\r
- if (pItemTime==NULL)\r
- return E_INVALIDARG;\r
-\r
- /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */\r
- if (pmkToLeft==NULL)\r
-\r
- return MK_E_NOTBINDABLE;\r
- else {\r
-\r
- /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */\r
- /* the time of last change. If the object is not in the ROT, the method calls */\r
- /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */\r
-\r
- res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);\r
-\r
- res=IBindCtx_GetRunningObjectTable(pbc,&rot);\r
-\r
- if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)\r
-\r
- res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);\r
-\r
- IMoniker_Release(compositeMk);\r
- }\r
-\r
- return res;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_Inverse\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)\r
-{\r
- TRACE("(%p,%p)\n",iface,ppmk);\r
-\r
- if (ppmk==NULL)\r
- return E_POINTER;\r
-\r
- return CreateAntiMoniker(ppmk);\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_CommonPrefixWith\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)\r
-{\r
- DWORD mkSys;\r
- \r
- TRACE("(%p,%p)\n", pmkOther, ppmkPrefix);\r
-\r
- IMoniker_IsSystemMoniker(pmkOther,&mkSys);\r
- /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */\r
- /* to this moniker and returns MK_S_US */\r
-\r
- if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){\r
-\r
- *ppmkPrefix=iface;\r
-\r
- IMoniker_AddRef(iface);\r
-\r
- return MK_S_US;\r
- }\r
- else\r
- /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */\r
- /* the case where the other moniker is a generic composite. */\r
- return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_RelativePathTo\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)\r
-{\r
- TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);\r
-\r
- if (ppmkRelPath==NULL)\r
- return E_POINTER;\r
-\r
- *ppmkRelPath=0;\r
-\r
- return MK_E_NOTBINDABLE;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_GetDisplayName\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- LPOLESTR *ppszDisplayName)\r
-{\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
-\r
- TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);\r
-\r
- if (ppszDisplayName==NULL)\r
- return E_POINTER;\r
-\r
- if (pmkToLeft!=NULL){\r
- return E_INVALIDARG;\r
- }\r
-\r
- *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1));\r
-\r
- if (*ppszDisplayName==NULL)\r
- return E_OUTOFMEMORY;\r
-\r
- lstrcpyW(*ppszDisplayName,This->itemDelimiter);\r
- lstrcatW(*ppszDisplayName,This->itemName);\r
-\r
- TRACE("-- %s\n", debugstr_w(*ppszDisplayName));\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_ParseDisplayName\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- LPOLESTR pszDisplayName,\r
- ULONG* pchEaten,\r
- IMoniker** ppmkOut)\r
-{\r
- IOleItemContainer* poic=0;\r
- IParseDisplayName* ppdn=0;\r
- LPOLESTR displayName;\r
- HRESULT res;\r
- ItemMonikerImpl *This = (ItemMonikerImpl *)iface;\r
-\r
- TRACE("%s\n", debugstr_w(pszDisplayName));\r
-\r
- /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */\r
- if (pmkToLeft==NULL)\r
-\r
- return MK_E_SYNTAX;\r
-\r
- else{\r
- /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */\r
- /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */\r
- /* name to IParseDisplayName::ParseDisplayName */\r
- res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);\r
-\r
- if (SUCCEEDED(res)){\r
-\r
- res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);\r
-\r
- res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName);\r
-\r
- res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut);\r
-\r
- IOleItemContainer_Release(poic);\r
- IParseDisplayName_Release(ppdn);\r
- }\r
- }\r
- return res;\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMoniker_IsSystemMoniker\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)\r
-{\r
- TRACE("(%p,%p)\n",iface,pwdMksys);\r
-\r
- if (!pwdMksys)\r
- return E_POINTER;\r
-\r
- (*pwdMksys)=MKSYS_ITEMMONIKER;\r
-\r
- return S_OK;\r
-}\r
-\r
-/*******************************************************************************\r
- * ItemMonikerIROTData_QueryInterface\r
- *******************************************************************************/\r
-HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)\r
-{\r
-\r
- ICOM_THIS_From_IROTData(IMoniker, iface);\r
-\r
- TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);\r
-\r
- return ItemMonikerImpl_QueryInterface(This, riid, ppvObject);\r
-}\r
-\r
-/***********************************************************************\r
- * ItemMonikerIROTData_AddRef\r
- */\r
-ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)\r
-{\r
- ICOM_THIS_From_IROTData(IMoniker, iface);\r
-\r
- TRACE("(%p)\n",iface);\r
-\r
- return ItemMonikerImpl_AddRef(This);\r
-}\r
-\r
-/***********************************************************************\r
- * ItemMonikerIROTData_Release\r
- */\r
-ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)\r
-{\r
- ICOM_THIS_From_IROTData(IMoniker, iface);\r
-\r
- TRACE("(%p)\n",iface);\r
-\r
- return ItemMonikerImpl_Release(This);\r
-}\r
-\r
-/******************************************************************************\r
- * ItemMonikerIROTData_GetComparaisonData\r
- ******************************************************************************/\r
-HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,\r
- BYTE* pbData,\r
- ULONG cbMax,\r
- ULONG* pcbData)\r
-{\r
- ICOM_THIS_From_IROTData(IMoniker, iface);\r
- ItemMonikerImpl *This1 = (ItemMonikerImpl *)This;\r
- int len = (strlenW(This1->itemName)+1);\r
- int i;\r
- LPWSTR pszItemName;\r
- LPWSTR pszItemDelimiter;\r
-\r
- TRACE("(%p, %lu, %p)\n", pbData, cbMax, pcbData);\r
-\r
- *pcbData = sizeof(CLSID) + sizeof(WCHAR) + len * sizeof(WCHAR);\r
- if (cbMax < *pcbData)\r
- return E_OUTOFMEMORY;\r
-\r
- /* write CLSID */\r
- memcpy(pbData, &CLSID_ItemMoniker, sizeof(CLSID));\r
- /* write delimiter */\r
- pszItemDelimiter = (LPWSTR)(pbData+sizeof(CLSID));\r
- *pszItemDelimiter = *This1->itemDelimiter;\r
- /* write name */\r
- pszItemName = pszItemDelimiter + 1;\r
- for (i = 0; i < len; i++)\r
- pszItemName[i] = toupperW(This1->itemName[i]);\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * CreateItemMoniker [OLE32.@]\r
- ******************************************************************************/\r
-HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk)\r
-{\r
- ItemMonikerImpl* newItemMoniker;\r
- HRESULT hr;\r
-\r
- TRACE("(%s,%s,%p)\n",debugstr_w(lpszDelim),debugstr_w(lpszItem),ppmk);\r
-\r
- newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));\r
-\r
- if (!newItemMoniker)\r
- return STG_E_INSUFFICIENTMEMORY;\r
-\r
- hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);\r
-\r
- if (FAILED(hr)){\r
-\r
- HeapFree(GetProcessHeap(),0,newItemMoniker);\r
- return hr;\r
- }\r
-\r
- return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&IID_IMoniker,(void**)ppmk);\r
-}\r
-\r
-static HRESULT WINAPI ItemMonikerCF_QueryInterface(LPCLASSFACTORY iface,\r
- REFIID riid, LPVOID *ppv)\r
-{\r
- *ppv = NULL;\r
- if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))\r
- {\r
- *ppv = iface;\r
- IUnknown_AddRef(iface);\r
- return S_OK;\r
- }\r
- return E_NOINTERFACE;\r
-}\r
-\r
-static ULONG WINAPI ItemMonikerCF_AddRef(LPCLASSFACTORY iface)\r
-{\r
- return 2; /* non-heap based object */\r
-}\r
-\r
-static ULONG WINAPI ItemMonikerCF_Release(LPCLASSFACTORY iface)\r
-{\r
- return 1; /* non-heap based object */\r
-}\r
-\r
-static HRESULT WINAPI ItemMonikerCF_CreateInstance(LPCLASSFACTORY iface,\r
- LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)\r
-{\r
- ItemMonikerImpl* newItemMoniker;\r
- HRESULT hr;\r
- static const WCHAR wszEmpty[] = { 0 };\r
-\r
- TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);\r
-\r
- *ppv = NULL;\r
-\r
- if (pUnk)\r
- return CLASS_E_NOAGGREGATION;\r
-\r
- newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));\r
- if (!newItemMoniker)\r
- return E_OUTOFMEMORY;\r
-\r
- hr = ItemMonikerImpl_Construct(newItemMoniker, wszEmpty, wszEmpty);\r
-\r
- if (SUCCEEDED(hr))\r
- hr = ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker, riid, ppv);\r
- if (FAILED(hr))\r
- HeapFree(GetProcessHeap(),0,newItemMoniker);\r
-\r
- return hr;\r
-}\r
-\r
-static HRESULT WINAPI ItemMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)\r
-{\r
- FIXME("(%d), stub!\n",fLock);\r
- return S_OK;\r
-}\r
-\r
-static const IClassFactoryVtbl ItemMonikerCFVtbl =\r
-{\r
- ItemMonikerCF_QueryInterface,\r
- ItemMonikerCF_AddRef,\r
- ItemMonikerCF_Release,\r
- ItemMonikerCF_CreateInstance,\r
- ItemMonikerCF_LockServer\r
-};\r
-static const IClassFactoryVtbl *ItemMonikerCF = &ItemMonikerCFVtbl;\r
-\r
-HRESULT ItemMonikerCF_Create(REFIID riid, LPVOID *ppv)\r
-{\r
- return IClassFactory_QueryInterface((IClassFactory *)&ItemMonikerCF, riid, ppv);\r
-}\r
+/***************************************************************************************
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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);
+
+const CLSID CLSID_ItemMoniker = {
+ 0x304, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
+};
+
+/* ItemMoniker data structure */
+typedef struct ItemMonikerImpl{
+
+ 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.
+ */
+ IROTDataVtbl* lpvtbl2; /* VTable relative to the IROTData interface.*/
+
+ ULONG ref; /* reference counter for this object */
+
+ LPOLESTR itemName; /* item name identified by this ItemMoniker */
+
+ LPOLESTR itemDelimiter; /* Delimiter string */
+
+ IUnknown *pMarshal; /* custom marshaler */
+} ItemMonikerImpl;
+
+/********************************************************************************/
+/* ItemMoniker prototype functions : */
+
+/* IUnknown prototype functions */
+static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
+static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface);
+static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface);
+
+/* IPersist prototype functions */
+static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
+
+/* IPersistStream prototype functions */
+static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface);
+static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface, IStream* pStm);
+static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
+static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
+
+/* IMoniker prototype functions */
+static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
+static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
+static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
+static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
+static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
+static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
+static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
+static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
+static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pItemTime);
+static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
+static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
+static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
+static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
+static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
+static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
+
+/* Local function used by ItemMoniker implementation */
+HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* iface, LPCOLESTR lpszDelim,LPCOLESTR lpszPathName);
+HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
+
+/********************************************************************************/
+/* IROTData prototype functions */
+
+/* IUnknown prototype functions */
+static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
+static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData* iface);
+static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface);
+
+/* IROTData prototype function */
+static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
+
+/********************************************************************************/
+/* Virtual function table for the ItemMonikerImpl class which include IPersist,*/
+/* IPersistStream and IMoniker functions. */
+static 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 IROTDataVtbl VT_ROTDataImpl =
+{
+ ItemMonikerROTDataImpl_QueryInterface,
+ ItemMonikerROTDataImpl_AddRef,
+ ItemMonikerROTDataImpl_Release,
+ ItemMonikerROTDataImpl_GetComparisonData
+};
+
+/*******************************************************************************
+ * ItemMoniker_QueryInterface
+ *******************************************************************************/
+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 = (IROTData*)&(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 */
+ ItemMonikerImpl_AddRef(iface);
+
+ return S_OK;
+}
+
+/******************************************************************************
+ * ItemMoniker_AddRef
+ ******************************************************************************/
+ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface)
+{
+ ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
+
+ TRACE("(%p)\n",This);
+
+ return InterlockedIncrement(&This->ref);
+}
+
+/******************************************************************************
+ * ItemMoniker_Release
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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 coments 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
+ ******************************************************************************/
+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);
+
+ return res;
+}
+
+/******************************************************************************
+ * ItemMoniker_GetSizeMax
+ ******************************************************************************/
+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 coments */
+
+ 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_Construct (local function)
+ *******************************************************************************/
+HRESULT WINAPI 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 fgunction 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)
+ *******************************************************************************/
+HRESULT WINAPI 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;
+}
+
+/******************************************************************************
+ * ItemMoniker_BindToObject
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
+ IBindCtx* pbc,
+ DWORD dwReduceHowFar,
+ IMoniker** ppmkToLeft,
+ IMoniker** ppmkReduced)
+{
+ TRACE("(%p,%p,%ld,%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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
+{
+ ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
+
+ int h = 0,i,skip,len;
+ int off = 0;
+ LPOLESTR val;
+
+ if (pdwHash==NULL)
+ return E_POINTER;
+
+ val = This->itemName;
+ len = lstrlenW(val);
+
+ if (len < 16) {
+ for (i = len ; i > 0; i--) {
+ h = (h * 37) + val[off++];
+ }
+ } else {
+ /* only sample some characters */
+ skip = len / 8;
+ for (i = len ; i > 0; i -= skip, off += skip) {
+ h = (h * 39) + val[off];
+ }
+ }
+
+ *pdwHash=h;
+
+ return S_OK;
+}
+
+/******************************************************************************
+ * ItemMoniker_IsRunning
+ ******************************************************************************/
+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_POINTER;
+
+ 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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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
+ ******************************************************************************/
+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
+ *******************************************************************************/
+HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
+{
+
+ ICOM_THIS_From_IROTData(IMoniker, iface);
+
+ TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
+
+ return ItemMonikerImpl_QueryInterface(This, riid, ppvObject);
+}
+
+/***********************************************************************
+ * ItemMonikerIROTData_AddRef
+ */
+ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
+{
+ ICOM_THIS_From_IROTData(IMoniker, iface);
+
+ TRACE("(%p)\n",iface);
+
+ return ItemMonikerImpl_AddRef(This);
+}
+
+/***********************************************************************
+ * ItemMonikerIROTData_Release
+ */
+ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
+{
+ ICOM_THIS_From_IROTData(IMoniker, iface);
+
+ TRACE("(%p)\n",iface);
+
+ return ItemMonikerImpl_Release(This);
+}
+
+/******************************************************************************
+ * ItemMonikerIROTData_GetComparaisonData
+ ******************************************************************************/
+HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,
+ BYTE* pbData,
+ ULONG cbMax,
+ ULONG* pcbData)
+{
+ ICOM_THIS_From_IROTData(IMoniker, iface);
+ ItemMonikerImpl *This1 = (ItemMonikerImpl *)This;
+ int len = (strlenW(This1->itemName)+1);
+ int i;
+ LPWSTR pszItemName;
+ LPWSTR pszItemDelimiter;
+
+ TRACE("(%p, %lu, %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;
+}
+
+/******************************************************************************
+ * 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);
+}