4 * Copyright 1998 Marcus Meissner
5 * Copyright 1999 Noomen Hamza
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * - IRunningObjectTable should work interprocess, but currently doesn't.
23 * Native (on Win2k at least) uses an undocumented RPC interface, IROT, to
24 * communicate with RPCSS which contains the table of marshalled data.
25 * - IRunningObjectTable should use marshalling instead of simple ref
26 * counting as there is the possibility of using the running object table
27 * to access objects in other apartments.
41 #include "wine/debug.h"
44 #include "compobj_private.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(ole);
48 #define BLOCK_TAB_SIZE 20 /* represent the first size table and it's increment block size */
50 /* define the structure of the running object table elements */
51 typedef struct RunObject{
53 IUnknown* pObj; /* points on a running object*/
54 IMoniker* pmkObj; /* points on a moniker who identifies this object */
55 FILETIME lastModifObj;
56 DWORD identRegObj; /* registration key relative to this object */
57 DWORD regTypeObj; /* registration type : strong or weak */
60 /* define the RunningObjectTableImpl structure */
61 typedef struct RunningObjectTableImpl{
63 IRunningObjectTableVtbl *lpVtbl;
66 RunObject* runObjTab; /* pointer to the first object in the table */
67 DWORD runObjTabSize; /* current table size */
68 DWORD runObjTabLastIndx; /* first free index element in the table. */
69 DWORD runObjTabRegister; /* registration key of the next registered object */
71 } RunningObjectTableImpl;
73 static RunningObjectTableImpl* runningObjectTableInstance = NULL;
75 static HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl*,DWORD,IMoniker*,DWORD *);
77 /* define the EnumMonikerImpl structure */
78 typedef struct EnumMonikerImpl{
80 IEnumMonikerVtbl *lpVtbl;
83 RunObject* TabMoniker; /* pointer to the first object in the table */
84 DWORD TabSize; /* current table size */
85 DWORD TabLastIndx; /* last used index element in the table. */
86 DWORD TabCurrentPos; /* enum position in the list */
91 /* IEnumMoniker Local functions*/
92 static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(RunObject* runObjTab,
96 IEnumMoniker ** ppenumMoniker);
97 /***********************************************************************
98 * RunningObjectTable_QueryInterface
100 static HRESULT WINAPI
101 RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,
102 REFIID riid,void** ppvObject)
104 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
106 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
108 /* validate arguments */
110 return CO_E_NOTINITIALIZED;
117 if (IsEqualIID(&IID_IUnknown, riid) ||
118 IsEqualIID(&IID_IRunningObjectTable, riid))
119 *ppvObject = (IRunningObjectTable*)This;
122 return E_NOINTERFACE;
124 IRunningObjectTable_AddRef(iface);
129 /***********************************************************************
130 * RunningObjectTable_AddRef
133 RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
135 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
137 TRACE("(%p)\n",This);
139 return InterlockedIncrement(&This->ref);
142 /***********************************************************************
143 * RunningObjectTable_Initialize
145 static HRESULT WINAPI
146 RunningObjectTableImpl_Destroy(void)
150 if (runningObjectTableInstance==NULL)
153 /* free the ROT table memory */
154 HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab);
156 /* free the ROT structure memory */
157 HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
158 runningObjectTableInstance = NULL;
163 /***********************************************************************
164 * RunningObjectTable_Release
167 RunningObjectTableImpl_Release(IRunningObjectTable* iface)
170 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
173 TRACE("(%p)\n",This);
175 ref = InterlockedDecrement(&This->ref);
177 /* unitialize ROT structure if there's no more reference to it*/
180 /* release all registered objects */
181 for(i=0;i<This->runObjTabLastIndx;i++)
183 if (( This->runObjTab[i].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0)
184 IUnknown_Release(This->runObjTab[i].pObj);
186 IMoniker_Release(This->runObjTab[i].pmkObj);
188 /* RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
189 * when RunningObjectTableImpl_UnInitialize function is called
192 /* there's no more elements in the table */
193 This->runObjTabRegister=0;
194 This->runObjTabLastIndx=0;
200 /***********************************************************************
201 * RunningObjectTable_Register
204 * grfFlags [in] Registration options
205 * punkObject [in] the object being registered
206 * pmkObjectName [in] the moniker of the object being registered
207 * pdwRegister [in] the value identifying the registration
209 static HRESULT WINAPI
210 RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
211 IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister)
214 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
216 TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
219 * there's only two types of register : strong and or weak registration
220 * (only one must be passed on parameter)
222 if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
223 (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
227 if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
230 /* verify if the object to be registered was registered before */
231 if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL)==S_OK)
232 res = MK_S_MONIKERALREADYREGISTERED;
234 /* put the new registered object in the first free element in the table */
235 This->runObjTab[This->runObjTabLastIndx].pObj = punkObject;
236 This->runObjTab[This->runObjTabLastIndx].pmkObj = pmkObjectName;
237 This->runObjTab[This->runObjTabLastIndx].regTypeObj = grfFlags;
238 This->runObjTab[This->runObjTabLastIndx].identRegObj = This->runObjTabRegister;
239 CoFileTimeNow(&(This->runObjTab[This->runObjTabLastIndx].lastModifObj));
241 /* gives a registration identifier to the registered object*/
242 (*pdwRegister)= This->runObjTabRegister;
244 if (This->runObjTabRegister == 0xFFFFFFFF){
246 FIXME("runObjTabRegister: %ld is out of data limite \n",This->runObjTabRegister);
249 This->runObjTabRegister++;
250 This->runObjTabLastIndx++;
252 if (This->runObjTabLastIndx == This->runObjTabSize){ /* table is full ! so it must be resized */
254 This->runObjTabSize+=BLOCK_TAB_SIZE; /* newsize table */
255 This->runObjTab=HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->runObjTab,
256 This->runObjTabSize * sizeof(RunObject));
257 if (!This->runObjTab)
258 return E_OUTOFMEMORY;
260 /* add a reference to the object in the strong registration case */
261 if ((grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) !=0 ) {
262 TRACE("strong registration, reffing %p\n", punkObject);
263 /* this is wrong; we should always add a reference to the object */
264 IUnknown_AddRef(punkObject);
267 IMoniker_AddRef(pmkObjectName);
272 /***********************************************************************
273 * RunningObjectTable_Revoke
276 * dwRegister [in] Value identifying registration to be revoked
278 static HRESULT WINAPI
279 RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister)
283 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
285 TRACE("(%p,%ld)\n",This,dwRegister);
287 /* verify if the object to be revoked was registered before or not */
288 if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
292 /* release the object if it was registered with a strong registrantion option */
293 if ((This->runObjTab[index].regTypeObj & ROTFLAGS_REGISTRATIONKEEPSALIVE)!=0) {
294 TRACE("releasing %p\n", This->runObjTab[index].pObj);
295 /* this is also wrong; we should always release the object (see above) */
296 IUnknown_Release(This->runObjTab[index].pObj);
299 IMoniker_Release(This->runObjTab[index].pmkObj);
301 /* remove the object from the table */
302 for(j=index; j<This->runObjTabLastIndx-1; j++)
303 This->runObjTab[j]= This->runObjTab[j+1];
305 This->runObjTabLastIndx--;
310 /***********************************************************************
311 * RunningObjectTable_IsRunning
314 * pmkObjectName [in] moniker of the object whose status is desired
316 static HRESULT WINAPI
317 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName)
319 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
321 TRACE("(%p,%p)\n",This,pmkObjectName);
323 return RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL);
326 /***********************************************************************
327 * RunningObjectTable_GetObject
330 * pmkObjectName [in] Pointer to the moniker on the object
331 * ppunkObject [out] variable that receives the IUnknown interface pointer
333 static HRESULT WINAPI
334 RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
335 IMoniker *pmkObjectName, IUnknown **ppunkObject)
338 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
340 TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
342 if (ppunkObject==NULL)
347 /* verify if the object was registered before or not */
348 if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE) {
349 WARN("Moniker unavailable - needs to work interprocess?\n");
350 return MK_E_UNAVAILABLE;
353 /* add a reference to the object then set output object argument */
354 IUnknown_AddRef(This->runObjTab[index].pObj);
355 *ppunkObject=This->runObjTab[index].pObj;
360 /***********************************************************************
361 * RunningObjectTable_NoteChangeTime
364 * dwRegister [in] Value identifying registration being updated
365 * pfiletime [in] Pointer to structure containing object's last change time
367 static HRESULT WINAPI
368 RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
369 DWORD dwRegister, FILETIME *pfiletime)
372 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
374 TRACE("(%p,%ld,%p)\n",This,dwRegister,pfiletime);
376 /* verify if the object to be changed was registered before or not */
377 if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
380 /* set the new value of the last time change */
381 This->runObjTab[index].lastModifObj= (*pfiletime);
386 /***********************************************************************
387 * RunningObjectTable_GetTimeOfLastChange
390 * pmkObjectName [in] moniker of the object whose status is desired
391 * pfiletime [out] structure that receives object's last change time
393 static HRESULT WINAPI
394 RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
395 IMoniker *pmkObjectName, FILETIME *pfiletime)
398 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
400 TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
402 if (pmkObjectName==NULL || pfiletime==NULL)
405 /* verify if the object was registered before or not */
406 if (RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,&index)==S_FALSE)
407 return MK_E_UNAVAILABLE;
409 (*pfiletime)= This->runObjTab[index].lastModifObj;
414 /***********************************************************************
415 * RunningObjectTable_EnumRunning
418 * ppenumMoniker [out] receives the IEnumMoniker interface pointer
420 static HRESULT WINAPI
421 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
422 IEnumMoniker **ppenumMoniker)
424 /* create the unique instance of the EnumMonkikerImpl structure
425 * and copy the Monikers referenced in the ROT so that they can be
426 * enumerated by the Enum interface
429 RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
431 rc=EnumMonikerImpl_CreateEnumROTMoniker(This->runObjTab,
433 This->runObjTabLastIndx, 0,
438 /***********************************************************************
441 static HRESULT WINAPI
442 RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,
443 DWORD identReg, IMoniker* pmk, DWORD *indx)
448 TRACE("(%p,%ld,%p,%p)\n",This,identReg,pmk,indx);
451 /* search object identified by a moniker */
452 for(i=0 ; (i < This->runObjTabLastIndx) &&(!IMoniker_IsEqual(This->runObjTab[i].pmkObj,pmk)==S_OK);i++);
454 /* search object identified by a register identifier */
455 for(i=0;((i<This->runObjTabLastIndx)&&(This->runObjTab[i].identRegObj!=identReg));i++);
457 if (i==This->runObjTabLastIndx) return S_FALSE;
459 if (indx != NULL) *indx=i;
464 /******************************************************************************
465 * GetRunningObjectTable (OLE2.30)
468 GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
470 FIXME("(%ld,%p),stub!\n",reserved,pprot);
474 /***********************************************************************
475 * GetRunningObjectTable (OLE32.@)
478 GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
480 IID riid=IID_IRunningObjectTable;
488 if(runningObjectTableInstance==NULL)
489 return CO_E_NOTINITIALIZED;
491 res = IRunningObjectTable_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot);
496 /******************************************************************************
499 HRESULT WINAPI OleRun(LPUNKNOWN pUnknown)
501 IRunnableObject *runable;
502 IRunnableObject *This = (IRunnableObject *)pUnknown;
505 ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable);
507 return 0; /* Appears to return no error. */
508 ret = IRunnableObject_Run(runable,NULL);
509 IRunnableObject_Release(runable);
513 /******************************************************************************
514 * MkParseDisplayName [OLE32.@]
516 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
517 LPDWORD pchEaten, LPMONIKER *ppmk)
519 FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk);
521 if (!(IsValidInterface((LPUNKNOWN) pbc)))
527 /******************************************************************************
528 * CreateClassMoniker [OLE32.@]
530 HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker ** ppmk)
532 FIXME("%s\n", debugstr_guid( rclsid ));
538 /* Virtual function table for the IRunningObjectTable class. */
539 static IRunningObjectTableVtbl VT_RunningObjectTableImpl =
541 RunningObjectTableImpl_QueryInterface,
542 RunningObjectTableImpl_AddRef,
543 RunningObjectTableImpl_Release,
544 RunningObjectTableImpl_Register,
545 RunningObjectTableImpl_Revoke,
546 RunningObjectTableImpl_IsRunning,
547 RunningObjectTableImpl_GetObject,
548 RunningObjectTableImpl_NoteChangeTime,
549 RunningObjectTableImpl_GetTimeOfLastChange,
550 RunningObjectTableImpl_EnumRunning
553 /***********************************************************************
554 * RunningObjectTable_Initialize
556 HRESULT WINAPI RunningObjectTableImpl_Initialize(void)
560 /* create the unique instance of the RunningObjectTableImpl structure */
561 runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));
563 if (runningObjectTableInstance == 0)
564 return E_OUTOFMEMORY;
566 /* initialize the virtual table function */
567 runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl;
569 /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */
570 /* the ROT referred many times not in the same time (all the objects in the ROT will */
571 /* be removed every time the ROT is removed ) */
572 runningObjectTableInstance->ref = 1;
574 /* allocate space memory for the table which contains all the running objects */
575 runningObjectTableInstance->runObjTab = HeapAlloc(GetProcessHeap(), 0, sizeof(RunObject[BLOCK_TAB_SIZE]));
577 if (runningObjectTableInstance->runObjTab == NULL)
578 return E_OUTOFMEMORY;
580 runningObjectTableInstance->runObjTabSize=BLOCK_TAB_SIZE;
581 runningObjectTableInstance->runObjTabRegister=1;
582 runningObjectTableInstance->runObjTabLastIndx=0;
587 /***********************************************************************
588 * RunningObjectTable_UnInitialize
590 HRESULT WINAPI RunningObjectTableImpl_UnInitialize()
594 if (runningObjectTableInstance==NULL)
597 RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance);
599 RunningObjectTableImpl_Destroy();
604 /***********************************************************************
605 * EnumMoniker_QueryInterface
607 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
609 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
611 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
613 /* validate arguments */
614 if (ppvObject == NULL)
619 if (IsEqualIID(&IID_IUnknown, riid))
620 *ppvObject = (IEnumMoniker*)This;
622 if (IsEqualIID(&IID_IEnumMoniker, riid))
623 *ppvObject = (IEnumMoniker*)This;
625 if ((*ppvObject)==NULL)
626 return E_NOINTERFACE;
628 IEnumMoniker_AddRef(iface);
633 /***********************************************************************
636 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
638 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
640 TRACE("(%p)\n",This);
642 return InterlockedIncrement(&This->ref);
645 /***********************************************************************
646 * EnumMoniker_release
648 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
651 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
654 TRACE("(%p)\n",This);
656 ref = InterlockedDecrement(&This->ref);
658 /* unitialize rot structure if there's no more reference to it*/
661 /* release all registered objects in Moniker list */
662 for(i=0; i < This->TabLastIndx ;i++)
664 IMoniker_Release(This->TabMoniker[i].pmkObj);
667 /* there're no more elements in the table */
669 TRACE("(%p) Deleting\n",This);
670 HeapFree (GetProcessHeap(), 0, This->TabMoniker); /* free Moniker list */
671 HeapFree (GetProcessHeap(), 0, This); /* free Enum Instance */
677 /***********************************************************************
680 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched)
683 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
684 TRACE("(%p) TabCurrentPos %ld Tablastindx %ld\n",This, This->TabCurrentPos, This->TabLastIndx);
686 /* retrieve the requested number of moniker from the current position */
687 for(i=0; (This->TabCurrentPos < This->TabLastIndx) && (i < celt); i++)
688 rgelt[i]=(IMoniker*)This->TabMoniker[This->TabCurrentPos++].pmkObj;
690 if (pceltFetched!=NULL)
700 /***********************************************************************
703 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt)
705 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
707 TRACE("(%p)\n",This);
709 if (This->TabCurrentPos+celt >= This->TabLastIndx)
712 This->TabCurrentPos+=celt;
717 /***********************************************************************
720 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
722 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
724 This->TabCurrentPos = 0; /* set back to start of list */
726 TRACE("(%p)\n",This);
731 /***********************************************************************
734 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)
736 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
738 TRACE("(%p)\n",This);
739 /* copy the enum structure */
740 return EnumMonikerImpl_CreateEnumROTMoniker(This->TabMoniker, This->TabSize,
741 This->TabLastIndx, This->TabCurrentPos,
745 /* Virtual function table for the IEnumMoniker class. */
746 static IEnumMonikerVtbl VT_EnumMonikerImpl =
748 EnumMonikerImpl_QueryInterface,
749 EnumMonikerImpl_AddRef,
750 EnumMonikerImpl_Release,
751 EnumMonikerImpl_Next,
752 EnumMonikerImpl_Skip,
753 EnumMonikerImpl_Reset,
754 EnumMonikerImpl_Clone
757 /***********************************************************************
758 * EnumMonikerImpl_CreateEnumROTMoniker
759 * Used by EnumRunning to create the structure and EnumClone
760 * to copy the structure
762 HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(RunObject* TabMoniker,
766 IEnumMoniker ** ppenumMoniker)
769 EnumMonikerImpl* This = NULL;
771 if (TabCurrentPos > TabSize)
774 if (ppenumMoniker == NULL)
777 This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
779 if (!ppenumMoniker) return E_OUTOFMEMORY;
781 TRACE("(%p)\n", This);
783 /* initialize the virtual table function */
784 This->lpVtbl = &VT_EnumMonikerImpl;
786 /* the initial reference is set to "1" */
787 This->ref = 1; /* set the ref count to one */
788 This->TabCurrentPos=0; /* Set the list start posn to start */
789 This->TabSize=TabSize; /* Need the same size table as ROT */
790 This->TabLastIndx=TabLastIndx; /* end element */
791 This->TabMoniker=HeapAlloc(GetProcessHeap(),0,This->TabSize*sizeof(RunObject));
793 if (This->TabMoniker==NULL) {
794 HeapFree(GetProcessHeap(), 0, This);
795 return E_OUTOFMEMORY;
797 for (i=0; i < This->TabLastIndx; i++){
799 This->TabMoniker[i]=TabMoniker[i];
800 IMoniker_AddRef(TabMoniker[i].pmkObj);
803 *ppenumMoniker = (IEnumMoniker*)This;