winegstreamer: Move the "flip" field to struct wg_parser_stream.
[wine/zf.git] / dlls / ole32 / pointermoniker.c
blob34692c4965b9b87a6d7fbb3151640caf9e2bef0e
1 /*
2 * Pointer Moniker Implementation
4 * Copyright 1999 Noomen Hamza
5 * Copyright 2008 Robert Shearman (for CodeWeavers)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
23 #include <string.h>
25 #define COBJMACROS
26 #define NONAMELESSUNION
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winerror.h"
31 #include "winuser.h"
32 #include "objbase.h"
33 #include "oleidl.h"
34 #include "wine/debug.h"
35 #include "wine/heap.h"
36 #include "moniker.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40 /* PointerMoniker data structure */
41 typedef struct PointerMonikerImpl
43 IMoniker IMoniker_iface;
44 IMarshal IMarshal_iface;
46 LONG refcount;
48 IUnknown *pObject;
49 } PointerMonikerImpl;
51 static inline PointerMonikerImpl *impl_from_IMoniker(IMoniker *iface)
53 return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface);
56 static PointerMonikerImpl *impl_from_IMarshal(IMarshal *iface)
58 return CONTAINING_RECORD(iface, PointerMonikerImpl, IMarshal_iface);
61 static PointerMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface);
63 static HRESULT WINAPI PointerMonikerImpl_QueryInterface(IMoniker *iface, REFIID riid, void **ppvObject)
65 PointerMonikerImpl *moniker = impl_from_IMoniker(iface);
67 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), ppvObject);
69 if (!ppvObject)
70 return E_INVALIDARG;
72 *ppvObject = 0;
74 if (IsEqualIID(&IID_IUnknown, riid) ||
75 IsEqualIID(&IID_IPersist, riid) ||
76 IsEqualIID(&IID_IPersistStream, riid) ||
77 IsEqualIID(&IID_IMoniker, riid) ||
78 IsEqualGUID(&CLSID_PointerMoniker, riid))
80 *ppvObject = iface;
82 else if (IsEqualIID(&IID_IMarshal, riid))
83 *ppvObject = &moniker->IMarshal_iface;
85 if (!*ppvObject)
86 return E_NOINTERFACE;
88 IMoniker_AddRef(iface);
90 return S_OK;
93 static ULONG WINAPI PointerMonikerImpl_AddRef(IMoniker *iface)
95 PointerMonikerImpl *moniker = impl_from_IMoniker(iface);
96 ULONG refcount = InterlockedIncrement(&moniker->refcount);
98 TRACE("%p, refcount %u.\n", iface, refcount);
100 return refcount;
103 static ULONG WINAPI PointerMonikerImpl_Release(IMoniker *iface)
105 PointerMonikerImpl *moniker = impl_from_IMoniker(iface);
106 ULONG refcount = InterlockedDecrement(&moniker->refcount);
108 TRACE("%p, refcount %u.\n", iface, refcount);
110 if (!refcount)
112 if (moniker->pObject) IUnknown_Release(moniker->pObject);
113 heap_free(moniker);
116 return refcount;
119 /******************************************************************************
120 * PointerMoniker_GetClassID
121 ******************************************************************************/
122 static HRESULT WINAPI
123 PointerMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
125 TRACE("(%p,%p)\n",iface,pClassID);
127 if (pClassID==NULL)
128 return E_POINTER;
130 *pClassID = CLSID_PointerMoniker;
132 return S_OK;
135 /******************************************************************************
136 * PointerMoniker_IsDirty
137 ******************************************************************************/
138 static HRESULT WINAPI
139 PointerMonikerImpl_IsDirty(IMoniker* iface)
141 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
142 method in the OLE-provided moniker interfaces always return S_FALSE because
143 their internal state never changes. */
145 TRACE("(%p)\n",iface);
147 return S_FALSE;
150 /******************************************************************************
151 * PointerMoniker_Load
152 ******************************************************************************/
153 static HRESULT WINAPI
154 PointerMonikerImpl_Load(IMoniker* iface,IStream* pStm)
156 TRACE("(%p)\n", pStm);
158 return E_NOTIMPL;
161 /******************************************************************************
162 * PointerMoniker_Save
163 ******************************************************************************/
164 static HRESULT WINAPI
165 PointerMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
167 TRACE("(%p, %d)\n", pStm, fClearDirty);
169 return E_NOTIMPL;
172 /******************************************************************************
173 * PointerMoniker_GetSizeMax
175 * PARAMS
176 * pcbSize [out] Pointer to size of stream needed to save object
177 ******************************************************************************/
178 static HRESULT WINAPI
179 PointerMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
181 TRACE("(%p,%p)\n",iface,pcbSize);
183 if (!pcbSize)
184 return E_POINTER;
186 pcbSize->u.LowPart = 0;
187 pcbSize->u.HighPart = 0;
189 return E_NOTIMPL;
192 /******************************************************************************
193 * PointerMoniker_BindToObject
194 ******************************************************************************/
195 static HRESULT WINAPI
196 PointerMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
197 REFIID riid, VOID** ppvResult)
199 PointerMonikerImpl *This = impl_from_IMoniker(iface);
201 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
203 if (!This->pObject)
204 return E_UNEXPECTED;
206 return IUnknown_QueryInterface(This->pObject, riid, ppvResult);
209 /******************************************************************************
210 * PointerMoniker_BindToStorage
211 ******************************************************************************/
212 static HRESULT WINAPI
213 PointerMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
214 REFIID riid, VOID** ppvResult)
216 PointerMonikerImpl *This = impl_from_IMoniker(iface);
218 TRACE("(%p,%p,%p,%s,%p)\n",iface,pbc,pmkToLeft,debugstr_guid(riid),ppvResult);
220 if (!This->pObject)
221 return E_UNEXPECTED;
223 return IUnknown_QueryInterface(This->pObject, riid, ppvResult);
226 /******************************************************************************
227 * PointerMoniker_Reduce
228 ******************************************************************************/
229 static HRESULT WINAPI
230 PointerMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
231 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
233 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
235 if (ppmkReduced==NULL)
236 return E_POINTER;
238 PointerMonikerImpl_AddRef(iface);
240 *ppmkReduced=iface;
242 return MK_S_REDUCED_TO_SELF;
244 /******************************************************************************
245 * PointerMoniker_ComposeWith
246 ******************************************************************************/
247 static HRESULT WINAPI
248 PointerMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
249 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
252 HRESULT res=S_OK;
253 DWORD mkSys,mkSys2, order;
254 IEnumMoniker* penumMk=0;
255 IMoniker *pmostLeftMk=0;
256 IMoniker* tempMkComposite=0;
258 TRACE("(%p,%d,%p)\n", pmkRight, fOnlyIfNotGeneric, ppmkComposite);
260 if ((ppmkComposite==NULL)||(pmkRight==NULL))
261 return E_POINTER;
263 *ppmkComposite=0;
265 if (is_anti_moniker(pmkRight, &order))
267 return order > 1 ? create_anti_moniker(order - 1, ppmkComposite) : S_OK;
269 else
271 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
272 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
273 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
275 if(mkSys==MKSYS_GENERICCOMPOSITE){
277 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
279 if (FAILED(res))
280 return res;
282 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
284 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
286 if(mkSys2==MKSYS_ANTIMONIKER){
288 IMoniker_Release(pmostLeftMk);
290 tempMkComposite=iface;
291 IMoniker_AddRef(iface);
293 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
295 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
297 IMoniker_Release(tempMkComposite);
298 IMoniker_Release(pmostLeftMk);
300 tempMkComposite=*ppmkComposite;
301 IMoniker_AddRef(tempMkComposite);
303 return res;
305 else
306 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
308 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
309 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
310 a NULL moniker and a return value of MK_E_NEEDGENERIC */
311 else
312 if (!fOnlyIfNotGeneric)
313 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
315 else
316 return MK_E_NEEDGENERIC;
320 /******************************************************************************
321 * PointerMoniker_Enum
322 ******************************************************************************/
323 static HRESULT WINAPI PointerMonikerImpl_Enum(IMoniker *iface, BOOL fForward, IEnumMoniker **ppenumMoniker)
325 TRACE("%p, %d, %p.\n", iface, fForward, ppenumMoniker);
327 if (!ppenumMoniker)
328 return E_POINTER;
330 *ppenumMoniker = NULL;
332 return E_NOTIMPL;
335 /******************************************************************************
336 * PointerMoniker_IsEqual
337 ******************************************************************************/
338 static HRESULT WINAPI PointerMonikerImpl_IsEqual(IMoniker *iface, IMoniker *other)
340 PointerMonikerImpl *moniker = impl_from_IMoniker(iface), *other_moniker;
342 TRACE("%p, %p.\n", iface, other);
344 if (!other)
345 return E_INVALIDARG;
347 other_moniker = unsafe_impl_from_IMoniker(other);
348 if (!other_moniker)
349 return S_FALSE;
351 return moniker->pObject == other_moniker->pObject ? S_OK : S_FALSE;
354 /******************************************************************************
355 * PointerMoniker_Hash
356 ******************************************************************************/
357 static HRESULT WINAPI PointerMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
359 PointerMonikerImpl *This = impl_from_IMoniker(iface);
361 if (pdwHash==NULL)
362 return E_POINTER;
364 *pdwHash = PtrToUlong(This->pObject);
366 return S_OK;
369 /******************************************************************************
370 * PointerMoniker_IsRunning
371 ******************************************************************************/
372 static HRESULT WINAPI
373 PointerMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
374 IMoniker* pmkNewlyRunning)
376 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
378 return S_OK;
381 /******************************************************************************
382 * PointerMoniker_GetTimeOfLastChange
383 ******************************************************************************/
384 static HRESULT WINAPI PointerMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
385 IBindCtx* pbc,
386 IMoniker* pmkToLeft,
387 FILETIME* pAntiTime)
389 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime);
390 return E_NOTIMPL;
393 /******************************************************************************
394 * PointerMoniker_Inverse
395 ******************************************************************************/
396 static HRESULT WINAPI
397 PointerMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
399 TRACE("(%p,%p)\n",iface,ppmk);
401 return CreateAntiMoniker(ppmk);
404 /******************************************************************************
405 * PointerMoniker_CommonPrefixWith
406 ******************************************************************************/
407 static HRESULT WINAPI PointerMonikerImpl_CommonPrefixWith(IMoniker *iface, IMoniker *other, IMoniker **prefix)
409 TRACE("%p, %p, %p.\n", iface, other, prefix);
411 if (!prefix || !other)
412 return E_INVALIDARG;
414 *prefix = NULL;
416 if (PointerMonikerImpl_IsEqual(iface, other) == S_OK)
418 IMoniker_AddRef(iface);
420 *prefix = iface;
422 return MK_S_US;
424 else
425 return MK_E_NOPREFIX;
428 /******************************************************************************
429 * PointerMoniker_RelativePathTo
430 ******************************************************************************/
431 static HRESULT WINAPI
432 PointerMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
434 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
436 if (ppmkRelPath==NULL)
437 return E_POINTER;
439 *ppmkRelPath = NULL;
441 return E_NOTIMPL;
444 /******************************************************************************
445 * PointerMoniker_GetDisplayName
446 ******************************************************************************/
447 static HRESULT WINAPI
448 PointerMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
449 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
451 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
453 if (ppszDisplayName==NULL)
454 return E_POINTER;
456 *ppszDisplayName = NULL;
457 return E_NOTIMPL;
460 /******************************************************************************
461 * PointerMoniker_ParseDisplayName
462 ******************************************************************************/
463 static HRESULT WINAPI
464 PointerMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
465 IMoniker* pmkToLeft, LPOLESTR pszDisplayName,
466 ULONG* pchEaten, IMoniker** ppmkOut)
468 PointerMonikerImpl *This = impl_from_IMoniker(iface);
469 HRESULT hr;
470 IParseDisplayName *pPDN;
472 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
474 if (pmkToLeft)
475 return MK_E_SYNTAX;
477 if (!This->pObject)
478 return E_UNEXPECTED;
480 hr = IUnknown_QueryInterface(This->pObject, &IID_IParseDisplayName, (void **)&pPDN);
481 if (FAILED(hr))
482 return hr;
484 hr = IParseDisplayName_ParseDisplayName(pPDN, pbc, pszDisplayName, pchEaten, ppmkOut);
485 IParseDisplayName_Release(pPDN);
487 return hr;
490 /******************************************************************************
491 * PointerMoniker_IsSystemMoniker
492 ******************************************************************************/
493 static HRESULT WINAPI
494 PointerMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
496 TRACE("(%p,%p)\n",iface,pwdMksys);
498 if (!pwdMksys)
499 return E_POINTER;
501 *pwdMksys = MKSYS_POINTERMONIKER;
503 return S_OK;
506 /********************************************************************************/
507 /* Virtual function table for the PointerMonikerImpl class which include IPersist,*/
508 /* IPersistStream and IMoniker functions. */
509 static const IMonikerVtbl VT_PointerMonikerImpl =
511 PointerMonikerImpl_QueryInterface,
512 PointerMonikerImpl_AddRef,
513 PointerMonikerImpl_Release,
514 PointerMonikerImpl_GetClassID,
515 PointerMonikerImpl_IsDirty,
516 PointerMonikerImpl_Load,
517 PointerMonikerImpl_Save,
518 PointerMonikerImpl_GetSizeMax,
519 PointerMonikerImpl_BindToObject,
520 PointerMonikerImpl_BindToStorage,
521 PointerMonikerImpl_Reduce,
522 PointerMonikerImpl_ComposeWith,
523 PointerMonikerImpl_Enum,
524 PointerMonikerImpl_IsEqual,
525 PointerMonikerImpl_Hash,
526 PointerMonikerImpl_IsRunning,
527 PointerMonikerImpl_GetTimeOfLastChange,
528 PointerMonikerImpl_Inverse,
529 PointerMonikerImpl_CommonPrefixWith,
530 PointerMonikerImpl_RelativePathTo,
531 PointerMonikerImpl_GetDisplayName,
532 PointerMonikerImpl_ParseDisplayName,
533 PointerMonikerImpl_IsSystemMoniker
536 static PointerMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface)
538 if (iface->lpVtbl != &VT_PointerMonikerImpl)
539 return NULL;
540 return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface);
543 static HRESULT WINAPI pointer_moniker_marshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
545 PointerMonikerImpl *moniker = impl_from_IMarshal(iface);
547 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), ppv);
549 return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppv);
552 static ULONG WINAPI pointer_moniker_marshal_AddRef(IMarshal *iface)
554 PointerMonikerImpl *moniker = impl_from_IMarshal(iface);
556 TRACE("%p.\n",iface);
558 return IMoniker_AddRef(&moniker->IMoniker_iface);
561 static ULONG WINAPI pointer_moniker_marshal_Release(IMarshal *iface)
563 PointerMonikerImpl *moniker = impl_from_IMarshal(iface);
565 TRACE("%p.\n",iface);
567 return IMoniker_Release(&moniker->IMoniker_iface);
570 static HRESULT WINAPI pointer_moniker_marshal_GetUnmarshalClass(IMarshal *iface, REFIID riid, void *pv,
571 DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
573 PointerMonikerImpl *moniker = impl_from_IMarshal(iface);
575 TRACE("%p, %s, %p, %x, %p, %x, %p.\n", iface, debugstr_guid(riid), pv, dwDestContext, pvDestContext,
576 mshlflags, clsid);
578 return IMoniker_GetClassID(&moniker->IMoniker_iface, clsid);
581 static HRESULT WINAPI pointer_moniker_marshal_GetMarshalSizeMax(IMarshal *iface, REFIID riid, void *pv,
582 DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size)
584 PointerMonikerImpl *moniker = impl_from_IMarshal(iface);
586 TRACE("%p, %s, %p, %d, %p, %#x, %p.\n", iface, debugstr_guid(riid), pv, dwDestContext, pvDestContext,
587 mshlflags, size);
589 return CoGetMarshalSizeMax(size, &IID_IUnknown, moniker->pObject, dwDestContext, pvDestContext, mshlflags);
592 static HRESULT WINAPI pointer_moniker_marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID riid,
593 void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
595 PointerMonikerImpl *moniker = impl_from_IMarshal(iface);
597 TRACE("%p, %s, %p, %x, %p, %x.\n", stream, debugstr_guid(riid), pv,
598 dwDestContext, pvDestContext, mshlflags);
600 return CoMarshalInterface(stream, &IID_IUnknown, moniker->pObject, dwDestContext,
601 pvDestContext, mshlflags);
604 static HRESULT WINAPI pointer_moniker_marshal_UnmarshalInterface(IMarshal *iface, IStream *stream,
605 REFIID riid, void **ppv)
607 PointerMonikerImpl *moniker = impl_from_IMarshal(iface);
608 IUnknown *object;
609 HRESULT hr;
611 TRACE("%p, %p, %s, %p.\n", iface, stream, debugstr_guid(riid), ppv);
613 hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void **)&object);
614 if (FAILED(hr))
616 ERR("Couldn't unmarshal moniker, hr = %#x.\n", hr);
617 return hr;
620 if (moniker->pObject)
621 IUnknown_Release(moniker->pObject);
622 moniker->pObject = object;
624 return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppv);
627 static HRESULT WINAPI pointer_moniker_marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
629 TRACE("%p, %p.\n", iface, stream);
631 return S_OK;
634 static HRESULT WINAPI pointer_moniker_marshal_DisconnectObject(IMarshal *iface, DWORD reserved)
636 TRACE("%p, %#x.\n", iface, reserved);
638 return S_OK;
641 static const IMarshalVtbl pointer_moniker_marshal_vtbl =
643 pointer_moniker_marshal_QueryInterface,
644 pointer_moniker_marshal_AddRef,
645 pointer_moniker_marshal_Release,
646 pointer_moniker_marshal_GetUnmarshalClass,
647 pointer_moniker_marshal_GetMarshalSizeMax,
648 pointer_moniker_marshal_MarshalInterface,
649 pointer_moniker_marshal_UnmarshalInterface,
650 pointer_moniker_marshal_ReleaseMarshalData,
651 pointer_moniker_marshal_DisconnectObject
654 /***********************************************************************
655 * CreatePointerMoniker (OLE32.@)
657 HRESULT WINAPI CreatePointerMoniker(IUnknown *object, IMoniker **ret)
659 PointerMonikerImpl *moniker;
661 TRACE("(%p, %p)\n", object, ret);
663 if (!ret)
664 return E_INVALIDARG;
666 moniker = heap_alloc(sizeof(*moniker));
667 if (!moniker)
669 *ret = NULL;
670 return E_OUTOFMEMORY;
673 moniker->IMoniker_iface.lpVtbl = &VT_PointerMonikerImpl;
674 moniker->IMarshal_iface.lpVtbl = &pointer_moniker_marshal_vtbl;
675 moniker->refcount = 1;
676 moniker->pObject = object;
677 if (moniker->pObject)
678 IUnknown_AddRef(moniker->pObject);
680 *ret = &moniker->IMoniker_iface;
682 return S_OK;
685 HRESULT WINAPI PointerMoniker_CreateInstance(IClassFactory *iface,
686 IUnknown *pUnk, REFIID riid, void **ppv)
688 IMoniker *pMoniker;
689 HRESULT hr;
691 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
693 *ppv = NULL;
695 if (pUnk)
696 return CLASS_E_NOAGGREGATION;
698 hr = CreatePointerMoniker(NULL, &pMoniker);
699 if (FAILED(hr))
700 return hr;
702 hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
703 IMoniker_Release(pMoniker);
705 return hr;