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