Remove LOCAL_*() calls from USER, use Local*16() instead.
[wine] / dlls / ole32 / moniker.c
1 /*
2  *      Monikers
3  *
4  *      Copyright 1998  Marcus Meissner
5  *      Copyright 1999  Noomen Hamza
6  *
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.
11  *
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.
16  *
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
20  *
21  * TODO:
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.
28  */
29
30 #include <assert.h>
31 #include <stdarg.h>
32 #include <string.h>
33
34 #define COBJMACROS
35
36 #include "winerror.h"
37 #include "windef.h"
38 #include "winbase.h"
39 #include "winuser.h"
40 #include "wtypes.h"
41 #include "wine/debug.h"
42 #include "ole2.h"
43
44 #include "compobj_private.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(ole);
47
48 #define  BLOCK_TAB_SIZE 20 /* represent the first size table and it's increment block size */
49
50 /* define the structure of the running object table elements */
51 typedef struct RunObject{
52
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 */
58 }RunObject;
59
60 /* define the RunningObjectTableImpl structure */
61 typedef struct RunningObjectTableImpl{
62
63     IRunningObjectTableVtbl *lpVtbl;
64     ULONG      ref;
65
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 */
70
71 } RunningObjectTableImpl;
72
73 static RunningObjectTableImpl* runningObjectTableInstance = NULL;
74
75 static HRESULT WINAPI RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl*,DWORD,IMoniker*,DWORD *);
76
77 /* define the EnumMonikerImpl structure */
78 typedef struct EnumMonikerImpl{
79
80     IEnumMonikerVtbl *lpVtbl;
81     ULONG      ref;
82
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                   */
87
88 } EnumMonikerImpl;
89
90
91 /* IEnumMoniker Local functions*/
92 static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(RunObject* runObjTab,
93                                                  ULONG TabSize,
94                                                  ULONG TabLastIndx,
95                                                  ULONG TabCurrentPos,
96                                                  IEnumMoniker ** ppenumMoniker);
97 /***********************************************************************
98  *        RunningObjectTable_QueryInterface
99  */
100 static HRESULT WINAPI
101 RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,
102                                       REFIID riid,void** ppvObject)
103 {
104     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
105
106     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
107
108     /* validate arguments */
109     if (This==0)
110         return CO_E_NOTINITIALIZED;
111
112     if (ppvObject==0)
113         return E_INVALIDARG;
114
115     *ppvObject = 0;
116
117     if (IsEqualIID(&IID_IUnknown, riid) ||
118         IsEqualIID(&IID_IRunningObjectTable, riid))
119         *ppvObject = (IRunningObjectTable*)This;
120
121     if ((*ppvObject)==0)
122         return E_NOINTERFACE;
123
124     IRunningObjectTable_AddRef(iface);
125
126     return S_OK;
127 }
128
129 /***********************************************************************
130  *        RunningObjectTable_AddRef
131  */
132 static ULONG WINAPI
133 RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
134 {
135     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
136
137     TRACE("(%p)\n",This);
138
139     return InterlockedIncrement(&This->ref);
140 }
141
142 /***********************************************************************
143  *        RunningObjectTable_Initialize
144  */
145 static HRESULT WINAPI
146 RunningObjectTableImpl_Destroy(void)
147 {
148     TRACE("()\n");
149
150     if (runningObjectTableInstance==NULL)
151         return E_INVALIDARG;
152
153     /* free the ROT table memory */
154     HeapFree(GetProcessHeap(),0,runningObjectTableInstance->runObjTab);
155
156     /* free the ROT structure memory */
157     HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
158     runningObjectTableInstance = NULL;
159
160     return S_OK;
161 }
162
163 /***********************************************************************
164  *        RunningObjectTable_Release
165  */
166 static ULONG WINAPI
167 RunningObjectTableImpl_Release(IRunningObjectTable* iface)
168 {
169     DWORD i;
170     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
171     ULONG ref;
172
173     TRACE("(%p)\n",This);
174
175     ref = InterlockedDecrement(&This->ref);
176
177     /* unitialize ROT structure if there's no more reference to it*/
178     if (ref == 0) {
179
180         /* release all registered objects */
181         for(i=0;i<This->runObjTabLastIndx;i++)
182         {
183             if (( This->runObjTab[i].regTypeObj &  ROTFLAGS_REGISTRATIONKEEPSALIVE) != 0)
184                 IUnknown_Release(This->runObjTab[i].pObj);
185
186             IMoniker_Release(This->runObjTab[i].pmkObj);
187         }
188        /*  RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
189         *  when RunningObjectTableImpl_UnInitialize function is called
190         */
191
192         /* there's no more elements in the table */
193         This->runObjTabRegister=0;
194         This->runObjTabLastIndx=0;
195     }
196
197     return ref;
198 }
199
200 /***********************************************************************
201  *        RunningObjectTable_Register
202  *
203  * PARAMS
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
208  */
209 static HRESULT WINAPI
210 RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
211                IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister)
212 {
213     HRESULT res=S_OK;
214     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
215
216     TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
217
218     /*
219      * there's only two types of register : strong and or weak registration
220      * (only one must be passed on parameter)
221      */
222     if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
223          (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ||  (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
224          (grfFlags) )
225         return E_INVALIDARG;
226
227     if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
228         return E_INVALIDARG;
229
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;
233
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));
240
241     /* gives a registration identifier to the registered object*/
242     (*pdwRegister)= This->runObjTabRegister;
243
244     if (This->runObjTabRegister == 0xFFFFFFFF){
245
246         FIXME("runObjTabRegister: %ld is out of data limite \n",This->runObjTabRegister);
247         return E_FAIL;
248     }
249     This->runObjTabRegister++;
250     This->runObjTabLastIndx++;
251
252     if (This->runObjTabLastIndx == This->runObjTabSize){ /* table is full ! so it must be resized */
253
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;
259     }
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);
265     }
266     
267     IMoniker_AddRef(pmkObjectName);
268
269     return res;
270 }
271
272 /***********************************************************************
273  *        RunningObjectTable_Revoke
274  *
275  * PARAMS
276  *  dwRegister [in] Value identifying registration to be revoked
277  */
278 static HRESULT WINAPI
279 RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister) 
280 {
281
282     DWORD index,j;
283     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
284
285     TRACE("(%p,%ld)\n",This,dwRegister);
286
287     /* verify if the object to be revoked was registered before or not */
288     if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
289
290         return E_INVALIDARG;
291
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);
297     }
298     
299     IMoniker_Release(This->runObjTab[index].pmkObj);
300
301     /* remove the object from the table */
302     for(j=index; j<This->runObjTabLastIndx-1; j++)
303         This->runObjTab[j]= This->runObjTab[j+1];
304
305     This->runObjTabLastIndx--;
306
307     return S_OK;
308 }
309
310 /***********************************************************************
311  *        RunningObjectTable_IsRunning
312  *
313  * PARAMS
314  *  pmkObjectName [in]  moniker of the object whose status is desired 
315  */
316 static HRESULT WINAPI
317 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName)
318 {
319     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
320
321     TRACE("(%p,%p)\n",This,pmkObjectName);
322
323     return RunningObjectTableImpl_GetObjectIndex(This,-1,pmkObjectName,NULL);
324 }
325
326 /***********************************************************************
327  *        RunningObjectTable_GetObject
328  *
329  * PARAMS
330  * pmkObjectName [in] Pointer to the moniker on the object 
331  * ppunkObject   [out] variable that receives the IUnknown interface pointer
332  */
333 static HRESULT WINAPI
334 RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
335                      IMoniker *pmkObjectName, IUnknown **ppunkObject)
336 {
337     DWORD index;
338     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
339
340     TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
341
342     if (ppunkObject==NULL)
343         return E_POINTER;
344
345     *ppunkObject=0;
346
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;
351     }
352
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;
356
357     return S_OK;
358 }
359
360 /***********************************************************************
361  *        RunningObjectTable_NoteChangeTime
362  *
363  * PARAMS
364  *  dwRegister [in] Value identifying registration being updated
365  *  pfiletime  [in] Pointer to structure containing object's last change time
366  */
367 static HRESULT WINAPI
368 RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
369                                       DWORD dwRegister, FILETIME *pfiletime)
370 {
371     DWORD index=-1;
372     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
373
374     TRACE("(%p,%ld,%p)\n",This,dwRegister,pfiletime);
375
376     /* verify if the object to be changed was registered before or not */
377     if (RunningObjectTableImpl_GetObjectIndex(This,dwRegister,NULL,&index)==S_FALSE)
378         return E_INVALIDARG;
379
380     /* set the new value of the last time change */
381     This->runObjTab[index].lastModifObj= (*pfiletime);
382
383     return S_OK;
384 }
385
386 /***********************************************************************
387  *        RunningObjectTable_GetTimeOfLastChange
388  *
389  * PARAMS
390  *  pmkObjectName  [in]  moniker of the object whose status is desired 
391  *  pfiletime      [out] structure that receives object's last change time
392  */
393 static HRESULT WINAPI
394 RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
395                             IMoniker *pmkObjectName, FILETIME *pfiletime)
396 {
397     DWORD index=-1;
398     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
399
400     TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
401
402     if (pmkObjectName==NULL || pfiletime==NULL)
403         return E_INVALIDARG;
404
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;
408
409     (*pfiletime)= This->runObjTab[index].lastModifObj;
410
411     return S_OK;
412 }
413
414 /***********************************************************************
415  *        RunningObjectTable_EnumRunning
416  *
417  * PARAMS
418  *  ppenumMoniker  [out]  receives the IEnumMoniker interface pointer 
419  */
420 static HRESULT WINAPI
421 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
422                                    IEnumMoniker **ppenumMoniker)
423 {
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
427      */
428     HRESULT rc = 0;
429     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
430
431     rc=EnumMonikerImpl_CreateEnumROTMoniker(This->runObjTab, 
432                                          This->runObjTabSize,
433                                          This->runObjTabLastIndx, 0, 
434                                          ppenumMoniker);
435     return rc;
436 }
437
438 /***********************************************************************
439  *        GetObjectIndex
440  */
441 static HRESULT WINAPI
442 RunningObjectTableImpl_GetObjectIndex(RunningObjectTableImpl* This,
443                DWORD identReg, IMoniker* pmk, DWORD *indx)
444 {
445
446     DWORD i;
447
448     TRACE("(%p,%ld,%p,%p)\n",This,identReg,pmk,indx);
449
450     if (pmk!=NULL)
451         /* search object identified by a moniker */
452         for(i=0 ; (i < This->runObjTabLastIndx) &&(!IMoniker_IsEqual(This->runObjTab[i].pmkObj,pmk)==S_OK);i++);
453     else
454         /* search object identified by a register identifier */
455         for(i=0;((i<This->runObjTabLastIndx)&&(This->runObjTab[i].identRegObj!=identReg));i++);
456
457     if (i==This->runObjTabLastIndx)  return S_FALSE;
458
459     if (indx != NULL)  *indx=i;
460
461     return S_OK;
462 }
463
464 /******************************************************************************
465  *              GetRunningObjectTable (OLE2.30)
466  */
467 HRESULT WINAPI
468 GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
469 {
470     FIXME("(%ld,%p),stub!\n",reserved,pprot);
471     return E_NOTIMPL;
472 }
473
474 /***********************************************************************
475  *           GetRunningObjectTable (OLE32.@)
476  */
477 HRESULT WINAPI
478 GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
479 {
480     IID riid=IID_IRunningObjectTable;
481     HRESULT res;
482
483     TRACE("()\n");
484
485     if (reserved!=0)
486         return E_UNEXPECTED;
487
488     if(runningObjectTableInstance==NULL)
489         return CO_E_NOTINITIALIZED;
490
491     res = IRunningObjectTable_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot);
492
493     return res;
494 }
495
496 /******************************************************************************
497  *              OleRun        [OLE32.@]
498  */
499 HRESULT WINAPI OleRun(LPUNKNOWN pUnknown)
500 {
501     IRunnableObject *runable;
502     IRunnableObject *This = (IRunnableObject *)pUnknown;
503     LRESULT ret;
504
505     ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable);
506     if (ret)
507         return 0; /* Appears to return no error. */
508     ret = IRunnableObject_Run(runable,NULL);
509     IRunnableObject_Release(runable);
510     return ret;
511 }
512
513 /******************************************************************************
514  *              MkParseDisplayName        [OLE32.@]
515  */
516 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
517                                 LPDWORD pchEaten, LPMONIKER *ppmk)
518 {
519     FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk);
520
521     if (!(IsValidInterface((LPUNKNOWN) pbc)))
522         return E_INVALIDARG;
523
524     return MK_E_SYNTAX;
525 }
526
527 /******************************************************************************
528  *              CreateClassMoniker        [OLE32.@]
529  */
530 HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker ** ppmk)
531 {
532     FIXME("%s\n", debugstr_guid( rclsid ));
533     if( ppmk )
534         *ppmk = NULL;
535     return E_NOTIMPL;
536 }
537
538 /* Virtual function table for the IRunningObjectTable class. */
539 static IRunningObjectTableVtbl VT_RunningObjectTableImpl =
540 {
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
551 };
552
553 /***********************************************************************
554  *        RunningObjectTable_Initialize
555  */
556 HRESULT WINAPI RunningObjectTableImpl_Initialize(void)
557 {
558     TRACE("\n");
559
560     /* create the unique instance of the RunningObjectTableImpl structure */
561     runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));
562
563     if (runningObjectTableInstance == 0)
564         return E_OUTOFMEMORY;
565
566     /* initialize the virtual table function */
567     runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl;
568
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;
573
574     /* allocate space memory for the table which contains all the running objects */
575     runningObjectTableInstance->runObjTab = HeapAlloc(GetProcessHeap(), 0, sizeof(RunObject[BLOCK_TAB_SIZE]));
576
577     if (runningObjectTableInstance->runObjTab == NULL)
578         return E_OUTOFMEMORY;
579
580     runningObjectTableInstance->runObjTabSize=BLOCK_TAB_SIZE;
581     runningObjectTableInstance->runObjTabRegister=1;
582     runningObjectTableInstance->runObjTabLastIndx=0;
583
584     return S_OK;
585 }
586
587 /***********************************************************************
588  *        RunningObjectTable_UnInitialize
589  */
590 HRESULT WINAPI RunningObjectTableImpl_UnInitialize()
591 {
592     TRACE("\n");
593
594     if (runningObjectTableInstance==NULL)
595         return E_POINTER;
596
597     RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance);
598
599     RunningObjectTableImpl_Destroy();
600
601     return S_OK;
602 }
603
604 /***********************************************************************
605  *        EnumMoniker_QueryInterface
606  */
607 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
608 {
609     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
610
611     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
612
613     /* validate arguments */
614     if (ppvObject == NULL)
615         return E_INVALIDARG;
616
617     *ppvObject = NULL;
618
619     if (IsEqualIID(&IID_IUnknown, riid))
620         *ppvObject = (IEnumMoniker*)This;
621     else
622         if (IsEqualIID(&IID_IEnumMoniker, riid))
623             *ppvObject = (IEnumMoniker*)This;
624
625     if ((*ppvObject)==NULL)
626         return E_NOINTERFACE;
627
628     IEnumMoniker_AddRef(iface);
629
630     return S_OK;
631 }
632
633 /***********************************************************************
634  *        EnumMoniker_AddRef
635  */
636 static ULONG   WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
637 {
638     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
639
640     TRACE("(%p)\n",This);
641
642     return InterlockedIncrement(&This->ref);
643 }
644
645 /***********************************************************************
646  *        EnumMoniker_release
647  */
648 static ULONG   WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
649 {
650     DWORD i;
651     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
652     ULONG ref;
653
654     TRACE("(%p)\n",This);
655
656     ref = InterlockedDecrement(&This->ref);
657
658     /* unitialize rot structure if there's no more reference to it*/
659     if (ref == 0) {
660
661         /* release all registered objects in Moniker list */
662         for(i=0; i < This->TabLastIndx ;i++)
663         {
664             IMoniker_Release(This->TabMoniker[i].pmkObj);
665         }
666
667         /* there're no more elements in the table */
668
669         TRACE("(%p) Deleting\n",This);
670         HeapFree (GetProcessHeap(), 0, This->TabMoniker); /* free Moniker list */
671         HeapFree (GetProcessHeap(), 0, This);             /* free Enum Instance */
672         
673     }
674
675     return ref;
676 }
677 /***********************************************************************
678  *        EnmumMoniker_Next
679  */
680 static HRESULT   WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched)
681 {
682     ULONG i;
683     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
684     TRACE("(%p) TabCurrentPos %ld Tablastindx %ld\n",This, This->TabCurrentPos, This->TabLastIndx);
685
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;
689
690     if (pceltFetched!=NULL)
691         *pceltFetched= i;
692
693     if (i==celt)
694         return S_OK;
695     else
696         return S_FALSE;
697
698 }
699
700 /***********************************************************************
701  *        EnmumMoniker_Skip
702  */
703 static HRESULT   WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt)
704 {
705     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
706
707     TRACE("(%p)\n",This);
708
709     if  (This->TabCurrentPos+celt >= This->TabLastIndx)
710         return S_FALSE;
711
712     This->TabCurrentPos+=celt;
713
714     return S_OK;
715 }
716
717 /***********************************************************************
718  *        EnmumMoniker_Reset
719  */
720 static HRESULT   WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
721 {
722     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
723
724     This->TabCurrentPos = 0;    /* set back to start of list */
725
726     TRACE("(%p)\n",This);
727
728     return S_OK;
729 }
730
731 /***********************************************************************
732  *        EnmumMoniker_Clone
733  */
734 static HRESULT   WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)
735 {
736     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
737
738     TRACE("(%p)\n",This);
739     /* copy the enum structure */ 
740     return EnumMonikerImpl_CreateEnumROTMoniker(This->TabMoniker, This->TabSize,
741                                          This->TabLastIndx, This->TabCurrentPos,
742                                          ppenum);
743 }
744
745 /* Virtual function table for the IEnumMoniker class. */
746 static IEnumMonikerVtbl VT_EnumMonikerImpl =
747 {
748     EnumMonikerImpl_QueryInterface,
749     EnumMonikerImpl_AddRef,
750     EnumMonikerImpl_Release,
751     EnumMonikerImpl_Next,
752     EnumMonikerImpl_Skip,
753     EnumMonikerImpl_Reset,
754     EnumMonikerImpl_Clone
755 };
756
757 /***********************************************************************
758  *        EnumMonikerImpl_CreateEnumROTMoniker
759  *        Used by EnumRunning to create the structure and EnumClone
760  *        to copy the structure
761  */
762 HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(RunObject* TabMoniker,
763                                                  ULONG TabSize,
764                                                  ULONG TabLastIndx,
765                                                  ULONG TabCurrentPos,
766                                                  IEnumMoniker ** ppenumMoniker)
767 {
768     int i;
769     EnumMonikerImpl* This = NULL;
770
771     if (TabCurrentPos > TabSize)
772         return E_INVALIDARG;
773
774     if (ppenumMoniker == NULL)
775         return E_INVALIDARG;
776
777     This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
778
779     if (!ppenumMoniker) return E_OUTOFMEMORY;
780
781     TRACE("(%p)\n", This);
782
783     /* initialize the virtual table function */
784     This->lpVtbl = &VT_EnumMonikerImpl;
785
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));
792
793     if (This->TabMoniker==NULL) {
794         HeapFree(GetProcessHeap(), 0, This);
795         return E_OUTOFMEMORY;
796     }
797     for (i=0; i < This->TabLastIndx; i++){
798
799         This->TabMoniker[i]=TabMoniker[i];
800         IMoniker_AddRef(TabMoniker[i].pmkObj);
801     }
802
803     *ppenumMoniker =  (IEnumMoniker*)This;
804
805     return S_OK;
806 }