diff --git a/dlls/ole32/filemoniker.c b/dlls/ole32/filemoniker.c index e192d9f9e03..0d4128c3b48 100644 --- a/dlls/ole32/filemoniker.c +++ b/dlls/ole32/filemoniker.c @@ -57,6 +57,7 @@ typedef struct FileMonikerImpl{ LPOLESTR filePathName; /* path string identified by this filemoniker */ + IUnknown *pMarshal; /* custom marshaler */ } FileMonikerImpl; /* Local function used by filemoniker implementation */ @@ -90,6 +91,15 @@ FileMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) 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) @@ -386,6 +396,7 @@ HRESULT WINAPI FileMonikerImpl_Destroy(FileMonikerImpl* This) { TRACE("(%p)\n",This); + if (This->pMarshal) IUnknown_Release(This->pMarshal); HeapFree(GetProcessHeap(),0,This->filePathName); HeapFree(GetProcessHeap(),0,This); @@ -1244,6 +1255,7 @@ FileMonikerImpl_Construct(FileMonikerImpl* This, LPCOLESTR lpszPathName) This->lpvtbl1 = &VT_FileMonikerImpl; This->lpvtbl2 = &VT_ROTDataImpl; This->ref = 0; + This->pMarshal = NULL; This->filePathName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr+1)); @@ -1329,3 +1341,75 @@ HRESULT WINAPI CreateFileMoniker(LPCOLESTR lpszPathName, LPMONIKER * ppmk) return hr; } + +static HRESULT WINAPI FileMonikerCF_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 FileMonikerCF_AddRef(LPCLASSFACTORY iface) +{ + return 2; /* non-heap based object */ +} + +static ULONG WINAPI FileMonikerCF_Release(LPCLASSFACTORY iface) +{ + return 1; /* non-heap based object */ +} + +static HRESULT WINAPI FileMonikerCF_CreateInstance(LPCLASSFACTORY iface, + LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv) +{ + FileMonikerImpl* newFileMoniker; + 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; + + newFileMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(FileMonikerImpl)); + if (!newFileMoniker) + return E_OUTOFMEMORY; + + hr = FileMonikerImpl_Construct(newFileMoniker, wszEmpty); + + if (SUCCEEDED(hr)) + hr = FileMonikerImpl_QueryInterface((IMoniker*)newFileMoniker, riid, ppv); + if (FAILED(hr)) + HeapFree(GetProcessHeap(),0,newFileMoniker); + + return hr; +} + +static HRESULT WINAPI FileMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock) +{ + FIXME("(%d), stub!\n",fLock); + return S_OK; +} + +static const IClassFactoryVtbl FileMonikerCFVtbl = +{ + FileMonikerCF_QueryInterface, + FileMonikerCF_AddRef, + FileMonikerCF_Release, + FileMonikerCF_CreateInstance, + FileMonikerCF_LockServer +}; +static const IClassFactoryVtbl *FileMonikerCF = &FileMonikerCFVtbl; + +HRESULT FileMonikerCF_Create(REFIID riid, LPVOID *ppv) +{ + return IClassFactory_QueryInterface((IClassFactory *)&FileMonikerCF, riid, ppv); +} diff --git a/dlls/ole32/itemmoniker.c b/dlls/ole32/itemmoniker.c index 4a2b249da13..78ceb67cdee 100644 --- a/dlls/ole32/itemmoniker.c +++ b/dlls/ole32/itemmoniker.c @@ -58,6 +58,7 @@ typedef struct ItemMonikerImpl{ LPOLESTR itemDelimiter; /* Delimiter string */ + IUnknown *pMarshal; /* custom marshaler */ } ItemMonikerImpl; /********************************************************************************/ @@ -175,6 +176,15 @@ HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** 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) @@ -391,6 +401,7 @@ HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDe 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) @@ -419,6 +430,7 @@ 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); @@ -1008,3 +1020,75 @@ HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONI 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); +} diff --git a/dlls/ole32/moniker.c b/dlls/ole32/moniker.c index 45b672648c9..fb2ee6da856 100644 --- a/dlls/ole32/moniker.c +++ b/dlls/ole32/moniker.c @@ -804,3 +804,170 @@ HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(RunObject* TabMoniker, return S_OK; } + + +/* Shared implementation of moniker marshaler based on saving and loading of + * monikers */ + +#define ICOM_THIS_From_IMoniker(class, name) class* This = (class*)(((char*)name)-FIELD_OFFSET(class, lpVtblMarshal)) + +typedef struct MonikerMarshal +{ + const IUnknownVtbl *lpVtbl; + const IMarshalVtbl *lpVtblMarshal; + + ULONG ref; + IMoniker *moniker; +} MonikerMarshal; + +static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv) +{ + MonikerMarshal *This = (MonikerMarshal *)iface; + TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); + *ppv = NULL; + if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid)) + { + *ppv = &This->lpVtblMarshal; + IUnknown_AddRef((IUnknown *)&This->lpVtblMarshal); + return S_OK; + } + FIXME("No interface for %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface) +{ + MonikerMarshal *This = (MonikerMarshal *)iface; + return InterlockedIncrement(&This->ref); +} + +static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface) +{ + MonikerMarshal *This = (MonikerMarshal *)iface; + ULONG ref = InterlockedDecrement(&This->ref); + + if (!ref) HeapFree(GetProcessHeap(), 0, This); + return ref; +} + +static const IUnknownVtbl VT_MonikerMarshalInner = +{ + MonikerMarshalInner_QueryInterface, + MonikerMarshalInner_AddRef, + MonikerMarshalInner_Release +}; + +static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + return IMoniker_QueryInterface(This->moniker, riid, ppv); +} + +static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + return IMoniker_AddRef(This->moniker); +} + +static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + return IMoniker_Release(This->moniker); +} + +static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass( + LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, + void* pvDestContext, DWORD mshlflags, CLSID* pCid) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + + TRACE("(%s, %p, %lx, %p, %lx, %p)\n", debugstr_guid(riid), pv, + dwDestContext, pvDestContext, mshlflags, pCid); + + return IMoniker_GetClassID(This->moniker, pCid); +} + +static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax( + LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext, + void* pvDestContext, DWORD mshlflags, DWORD* pSize) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + HRESULT hr; + ULARGE_INTEGER size; + + TRACE("(%s, %p, %lx, %p, %lx, %p)\n", debugstr_guid(riid), pv, + dwDestContext, pvDestContext, mshlflags, pSize); + + hr = IMoniker_GetSizeMax(This->moniker, &size); + if (hr == S_OK) + *pSize = (DWORD)size.QuadPart; + return hr; +} + +static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm, + REFIID riid, void* pv, DWORD dwDestContext, + void* pvDestContext, DWORD mshlflags) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + + TRACE("(%p, %s, %p, %lx, %p, %lx)\n", pStm, debugstr_guid(riid), pv, + dwDestContext, pvDestContext, mshlflags); + + return IMoniker_Save(This->moniker, pStm, FALSE); +} + +static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv) +{ + ICOM_THIS_From_IMoniker(MonikerMarshal, iface); + HRESULT hr; + + TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv); + + hr = IMoniker_Load(This->moniker, pStm); + if (hr == S_OK) + hr = IMoniker_QueryInterface(This->moniker, riid, ppv); + return hr; +} + +static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm) +{ + TRACE("()\n"); + /* can't release a state-based marshal as nothing on server side to + * release */ + return S_OK; +} + +static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved) +{ + TRACE("()\n"); + /* can't disconnect a state-based marshal as nothing on server side to + * disconnect from */ + return S_OK; +} + +static const IMarshalVtbl VT_MonikerMarshal = +{ + MonikerMarshal_QueryInterface, + MonikerMarshal_AddRef, + MonikerMarshal_Release, + MonikerMarshal_GetUnmarshalClass, + MonikerMarshal_GetMarshalSizeMax, + MonikerMarshal_MarshalInterface, + MonikerMarshal_UnmarshalInterface, + MonikerMarshal_ReleaseMarshalData, + MonikerMarshal_DisconnectObject +}; + +HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer) +{ + MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); + if (!This) return E_OUTOFMEMORY; + + This->lpVtbl = &VT_MonikerMarshalInner; + This->lpVtblMarshal = &VT_MonikerMarshal; + This->ref = 1; + This->moniker = inner; + + *outer = (IUnknown *)&This->lpVtbl; + return S_OK; +} diff --git a/dlls/ole32/moniker.h b/dlls/ole32/moniker.h index 8e4c6ca3ce8..45722fa4ba5 100644 --- a/dlls/ole32/moniker.h +++ b/dlls/ole32/moniker.h @@ -8,4 +8,10 @@ extern const CLSID CLSID_ItemMoniker; extern const CLSID CLSID_AntiMoniker; extern const CLSID CLSID_CompositeMoniker; +HRESULT FileMonikerCF_Create(REFIID riid, LPVOID *ppv); +HRESULT ItemMonikerCF_Create(REFIID riid, LPVOID *ppv); + +HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer); + + #endif /* __WINE_MONIKER_H__ */ diff --git a/dlls/ole32/oleproxy.c b/dlls/ole32/oleproxy.c index 68bf9452315..99fc5f562fc 100644 --- a/dlls/ole32/oleproxy.c +++ b/dlls/ole32/oleproxy.c @@ -57,6 +57,7 @@ #include "wtypes.h" #include "compobj_private.h" +#include "moniker.h" #include "wine/debug.h" @@ -971,10 +972,8 @@ static IPSFactoryBufferVtbl *lppsfac = &psfacbufvtbl; HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) { *ppv = NULL; - if (IsEqualIID(rclsid,&CLSID_PSFactoryBuffer)) { - *ppv = &lppsfac; - return S_OK; - } + if (IsEqualIID(rclsid, &CLSID_PSFactoryBuffer)) + return IPSFactoryBuffer_QueryInterface((IPSFactoryBuffer *)&lppsfac, iid, ppv); if (IsEqualIID(rclsid,&CLSID_DfMarshal)&&( IsEqualIID(iid,&IID_IClassFactory) || IsEqualIID(iid,&IID_IUnknown) @@ -983,6 +982,10 @@ HRESULT WINAPI OLE32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) return MARSHAL_GetStandardMarshalCF(ppv); if (IsEqualIID(rclsid,&CLSID_StdGlobalInterfaceTable) && (IsEqualIID(iid,&IID_IClassFactory) || IsEqualIID(iid,&IID_IUnknown))) return StdGlobalInterfaceTable_GetFactory(ppv); + if (IsEqualCLSID(rclsid, &CLSID_FileMoniker)) + return FileMonikerCF_Create(iid, ppv); + if (IsEqualCLSID(rclsid, &CLSID_ItemMoniker)) + return ItemMonikerCF_Create(iid, ppv); FIXME("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid)); return CLASS_E_CLASSNOTAVAILABLE;