2004-12-31 15:20:48 +00:00
|
|
|
/***************************************************************************************
|
|
|
|
* 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 */
|
|
|
|
|
2005-05-28 09:30:04 +00:00
|
|
|
IUnknown *pMarshal; /* custom marshaler */
|
2004-12-31 15:20:48 +00:00
|
|
|
} 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 */
|
2005-05-28 09:30:04 +00:00
|
|
|
static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
|
2004-12-31 15:20:48 +00:00
|
|
|
|
|
|
|
/********************************************************************************/
|
|
|
|
/* 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,
|
2005-05-28 09:30:04 +00:00
|
|
|
ItemMonikerROTDataImpl_GetComparisonData
|
2004-12-31 15:20:48 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
* ItemMoniker_QueryInterface
|
|
|
|
*******************************************************************************/
|
|
|
|
HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
|
|
|
|
{
|
|
|
|
ItemMonikerImpl *This = (ItemMonikerImpl *)iface;
|
|
|
|
|
2005-03-14 23:17:44 +00:00
|
|
|
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
|
2004-12-31 15:20:48 +00:00
|
|
|
|
|
|
|
/* 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);
|
2005-05-28 09:30:04 +00:00
|
|
|
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);
|
|
|
|
}
|
2004-12-31 15:20:48 +00:00
|
|
|
|
|
|
|
/* 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)
|
|
|
|
{
|
2005-03-14 23:17:44 +00:00
|
|
|
TRACE("(%p,%p)\n",iface,pClassID);
|
2004-12-31 15:20:48 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2005-03-14 23:17:44 +00:00
|
|
|
TRACE("\n");
|
|
|
|
|
2004-12-31 15:20:48 +00:00
|
|
|
/* 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);
|
|
|
|
|
2005-03-14 23:17:44 +00:00
|
|
|
TRACE("%p, %s\n", pStm, fClearDirty ? "TRUE" : "FALSE");
|
|
|
|
|
2004-12-31 15:20:48 +00:00
|
|
|
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);
|
|
|
|
|
2005-05-28 09:30:04 +00:00
|
|
|
if (!pcbSize)
|
2004-12-31 15:20:48 +00:00
|
|
|
return E_POINTER;
|
|
|
|
|
|
|
|
/* for more details see ItemMonikerImpl_Save coments */
|
|
|
|
|
|
|
|
pcbSize->u.LowPart = sizeof(DWORD) + /* DWORD which contains delimiter length */
|
2005-05-28 09:30:04 +00:00
|
|
|
delimiterLength*4 + /* item delimiter string */
|
2004-12-31 15:20:48 +00:00
|
|
|
sizeof(DWORD) + /* DWORD which contains item name length */
|
2005-05-28 09:30:04 +00:00
|
|
|
nameLength*4 + /* item name string */
|
|
|
|
18; /* strange, but true */
|
2004-12-31 15:20:48 +00:00
|
|
|
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;
|
|
|
|
|
2005-03-14 23:17:44 +00:00
|
|
|
TRACE("(%p,%s,%s)\n",This,debugstr_w(lpszDelim),debugstr_w(lpszItem));
|
2004-12-31 15:20:48 +00:00
|
|
|
|
|
|
|
/* Initialize the virtual fgunction table. */
|
|
|
|
This->lpvtbl1 = &VT_ItemMonikerImpl;
|
|
|
|
This->lpvtbl2 = &VT_ROTDataImpl;
|
|
|
|
This->ref = 0;
|
2005-05-28 09:30:04 +00:00
|
|
|
This->pMarshal = NULL;
|
2004-12-31 15:20:48 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2005-05-28 09:30:04 +00:00
|
|
|
if (This->pMarshal) IUnknown_Release(This->pMarshal);
|
Sync to Wine-20050111:
Michael Stefaniuc <mstefani@redhat.de>
- Do not check for non NULL pointer before HeapFree'ing it. It's
redundant.
Eric Pouech <pouech-eric@wanadoo.fr>
- Fixed some errors in function prototypes.
- ReadFile and WriteFile must be passed a parameter for the number of
handled bytes when no overlapped operation is done.
- Removed excessive statement (break after return or goto, not useful
break, not needed vars...)
Robert Shearman <rob@codeweavers.com>
- Remove unnecessary WNDPROC casts.
- Document how thread-safety is ensured for each member of the
stub_manager and ifstub structs.
- Make stub_manager ref counted to ensure it doesn't get freed whilst
it is still being used.
- ifstubs are now freed only when the controlling stub_manager is freed.
- Rename stub_manager_ref/unref to stub_manager_ext_addref/release
respectively and make then take an unsigned long to prevent
malicious callers from passing in a negative value and corrupting
the ref count.
- Rename iid in wine_marshal_id to ipid and use IPIDs instead of IIDs in
the stub manager.
- The channel buffer can be NULL if the proxy is disconnected, so check
for this before releasing it.
- Make the ClassFactory proxy support aggregation.
- Document how thread-safety is ensured for each member of the
stub_manager and ifstub structs.
- Make stub_manager ref counted to ensure it doesn't get freed whilst
it is still being used.
- ifstubs are now freed only when the controlling stub_manager is freed.
- Rename stub_manager_ref/unref to stub_manager_ext_addref/release
respectively and make then take an unsigned long to prevent
malicious callers from passing in a negative value and corrupting
the ref count.
- The current architecture cannot handle pipes changing address, so use
a static array. Fixes memory corruption that sometimes occurs when
using multiple pipes.
- Fix race on apartment creation.
- Display errors in decimal to make searching for the meaning in
winerror.h easier.
- Move named pipe macros into rpc.c.
- Remove unneeded function.
- Implement COM local servers using table marshaling to avoid doing the
marshaling in a child thread where COM has not been initialized.
- Remove unneeded includes and the unused COMPOBJ_hInstance32 variable.
- Make the wine_marshal_id structure more like the DCOM OBJREF
structure, by replacing the process id field by apartment id (OXID),
changing the users of the process id field to use the new field and
renaming the objectid field to oid.
- Fix StdMarshalImpl_UnmarshalInterface to invalidate and release its
stub when doing a same apartment marshal.
- Fixed incorrect unsigned test.
- Add tracing for proxy ref count functions.
- Release the channel on proxy destruction.
- Implement proxy manager.
- Add documentation to several functions.
- Coding style changes according to the style Mike and I have agreed
upon for COM related files.
- Use OBJREF on the wire for generic marshaling functions.
- Add some function declarations to objbase.h.
- Add stubs for server ref counting.
- Implement HRESULT marshaling.
- Make struct oletls ref counted so that it is only detached from the
apartment on the final CoUninitialize.
- Decrease the size of the crit sec on destroying an apartment - it is
only needed for touching the apartment list.
- Small cleanups.
Mike Hearn <mh@codeweavers.com>
- Implement the COM stub manager, refactor the current stub code.
- Begin implementing interface stubs.
- Make apartment access thread-safe by introducing refcounting and
wider usage of the apartment lock.
- Rework OLE TLS management to eliminate uninitialised apartments and
parent chaining.
- Comment out an assert, as we don't yet implement IRemUnknown.
- Propagate apartments through the intermediate threads, make listener
thread apartment scoped.
- Rename the STUBMGR thread to more accurately reflect its purpose.
- Add a DCOM todo list.
Mike McCormack <mike@codeweavers.com>
- Test and fix a few problems with OLE storage streams.
- Allow COM to start services containing COM servers.
- Tests and fixes for StgOpenStorage.
- Test and fix StgCreateDocFile grfModes.
Paul Vriens <Paul.Vriens@xs4all.nl>
- use Interlocked* functions in AddRef and Release.
- store the result of the Interlocked functions and use only this.
Francois Gouget <fgouget@free.fr>
- Assorted spelling fixes.
Alexandre Julliard <julliard@winehq.org>
- Janitorial: C booleans must not be compared against TRUE.
Bill Medland <billmedland@mercuryspeed.com>
- Corrected testing for multithreaded (based upon observations by Paul
Vriens, Christian Costa and Robert Shearman).
- Added TRACE for investigating OXID errors.
svn path=/trunk/; revision=12952
2005-01-12 10:23:25 +00:00
|
|
|
HeapFree(GetProcessHeap(),0,This->itemName);
|
|
|
|
HeapFree(GetProcessHeap(),0,This->itemDelimiter);
|
2004-12-31 15:20:48 +00:00
|
|
|
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;
|
|
|
|
|
2005-03-14 23:17:44 +00:00
|
|
|
TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
|
2004-12-31 15:20:48 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2005-03-14 23:17:44 +00:00
|
|
|
TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
|
2004-12-31 15:20:48 +00:00
|
|
|
|
|
|
|
*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;
|
2005-03-14 23:17:44 +00:00
|
|
|
|
|
|
|
TRACE("(%p,%p)\n", pmkOther, ppmkPrefix);
|
|
|
|
|
2004-12-31 15:20:48 +00:00
|
|
|
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);
|
|
|
|
|
2005-03-14 23:17:44 +00:00
|
|
|
TRACE("-- %s\n", debugstr_w(*ppszDisplayName));
|
|
|
|
|
2004-12-31 15:20:48 +00:00
|
|
|
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;
|
|
|
|
|
2005-03-14 23:17:44 +00:00
|
|
|
TRACE("%s\n", debugstr_w(pszDisplayName));
|
|
|
|
|
2004-12-31 15:20:48 +00:00
|
|
|
/* 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
|
|
|
|
******************************************************************************/
|
2005-05-28 09:30:04 +00:00
|
|
|
HRESULT WINAPI ItemMonikerROTDataImpl_GetComparisonData(IROTData* iface,
|
2004-12-31 15:20:48 +00:00
|
|
|
BYTE* pbData,
|
|
|
|
ULONG cbMax,
|
|
|
|
ULONG* pcbData)
|
|
|
|
{
|
2005-05-28 09:30:04 +00:00
|
|
|
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;
|
2004-12-31 15:20:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
* CreateItemMoniker [OLE32.@]
|
|
|
|
******************************************************************************/
|
|
|
|
HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk)
|
|
|
|
{
|
2005-03-14 23:17:44 +00:00
|
|
|
ItemMonikerImpl* newItemMoniker;
|
|
|
|
HRESULT hr;
|
2004-12-31 15:20:48 +00:00
|
|
|
|
2005-03-14 23:17:44 +00:00
|
|
|
TRACE("(%s,%s,%p)\n",debugstr_w(lpszDelim),debugstr_w(lpszItem),ppmk);
|
2004-12-31 15:20:48 +00:00
|
|
|
|
|
|
|
newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
|
|
|
|
|
2005-03-14 23:17:44 +00:00
|
|
|
if (!newItemMoniker)
|
2004-12-31 15:20:48 +00:00
|
|
|
return STG_E_INSUFFICIENTMEMORY;
|
|
|
|
|
|
|
|
hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);
|
|
|
|
|
|
|
|
if (FAILED(hr)){
|
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(),0,newItemMoniker);
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
|
2005-03-14 23:17:44 +00:00
|
|
|
return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&IID_IMoniker,(void**)ppmk);
|
2004-12-31 15:20:48 +00:00
|
|
|
}
|
2005-05-28 09:30:04 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|