Implement OleRegEnumVerbs.
[wine] / dlls / ole32 / moniker.c
1 /*
2  *      Monikers
3  *
4  *      Copyright 1998  Marcus Meissner
5  *      Copyright 1999  Noomen Hamza
6  *      Copyright 2005  Robert Shearman (for CodeWeavers)
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  * TODO:
23  * - IRunningObjectTable should work interprocess, but currently doesn't.
24  *   Native (on Win2k at least) uses an undocumented RPC interface, IROT, to
25  *   communicate with RPCSS which contains the table of marshalled data.
26  */
27
28 #include <assert.h>
29 #include <stdarg.h>
30 #include <string.h>
31
32 #define COBJMACROS
33
34 #include "winerror.h"
35 #include "windef.h"
36 #include "winbase.h"
37 #include "winuser.h"
38 #include "wtypes.h"
39 #include "ole2.h"
40
41 #include "wine/list.h"
42 #include "wine/debug.h"
43
44 #include "compobj_private.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(ole);
47
48 /* define the structure of the running object table elements */
49 struct rot_entry
50 {
51     struct list        entry;
52     MInterfacePointer* object; /* marshaled running object*/
53     MInterfacePointer* moniker; /* marshaled moniker that identifies this object */
54     MInterfacePointer* moniker_data; /* moniker comparison data that identifies this object */
55     DWORD              cookie; /* cookie identifying this object */
56     FILETIME           last_modified;
57 };
58
59 /* define the RunningObjectTableImpl structure */
60 typedef struct RunningObjectTableImpl
61 {
62     const IRunningObjectTableVtbl *lpVtbl;
63     LONG ref;
64
65     struct list rot; /* list of ROT entries */
66     CRITICAL_SECTION lock;
67 } RunningObjectTableImpl;
68
69 static RunningObjectTableImpl* runningObjectTableInstance = NULL;
70
71
72
73 static inline HRESULT WINAPI
74 IrotRegister(DWORD *cookie)
75 {
76     static LONG last_cookie = 1;
77     *cookie = InterlockedIncrement(&last_cookie);
78     return S_OK;
79 }
80
81 /* define the EnumMonikerImpl structure */
82 typedef struct EnumMonikerImpl
83 {
84     const IEnumMonikerVtbl *lpVtbl;
85     LONG ref;
86
87     MInterfacePointer **monikers;
88     ULONG moniker_count;
89     ULONG pos;
90 } EnumMonikerImpl;
91
92
93 /* IEnumMoniker Local functions*/
94 static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers,
95     ULONG moniker_count, ULONG pos, IEnumMoniker **ppenumMoniker);
96
97 static HRESULT create_stream_on_mip_ro(const MInterfacePointer *mip, IStream **stream)
98 {
99     HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData);
100     void *pv = GlobalLock(hglobal);
101     memcpy(pv, mip->abData, mip->ulCntData);
102     GlobalUnlock(hglobal);
103     return CreateStreamOnHGlobal(hglobal, TRUE, stream);
104 }
105
106 static inline void rot_entry_delete(struct rot_entry *rot_entry)
107 {
108     /* FIXME: revoke entry from rpcss's copy of the ROT */
109     if (rot_entry->object)
110     {
111         IStream *stream;
112         HRESULT hr;
113         hr = create_stream_on_mip_ro(rot_entry->object, &stream);
114         if (hr == S_OK)
115         {
116             CoReleaseMarshalData(stream);
117             IUnknown_Release(stream);
118         }
119     }
120     if (rot_entry->moniker)
121     {
122         IStream *stream;
123         HRESULT hr;
124         hr = create_stream_on_mip_ro(rot_entry->moniker, &stream);
125         if (hr == S_OK)
126         {
127             CoReleaseMarshalData(stream);
128             IUnknown_Release(stream);
129         }
130     }
131     HeapFree(GetProcessHeap(), 0, rot_entry->object);
132     HeapFree(GetProcessHeap(), 0, rot_entry->moniker);
133     HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
134     HeapFree(GetProcessHeap(), 0, rot_entry);
135 }
136
137 /* moniker_data must be freed with HeapFree when no longer in use */
138 static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MInterfacePointer **moniker_data)
139 {
140     HRESULT hr;
141     IROTData *pROTData = NULL;
142     ULONG size = 0;
143     hr = IMoniker_QueryInterface(pMoniker, &IID_IROTData, (void *)&pROTData);
144     if (hr != S_OK)
145     {
146         ERR("Failed to query moniker for IROTData interface, hr = 0x%08lx\n", hr);
147         return hr;
148     }
149     IROTData_GetComparisonData(pROTData, NULL, 0, &size);
150     *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
151     (*moniker_data)->ulCntData = size;
152     hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size);
153     if (hr != S_OK)
154     {
155         ERR("Failed to copy comparison data into buffer, hr = 0x%08lx\n", hr);
156         HeapFree(GetProcessHeap(), 0, *moniker_data);
157         return hr;
158     }
159     return S_OK;
160 }
161
162 /***********************************************************************
163  *        RunningObjectTable_QueryInterface
164  */
165 static HRESULT WINAPI
166 RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,
167                                       REFIID riid,void** ppvObject)
168 {
169     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
170
171     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
172
173     /* validate arguments */
174
175     if (ppvObject==0)
176         return E_INVALIDARG;
177
178     *ppvObject = 0;
179
180     if (IsEqualIID(&IID_IUnknown, riid) ||
181         IsEqualIID(&IID_IRunningObjectTable, riid))
182         *ppvObject = (IRunningObjectTable*)This;
183
184     if ((*ppvObject)==0)
185         return E_NOINTERFACE;
186
187     IRunningObjectTable_AddRef(iface);
188
189     return S_OK;
190 }
191
192 /***********************************************************************
193  *        RunningObjectTable_AddRef
194  */
195 static ULONG WINAPI
196 RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
197 {
198     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
199
200     TRACE("(%p)\n",This);
201
202     return InterlockedIncrement(&This->ref);
203 }
204
205 /***********************************************************************
206  *        RunningObjectTable_Initialize
207  */
208 static HRESULT WINAPI
209 RunningObjectTableImpl_Destroy(void)
210 {
211     struct list *cursor, *cursor2;
212
213     TRACE("()\n");
214
215     if (runningObjectTableInstance==NULL)
216         return E_INVALIDARG;
217
218     /* free the ROT table memory */
219     LIST_FOR_EACH_SAFE(cursor, cursor2, &runningObjectTableInstance->rot)
220     {
221         struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry);
222         list_remove(&rot_entry->entry);
223         rot_entry_delete(rot_entry);
224     }
225
226     /* free the ROT structure memory */
227     HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
228     runningObjectTableInstance = NULL;
229
230     return S_OK;
231 }
232
233 /***********************************************************************
234  *        RunningObjectTable_Release
235  */
236 static ULONG WINAPI
237 RunningObjectTableImpl_Release(IRunningObjectTable* iface)
238 {
239     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
240     ULONG ref;
241
242     TRACE("(%p)\n",This);
243
244     ref = InterlockedDecrement(&This->ref);
245
246     /* uninitialize ROT structure if there's no more references to it */
247     if (ref == 0)
248     {
249         struct list *cursor, *cursor2;
250         LIST_FOR_EACH_SAFE(cursor, cursor2, &This->rot)
251         {
252             struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry);
253             list_remove(&rot_entry->entry);
254             rot_entry_delete(rot_entry);
255         }
256         /*  RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
257          *  when RunningObjectTableImpl_UnInitialize function is called
258          */
259     }
260
261     return ref;
262 }
263
264 /***********************************************************************
265  *        RunningObjectTable_Register
266  *
267  * PARAMS
268  * grfFlags       [in] Registration options 
269  * punkObject     [in] the object being registered
270  * pmkObjectName  [in] the moniker of the object being registered
271  * pdwRegister    [in] the value identifying the registration
272  */
273 static HRESULT WINAPI
274 RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
275                IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister)
276 {
277     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
278     struct rot_entry *rot_entry;
279     HRESULT hr = S_OK;
280     IStream *pStream = NULL;
281     DWORD mshlflags;
282
283     TRACE("(%p,%ld,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
284
285     /*
286      * there's only two types of register : strong and or weak registration
287      * (only one must be passed on parameter)
288      */
289     if ( ( (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) || !(grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
290          (!(grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ||  (grfFlags & ROTFLAGS_ALLOWANYCLIENT)) &&
291          (grfFlags) )
292     {
293         ERR("Invalid combination of ROTFLAGS: %lx\n", grfFlags);
294         return E_INVALIDARG;
295     }
296
297     if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
298         return E_INVALIDARG;
299
300     rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));
301     if (!rot_entry)
302         return E_OUTOFMEMORY;
303
304     CoFileTimeNow(&rot_entry->last_modified);
305
306     /* marshal object */
307     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
308     if (hr != S_OK)
309     {
310         rot_entry_delete(rot_entry);
311         return hr;
312     }
313     mshlflags = (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK;
314     hr = CoMarshalInterface(pStream, &IID_IUnknown, punkObject, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, mshlflags);
315     /* FIXME: a cleaner way would be to create an IStream class that writes
316      * directly to an MInterfacePointer */
317     if (hr == S_OK)
318     {
319         HGLOBAL hglobal;
320         hr = GetHGlobalFromStream(pStream, &hglobal);
321         if (hr == S_OK)
322         {
323             SIZE_T size = GlobalSize(hglobal);
324             const void *pv = GlobalLock(hglobal);
325             rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
326             rot_entry->object->ulCntData = size;
327             memcpy(&rot_entry->object->abData, pv, size);
328             GlobalUnlock(hglobal);
329         }
330     }
331     IStream_Release(pStream);
332     if (hr != S_OK)
333     {
334         rot_entry_delete(rot_entry);
335         return hr;
336     }
337
338     hr = get_moniker_comparison_data(pmkObjectName, &rot_entry->moniker_data);
339     if (hr != S_OK)
340     {
341         rot_entry_delete(rot_entry);
342         return hr;
343     }
344
345     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
346     if (hr != S_OK)
347     {
348         rot_entry_delete(rot_entry);
349         return hr;
350     }
351     /* marshal moniker */
352     hr = CoMarshalInterface(pStream, &IID_IMoniker, (IUnknown *)pmkObjectName, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG);
353     /* FIXME: a cleaner way would be to create an IStream class that writes
354      * directly to an MInterfacePointer */
355     if (hr == S_OK)
356     {
357         HGLOBAL hglobal;
358         hr = GetHGlobalFromStream(pStream, &hglobal);
359         if (hr == S_OK)
360         {
361             SIZE_T size = GlobalSize(hglobal);
362             const void *pv = GlobalLock(hglobal);
363             rot_entry->moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
364             rot_entry->moniker->ulCntData = size;
365             memcpy(&rot_entry->moniker->abData, pv, size);
366             GlobalUnlock(hglobal);
367         }
368     }
369     IStream_Release(pStream);
370     if (hr != S_OK)
371     {
372         rot_entry_delete(rot_entry);
373         return hr;
374     }
375
376     /* FIXME: not the right signature of IrotRegister function */
377     hr = IrotRegister(&rot_entry->cookie);
378     if (hr != S_OK)
379     {
380         rot_entry_delete(rot_entry);
381         return hr;
382     }
383
384     /* gives a registration identifier to the registered object*/
385     *pdwRegister = rot_entry->cookie;
386
387     EnterCriticalSection(&This->lock);
388     /* FIXME: see if object was registered before and return MK_S_MONIKERALREADYREGISTERED */
389     list_add_tail(&This->rot, &rot_entry->entry);
390     LeaveCriticalSection(&This->lock);
391
392     return hr;
393 }
394
395 /***********************************************************************
396  *        RunningObjectTable_Revoke
397  *
398  * PARAMS
399  *  dwRegister [in] Value identifying registration to be revoked
400  */
401 static HRESULT WINAPI
402 RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister) 
403 {
404     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
405     struct rot_entry *rot_entry;
406
407     TRACE("(%p,%ld)\n",This,dwRegister);
408
409     EnterCriticalSection(&This->lock);
410     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
411     {
412         if (rot_entry->cookie == dwRegister)
413         {
414             list_remove(&rot_entry->entry);
415             LeaveCriticalSection(&This->lock);
416
417             rot_entry_delete(rot_entry);
418             return S_OK;
419         }
420     }
421     LeaveCriticalSection(&This->lock);
422
423     return E_INVALIDARG;
424 }
425
426 /***********************************************************************
427  *        RunningObjectTable_IsRunning
428  *
429  * PARAMS
430  *  pmkObjectName [in]  moniker of the object whose status is desired 
431  */
432 static HRESULT WINAPI
433 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName)
434 {
435     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
436     MInterfacePointer *moniker_data;
437     HRESULT hr;
438     struct rot_entry *rot_entry;
439
440     TRACE("(%p,%p)\n",This,pmkObjectName);
441
442     hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
443     if (hr != S_OK)
444         return hr;
445
446     hr = S_FALSE;
447     EnterCriticalSection(&This->lock);
448     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
449     {
450         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
451             !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData))
452         {
453             hr = S_OK;
454             break;
455         }
456     }
457     LeaveCriticalSection(&This->lock);
458
459     /* FIXME: call IrotIsRunning */
460
461     HeapFree(GetProcessHeap(), 0, moniker_data);
462
463     return hr;
464 }
465
466 /***********************************************************************
467  *        RunningObjectTable_GetObject
468  *
469  * PARAMS
470  * pmkObjectName [in] Pointer to the moniker on the object 
471  * ppunkObject   [out] variable that receives the IUnknown interface pointer
472  */
473 static HRESULT WINAPI
474 RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
475                      IMoniker *pmkObjectName, IUnknown **ppunkObject)
476 {
477     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
478     MInterfacePointer *moniker_data;
479     HRESULT hr;
480     struct rot_entry *rot_entry;
481
482     TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
483
484     if (ppunkObject == NULL)
485         return E_POINTER;
486
487     *ppunkObject = NULL;
488
489     hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
490     if (hr != S_OK)
491         return hr;
492
493     EnterCriticalSection(&This->lock);
494     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
495     {
496         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
497             !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData))
498         {
499             IStream *pStream;
500             hr = create_stream_on_mip_ro(rot_entry->object, &pStream);
501             if (hr == S_OK)
502             {
503                 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
504                 IStream_Release(pStream);
505             }
506
507             LeaveCriticalSection(&This->lock);
508             HeapFree(GetProcessHeap(), 0, moniker_data);
509
510             return hr;
511         }
512     }
513     LeaveCriticalSection(&This->lock);
514
515     /* FIXME: call IrotGetObject */
516     WARN("Moniker unavailable - app may require interprocess running object table\n");
517     hr = MK_E_UNAVAILABLE;
518
519     HeapFree(GetProcessHeap(), 0, moniker_data);
520
521     return hr;
522 }
523
524 /***********************************************************************
525  *        RunningObjectTable_NoteChangeTime
526  *
527  * PARAMS
528  *  dwRegister [in] Value identifying registration being updated
529  *  pfiletime  [in] Pointer to structure containing object's last change time
530  */
531 static HRESULT WINAPI
532 RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
533                                       DWORD dwRegister, FILETIME *pfiletime)
534 {
535     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
536     struct rot_entry *rot_entry;
537
538     TRACE("(%p,%ld,%p)\n",This,dwRegister,pfiletime);
539
540     EnterCriticalSection(&This->lock);
541     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
542     {
543         if (rot_entry->cookie == dwRegister)
544         {
545             rot_entry->last_modified = *pfiletime;
546             LeaveCriticalSection(&This->lock);
547             return S_OK;
548         }
549     }
550     LeaveCriticalSection(&This->lock);
551
552     /* FIXME: call IrotNoteChangeTime */
553
554     return E_INVALIDARG;
555 }
556
557 /***********************************************************************
558  *        RunningObjectTable_GetTimeOfLastChange
559  *
560  * PARAMS
561  *  pmkObjectName  [in]  moniker of the object whose status is desired 
562  *  pfiletime      [out] structure that receives object's last change time
563  */
564 static HRESULT WINAPI
565 RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
566                             IMoniker *pmkObjectName, FILETIME *pfiletime)
567 {
568     HRESULT hr = MK_E_UNAVAILABLE;
569     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
570     MInterfacePointer *moniker_data;
571     struct rot_entry *rot_entry;
572
573     TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
574
575     if (pmkObjectName==NULL || pfiletime==NULL)
576         return E_INVALIDARG;
577
578     hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
579     if (hr != S_OK)
580         return hr;
581
582     hr = MK_E_UNAVAILABLE;
583
584     EnterCriticalSection(&This->lock);
585     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
586     {
587         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
588             !memcmp(moniker_data, rot_entry->moniker_data, moniker_data->ulCntData))
589         {
590             *pfiletime = rot_entry->last_modified;
591             hr = S_OK;
592             break;
593         }
594     }
595     LeaveCriticalSection(&This->lock);
596
597     /* FIXME: if (hr != S_OK) call IrotGetTimeOfLastChange */
598
599     HeapFree(GetProcessHeap(), 0, moniker_data);
600     return hr;
601 }
602
603 /***********************************************************************
604  *        RunningObjectTable_EnumRunning
605  *
606  * PARAMS
607  *  ppenumMoniker  [out]  receives the IEnumMoniker interface pointer 
608  */
609 static HRESULT WINAPI
610 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
611                                    IEnumMoniker **ppenumMoniker)
612 {
613     HRESULT hr;
614     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
615     MInterfacePointer **monikers;
616     ULONG moniker_count = 0;
617     const struct rot_entry *rot_entry;
618     ULONG i = 0;
619
620     EnterCriticalSection(&This->lock);
621
622     LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry )
623         moniker_count++;
624
625     monikers = HeapAlloc(GetProcessHeap(), 0, moniker_count * sizeof(*monikers));
626
627     LIST_FOR_EACH_ENTRY( rot_entry, &This->rot, const struct rot_entry, entry )
628     {
629         SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[rot_entry->moniker->ulCntData]);
630         monikers[i] = HeapAlloc(GetProcessHeap(), 0, size);
631         memcpy(monikers[i], rot_entry->moniker, size);
632         i++;
633     }
634
635     LeaveCriticalSection(&This->lock);
636     
637     /* FIXME: call IrotEnumRunning and append data */
638
639     hr = EnumMonikerImpl_CreateEnumROTMoniker(monikers, moniker_count, 0, ppenumMoniker);
640
641     return hr;
642 }
643
644 /******************************************************************************
645  *              GetRunningObjectTable (OLE2.30)
646  */
647 HRESULT WINAPI
648 GetRunningObjectTable16(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
649 {
650     FIXME("(%ld,%p),stub!\n",reserved,pprot);
651     return E_NOTIMPL;
652 }
653
654 /***********************************************************************
655  *           GetRunningObjectTable (OLE32.@)
656  */
657 HRESULT WINAPI
658 GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
659 {
660     IID riid=IID_IRunningObjectTable;
661     HRESULT res;
662
663     TRACE("()\n");
664
665     if (reserved!=0)
666         return E_UNEXPECTED;
667
668     if(runningObjectTableInstance==NULL)
669         return CO_E_NOTINITIALIZED;
670
671     res = IRunningObjectTable_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot);
672
673     return res;
674 }
675
676 /******************************************************************************
677  *              OleRun        [OLE32.@]
678  */
679 HRESULT WINAPI OleRun(LPUNKNOWN pUnknown)
680 {
681     IRunnableObject *runable;
682     IRunnableObject *This = (IRunnableObject *)pUnknown;
683     LRESULT ret;
684
685     ret = IRunnableObject_QueryInterface(This,&IID_IRunnableObject,(LPVOID*)&runable);
686     if (ret)
687         return 0; /* Appears to return no error. */
688     ret = IRunnableObject_Run(runable,NULL);
689     IRunnableObject_Release(runable);
690     return ret;
691 }
692
693 /******************************************************************************
694  *              MkParseDisplayName        [OLE32.@]
695  */
696 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szUserName,
697                                 LPDWORD pchEaten, LPMONIKER *ppmk)
698 {
699     FIXME("(%p, %s, %p, %p): stub.\n", pbc, debugstr_w(szUserName), pchEaten, *ppmk);
700
701     if (!(IsValidInterface((LPUNKNOWN) pbc)))
702         return E_INVALIDARG;
703
704     return MK_E_SYNTAX;
705 }
706
707 /******************************************************************************
708  *              CreateClassMoniker        [OLE32.@]
709  */
710 HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker ** ppmk)
711 {
712     FIXME("%s\n", debugstr_guid( rclsid ));
713     if( ppmk )
714         *ppmk = NULL;
715     return E_NOTIMPL;
716 }
717
718 /* Virtual function table for the IRunningObjectTable class. */
719 static const IRunningObjectTableVtbl VT_RunningObjectTableImpl =
720 {
721     RunningObjectTableImpl_QueryInterface,
722     RunningObjectTableImpl_AddRef,
723     RunningObjectTableImpl_Release,
724     RunningObjectTableImpl_Register,
725     RunningObjectTableImpl_Revoke,
726     RunningObjectTableImpl_IsRunning,
727     RunningObjectTableImpl_GetObject,
728     RunningObjectTableImpl_NoteChangeTime,
729     RunningObjectTableImpl_GetTimeOfLastChange,
730     RunningObjectTableImpl_EnumRunning
731 };
732
733 /***********************************************************************
734  *        RunningObjectTable_Initialize
735  */
736 HRESULT WINAPI RunningObjectTableImpl_Initialize(void)
737 {
738     TRACE("\n");
739
740     /* create the unique instance of the RunningObjectTableImpl structure */
741     runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));
742
743     if (!runningObjectTableInstance)
744         return E_OUTOFMEMORY;
745
746     /* initialize the virtual table function */
747     runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl;
748
749     /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */
750     /* the ROT referred many times not in the same time (all the objects in the ROT will  */
751     /* be removed every time the ROT is removed ) */
752     runningObjectTableInstance->ref = 1;
753
754     list_init(&runningObjectTableInstance->rot);
755     InitializeCriticalSection(&runningObjectTableInstance->lock);
756
757     return S_OK;
758 }
759
760 /***********************************************************************
761  *        RunningObjectTable_UnInitialize
762  */
763 HRESULT WINAPI RunningObjectTableImpl_UnInitialize()
764 {
765     TRACE("\n");
766
767     if (runningObjectTableInstance==NULL)
768         return E_POINTER;
769
770     RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance);
771
772     RunningObjectTableImpl_Destroy();
773
774     return S_OK;
775 }
776
777 /***********************************************************************
778  *        EnumMoniker_QueryInterface
779  */
780 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
781 {
782     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
783
784     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
785
786     /* validate arguments */
787     if (ppvObject == NULL)
788         return E_INVALIDARG;
789
790     *ppvObject = NULL;
791
792     if (IsEqualIID(&IID_IUnknown, riid))
793         *ppvObject = (IEnumMoniker*)This;
794     else
795         if (IsEqualIID(&IID_IEnumMoniker, riid))
796             *ppvObject = (IEnumMoniker*)This;
797
798     if ((*ppvObject)==NULL)
799         return E_NOINTERFACE;
800
801     IEnumMoniker_AddRef(iface);
802
803     return S_OK;
804 }
805
806 /***********************************************************************
807  *        EnumMoniker_AddRef
808  */
809 static ULONG   WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
810 {
811     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
812
813     TRACE("(%p)\n",This);
814
815     return InterlockedIncrement(&This->ref);
816 }
817
818 /***********************************************************************
819  *        EnumMoniker_release
820  */
821 static ULONG   WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
822 {
823     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
824     ULONG ref;
825
826     TRACE("(%p)\n",This);
827
828     ref = InterlockedDecrement(&This->ref);
829
830     /* unitialize rot structure if there's no more reference to it*/
831     if (ref == 0)
832     {
833         ULONG i;
834
835         TRACE("(%p) Deleting\n",This);
836
837         for (i = 0; i < This->moniker_count; i++)
838             HeapFree(GetProcessHeap(), 0, This->monikers[i]);
839         HeapFree(GetProcessHeap(), 0, This->monikers);
840         HeapFree(GetProcessHeap(), 0, This);
841     }
842
843     return ref;
844 }
845 /***********************************************************************
846  *        EnmumMoniker_Next
847  */
848 static HRESULT   WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched)
849 {
850     ULONG i;
851     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
852     HRESULT hr = S_OK;
853
854     TRACE("(%p) TabCurrentPos %ld Tablastindx %ld\n", This, This->pos, This->moniker_count);
855
856     /* retrieve the requested number of moniker from the current position */
857     for(i = 0; (This->pos < This->moniker_count) && (i < celt); i++)
858     {
859         IStream *stream;
860         hr = create_stream_on_mip_ro(This->monikers[This->pos++], &stream);
861         if (hr != S_OK) break;
862         hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]);
863         IStream_Release(stream);
864         if (hr != S_OK) break;
865     }
866
867     if (pceltFetched != NULL)
868         *pceltFetched= i;
869
870     if (hr != S_OK)
871         return hr;
872
873     if (i == celt)
874         return S_OK;
875     else
876         return S_FALSE;
877
878 }
879
880 /***********************************************************************
881  *        EnmumMoniker_Skip
882  */
883 static HRESULT   WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt)
884 {
885     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
886
887     TRACE("(%p)\n",This);
888
889     if  (This->pos + celt >= This->moniker_count)
890         return S_FALSE;
891
892     This->pos += celt;
893
894     return S_OK;
895 }
896
897 /***********************************************************************
898  *        EnmumMoniker_Reset
899  */
900 static HRESULT   WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
901 {
902     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
903
904     This->pos = 0;      /* set back to start of list */
905
906     TRACE("(%p)\n",This);
907
908     return S_OK;
909 }
910
911 /***********************************************************************
912  *        EnmumMoniker_Clone
913  */
914 static HRESULT   WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)
915 {
916     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
917     MInterfacePointer **monikers = HeapAlloc(GetProcessHeap(), 0, sizeof(*monikers)*This->moniker_count);
918     ULONG i;
919
920     TRACE("(%p)\n",This);
921
922     for (i = 0; i < This->moniker_count; i++)
923     {
924         SIZE_T size = FIELD_OFFSET(MInterfacePointer, abData[This->monikers[i]->ulCntData]);
925         monikers[i] = HeapAlloc(GetProcessHeap(), 0, size);
926         memcpy(monikers[i], This->monikers[i], size);
927     }
928
929     /* copy the enum structure */ 
930     return EnumMonikerImpl_CreateEnumROTMoniker(monikers, This->moniker_count,
931         This->pos, ppenum);
932 }
933
934 /* Virtual function table for the IEnumMoniker class. */
935 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
936 {
937     EnumMonikerImpl_QueryInterface,
938     EnumMonikerImpl_AddRef,
939     EnumMonikerImpl_Release,
940     EnumMonikerImpl_Next,
941     EnumMonikerImpl_Skip,
942     EnumMonikerImpl_Reset,
943     EnumMonikerImpl_Clone
944 };
945
946 /***********************************************************************
947  *        EnumMonikerImpl_CreateEnumROTMoniker
948  *        Used by EnumRunning to create the structure and EnumClone
949  *        to copy the structure
950  */
951 static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(MInterfacePointer **monikers,
952                                                  ULONG moniker_count,
953                                                  ULONG current_pos,
954                                                  IEnumMoniker **ppenumMoniker)
955 {
956     EnumMonikerImpl* This = NULL;
957
958     if (!ppenumMoniker)
959         return E_INVALIDARG;
960
961     This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
962     if (!This) return E_OUTOFMEMORY;
963
964     TRACE("(%p)\n", This);
965
966     /* initialize the virtual table function */
967     This->lpVtbl = &VT_EnumMonikerImpl;
968
969     /* the initial reference is set to "1" */
970     This->ref = 1;                      /* set the ref count to one         */
971     This->pos = current_pos;            /* Set the list start posn */
972     This->moniker_count = moniker_count; /* Need the same size table as ROT */
973     This->monikers = monikers;
974
975     *ppenumMoniker =  (IEnumMoniker*)This;
976
977     return S_OK;
978 }
979
980
981 /* Shared implementation of moniker marshaler based on saving and loading of
982  * monikers */
983
984 typedef struct MonikerMarshal
985 {
986     const IUnknownVtbl *lpVtbl;
987     const IMarshalVtbl *lpVtblMarshal;
988     
989     LONG ref;
990     IMoniker *moniker;
991 } MonikerMarshal;
992
993 static inline MonikerMarshal *impl_from_IMarshal( IMarshal *iface )
994 {
995     return (MonikerMarshal *)((char*)iface - FIELD_OFFSET(MonikerMarshal, lpVtblMarshal));
996 }
997
998 static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv)
999 {
1000     MonikerMarshal *This = (MonikerMarshal *)iface;
1001     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1002     *ppv = NULL;
1003     if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid))
1004     {
1005         *ppv = &This->lpVtblMarshal;
1006         IUnknown_AddRef((IUnknown *)&This->lpVtblMarshal);
1007         return S_OK;
1008     }
1009     FIXME("No interface for %s\n", debugstr_guid(riid));
1010     return E_NOINTERFACE;
1011 }
1012
1013 static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface)
1014 {
1015     MonikerMarshal *This = (MonikerMarshal *)iface;
1016     return InterlockedIncrement(&This->ref);
1017 }
1018
1019 static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface)
1020 {
1021     MonikerMarshal *This = (MonikerMarshal *)iface;
1022     ULONG ref = InterlockedDecrement(&This->ref);
1023
1024     if (!ref) HeapFree(GetProcessHeap(), 0, This);
1025     return ref;
1026 }
1027
1028 static const IUnknownVtbl VT_MonikerMarshalInner =
1029 {
1030     MonikerMarshalInner_QueryInterface,
1031     MonikerMarshalInner_AddRef,
1032     MonikerMarshalInner_Release
1033 };
1034
1035 static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
1036 {
1037     MonikerMarshal *This = impl_from_IMarshal(iface);
1038     return IMoniker_QueryInterface(This->moniker, riid, ppv);
1039 }
1040
1041 static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface)
1042 {
1043     MonikerMarshal *This = impl_from_IMarshal(iface);
1044     return IMoniker_AddRef(This->moniker);
1045 }
1046
1047 static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface)
1048 {
1049     MonikerMarshal *This = impl_from_IMarshal(iface);
1050     return IMoniker_Release(This->moniker);
1051 }
1052
1053 static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass(
1054   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1055   void* pvDestContext, DWORD mshlflags, CLSID* pCid)
1056 {
1057     MonikerMarshal *This = impl_from_IMarshal(iface);
1058
1059     TRACE("(%s, %p, %lx, %p, %lx, %p)\n", debugstr_guid(riid), pv,
1060         dwDestContext, pvDestContext, mshlflags, pCid);
1061
1062     return IMoniker_GetClassID(This->moniker, pCid);
1063 }
1064
1065 static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax(
1066   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1067   void* pvDestContext, DWORD mshlflags, DWORD* pSize)
1068 {
1069     MonikerMarshal *This = impl_from_IMarshal(iface);
1070     HRESULT hr;
1071     ULARGE_INTEGER size;
1072
1073     TRACE("(%s, %p, %lx, %p, %lx, %p)\n", debugstr_guid(riid), pv,
1074         dwDestContext, pvDestContext, mshlflags, pSize);
1075
1076     hr = IMoniker_GetSizeMax(This->moniker, &size);
1077     if (hr == S_OK)
1078         *pSize = (DWORD)size.QuadPart;
1079     return hr;
1080 }
1081
1082 static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm, 
1083     REFIID riid, void* pv, DWORD dwDestContext,
1084     void* pvDestContext, DWORD mshlflags)
1085 {
1086     MonikerMarshal *This = impl_from_IMarshal(iface);
1087
1088     TRACE("(%p, %s, %p, %lx, %p, %lx)\n", pStm, debugstr_guid(riid), pv,
1089         dwDestContext, pvDestContext, mshlflags);
1090
1091     return IMoniker_Save(This->moniker, pStm, FALSE);
1092 }
1093
1094 static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
1095 {
1096     MonikerMarshal *This = impl_from_IMarshal(iface);
1097     HRESULT hr;
1098
1099     TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
1100
1101     hr = IMoniker_Load(This->moniker, pStm);
1102     if (hr == S_OK)
1103         hr = IMoniker_QueryInterface(This->moniker, riid, ppv);
1104     return hr;
1105 }
1106
1107 static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
1108 {
1109     TRACE("()\n");
1110     /* can't release a state-based marshal as nothing on server side to
1111      * release */
1112     return S_OK;
1113 }
1114
1115 static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)
1116 {
1117     TRACE("()\n");
1118     /* can't disconnect a state-based marshal as nothing on server side to
1119      * disconnect from */
1120     return S_OK;
1121 }
1122
1123 static const IMarshalVtbl VT_MonikerMarshal =
1124 {
1125     MonikerMarshal_QueryInterface,
1126     MonikerMarshal_AddRef,
1127     MonikerMarshal_Release,
1128     MonikerMarshal_GetUnmarshalClass,
1129     MonikerMarshal_GetMarshalSizeMax,
1130     MonikerMarshal_MarshalInterface,
1131     MonikerMarshal_UnmarshalInterface,
1132     MonikerMarshal_ReleaseMarshalData,
1133     MonikerMarshal_DisconnectObject
1134 };
1135
1136 HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer)
1137 {
1138     MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1139     if (!This) return E_OUTOFMEMORY;
1140
1141     This->lpVtbl = &VT_MonikerMarshalInner;
1142     This->lpVtblMarshal = &VT_MonikerMarshal;
1143     This->ref = 1;
1144     This->moniker = inner;
1145
1146     *outer = (IUnknown *)&This->lpVtbl;
1147     return S_OK;
1148 }