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