ole32: get_moniker_for_progid_display_name should fallback to using IClassFactory...
[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  *      Copyright 2007  Robert Shearman
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22  *
23  * TODO:
24  * - IRunningObjectTable should work interprocess, but currently doesn't.
25  *   Native (on Win2k at least) uses an undocumented RPC interface, IROT, to
26  *   communicate with RPCSS which contains the table of marshalled data.
27  */
28
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 #include "wine/exception.h"
45
46 #include "compobj_private.h"
47 #include "moniker.h"
48 #include "irot.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(ole);
51
52 /* see MSDN docs for IROTData::GetComparisonData, which states what this
53  * constant is (http://msdn2.microsoft.com/en-us/library/ms693773.aspx) */
54 #define MAX_COMPARISON_DATA 2048
55
56 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *__eptr)
57 {
58     switch (GetExceptionCode())
59     {
60     case EXCEPTION_ACCESS_VIOLATION:
61     case EXCEPTION_ILLEGAL_INSTRUCTION:
62         return EXCEPTION_CONTINUE_SEARCH;
63     default:
64         return EXCEPTION_EXECUTE_HANDLER;
65     }
66 }
67
68 /* define the structure of the running object table elements */
69 struct rot_entry
70 {
71     struct list        entry;
72     InterfaceData* object; /* marshaled running object*/
73     MonikerComparisonData* moniker_data; /* moniker comparison data that identifies this object */
74     DWORD              cookie; /* cookie identifying this object */
75     FILETIME           last_modified;
76     IrotContextHandle  ctxt_handle;
77 };
78
79 /* define the RunningObjectTableImpl structure */
80 typedef struct RunningObjectTableImpl
81 {
82     const IRunningObjectTableVtbl *lpVtbl;
83     LONG ref;
84
85     struct list rot; /* list of ROT entries */
86     CRITICAL_SECTION lock;
87 } RunningObjectTableImpl;
88
89 static RunningObjectTableImpl* runningObjectTableInstance = NULL;
90 static IrotHandle irot_handle;
91
92 /* define the EnumMonikerImpl structure */
93 typedef struct EnumMonikerImpl
94 {
95     const IEnumMonikerVtbl *lpVtbl;
96     LONG ref;
97
98     InterfaceList *moniker_list;
99     ULONG pos;
100 } EnumMonikerImpl;
101
102
103 /* IEnumMoniker Local functions*/
104 static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list,
105     ULONG pos, IEnumMoniker **ppenumMoniker);
106
107 static IrotHandle get_irot_handle(void)
108 {
109     if (!irot_handle)
110     {
111         RPC_STATUS status;
112         RPC_WSTR binding;
113         IrotHandle new_handle;
114         unsigned short ncacn_np[] = IROT_PROTSEQ;
115         unsigned short endpoint[] = IROT_ENDPOINT;
116         status = RpcStringBindingComposeW(NULL, ncacn_np, NULL, endpoint, NULL, &binding);
117         if (status == RPC_S_OK)
118         {
119             status = RpcBindingFromStringBindingW(binding, &new_handle);
120             RpcStringFreeW(&binding);
121         }
122         if (status != RPC_S_OK)
123             return NULL;
124         if (InterlockedCompareExchangePointer(&irot_handle, new_handle, NULL))
125             /* another thread beat us to it */
126             RpcBindingFree(&new_handle);
127     }
128     return irot_handle;
129 }
130
131 static BOOL start_rpcss(void)
132 {
133     PROCESS_INFORMATION pi;
134     STARTUPINFOW si;
135     static WCHAR cmd[6];
136     static const WCHAR rpcss[] = {'r','p','c','s','s',0};
137     BOOL rslt;
138
139     TRACE("\n");
140
141     ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
142     ZeroMemory(&si, sizeof(STARTUPINFOA));
143     si.cb = sizeof(STARTUPINFOA);
144
145     memcpy(cmd, rpcss, sizeof(rpcss));
146
147     rslt = CreateProcessW(
148                           NULL,           /* executable */
149                           cmd,            /* command line */
150                           NULL,           /* process security attributes */
151                           NULL,           /* primary thread security attributes */
152                           FALSE,          /* inherit handles */
153                           0,              /* creation flags */
154                           NULL,           /* use parent's environment */
155                           NULL,           /* use parent's current directory */
156                           &si,            /* STARTUPINFO pointer */
157                           &pi             /* PROCESS_INFORMATION */
158                           );
159
160     if (rslt)
161     {
162         CloseHandle(pi.hProcess);
163         CloseHandle(pi.hThread);
164         Sleep(100);
165     }
166
167     return rslt;
168 }
169
170 static HRESULT create_stream_on_mip_ro(const InterfaceData *mip, IStream **stream)
171 {
172     HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData);
173     void *pv = GlobalLock(hglobal);
174     memcpy(pv, mip->abData, mip->ulCntData);
175     GlobalUnlock(hglobal);
176     return CreateStreamOnHGlobal(hglobal, TRUE, stream);
177 }
178
179 static inline void rot_entry_delete(struct rot_entry *rot_entry)
180 {
181     if (rot_entry->cookie)
182     {
183         InterfaceData *object = NULL;
184         InterfaceData *moniker = NULL;
185         __TRY
186         {
187             IrotRevoke(get_irot_handle(), rot_entry->cookie,
188                        &rot_entry->ctxt_handle, &object, &moniker);
189         }
190         __EXCEPT(rpc_filter)
191         {
192         }
193         __ENDTRY
194         MIDL_user_free(object);
195         if (moniker)
196         {
197             IStream *stream;
198             HRESULT hr;
199             hr = create_stream_on_mip_ro(moniker, &stream);
200             if (hr == S_OK)
201             {
202                 CoReleaseMarshalData(stream);
203                 IUnknown_Release(stream);
204             }
205         }
206         MIDL_user_free(moniker);
207     }
208     if (rot_entry->object)
209     {
210         IStream *stream;
211         HRESULT hr;
212         hr = create_stream_on_mip_ro(rot_entry->object, &stream);
213         if (hr == S_OK)
214         {
215             CoReleaseMarshalData(stream);
216             IUnknown_Release(stream);
217         }
218     }
219     HeapFree(GetProcessHeap(), 0, rot_entry->object);
220     HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
221     HeapFree(GetProcessHeap(), 0, rot_entry);
222 }
223
224 /* moniker_data must be freed with HeapFree when no longer in use */
225 static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MonikerComparisonData **moniker_data)
226 {
227     HRESULT hr;
228     IROTData *pROTData = NULL;
229     hr = IMoniker_QueryInterface(pMoniker, &IID_IROTData, (void *)&pROTData);
230     if (SUCCEEDED(hr))
231     {
232         ULONG size = MAX_COMPARISON_DATA;
233         *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[size]));
234         if (!*moniker_data)
235         {
236             IROTData_Release(pROTData);
237             return E_OUTOFMEMORY;
238         }
239         hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size);
240         IROTData_Release(pROTData);
241         if (hr != S_OK)
242         {
243             ERR("Failed to copy comparison data into buffer, hr = 0x%08x\n", hr);
244             HeapFree(GetProcessHeap(), 0, *moniker_data);
245             return hr;
246         }
247         (*moniker_data)->ulCntData = size;
248     }
249     else
250     {
251         IBindCtx *pbc;
252         LPOLESTR pszDisplayName;
253         CLSID clsid;
254         int len;
255
256         TRACE("generating comparison data from display name\n");
257
258         hr = CreateBindCtx(0, &pbc);
259         if (FAILED(hr))
260             return hr;
261         hr = IMoniker_GetDisplayName(pMoniker, pbc, NULL, &pszDisplayName);
262         IBindCtx_Release(pbc);
263         if (FAILED(hr))
264             return hr;
265         hr = IMoniker_GetClassID(pMoniker, &clsid);
266         if (FAILED(hr))
267         {
268             CoTaskMemFree(pszDisplayName);
269             return hr;
270         }
271
272         len = strlenW(pszDisplayName);
273         *moniker_data = HeapAlloc(GetProcessHeap(), 0,
274             FIELD_OFFSET(MonikerComparisonData, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)]));
275         if (!*moniker_data)
276         {
277             CoTaskMemFree(pszDisplayName);
278             return E_OUTOFMEMORY;
279         }
280         (*moniker_data)->ulCntData = sizeof(CLSID) + (len+1)*sizeof(WCHAR);
281
282         memcpy(&(*moniker_data)->abData[0], &clsid, sizeof(clsid));
283         memcpy(&(*moniker_data)->abData[sizeof(clsid)], pszDisplayName, (len+1)*sizeof(WCHAR));
284         CoTaskMemFree(pszDisplayName);
285     }
286     return S_OK;
287 }
288
289 static HRESULT reduce_moniker(IMoniker *pmk, IBindCtx *pbc, IMoniker **pmkReduced)
290 {
291     IBindCtx *pbcNew = NULL;
292     HRESULT hr;
293     if (!pbc)
294     {
295         hr = CreateBindCtx(0, &pbcNew);
296         if (FAILED(hr))
297             return hr;
298         pbc = pbcNew;
299     }
300     hr = IMoniker_Reduce(pmk, pbc, MKRREDUCE_ALL, NULL, pmkReduced);
301     if (FAILED(hr))
302         ERR("reducing moniker failed with error 0x%08x\n", hr);
303     if (pbcNew) IBindCtx_Release(pbcNew);
304     return hr;
305 }
306
307 /***********************************************************************
308  *        RunningObjectTable_QueryInterface
309  */
310 static HRESULT WINAPI
311 RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,
312                                       REFIID riid,void** ppvObject)
313 {
314     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
315
316     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
317
318     /* validate arguments */
319
320     if (ppvObject==0)
321         return E_INVALIDARG;
322
323     *ppvObject = 0;
324
325     if (IsEqualIID(&IID_IUnknown, riid) ||
326         IsEqualIID(&IID_IRunningObjectTable, riid))
327         *ppvObject = (IRunningObjectTable*)This;
328
329     if ((*ppvObject)==0)
330         return E_NOINTERFACE;
331
332     IRunningObjectTable_AddRef(iface);
333
334     return S_OK;
335 }
336
337 /***********************************************************************
338  *        RunningObjectTable_AddRef
339  */
340 static ULONG WINAPI
341 RunningObjectTableImpl_AddRef(IRunningObjectTable* iface)
342 {
343     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
344
345     TRACE("(%p)\n",This);
346
347     return InterlockedIncrement(&This->ref);
348 }
349
350 /***********************************************************************
351  *        RunningObjectTable_Initialize
352  */
353 static HRESULT WINAPI
354 RunningObjectTableImpl_Destroy(void)
355 {
356     struct list *cursor, *cursor2;
357     IrotHandle old_handle;
358
359     TRACE("()\n");
360
361     if (runningObjectTableInstance==NULL)
362         return E_INVALIDARG;
363
364     /* free the ROT table memory */
365     LIST_FOR_EACH_SAFE(cursor, cursor2, &runningObjectTableInstance->rot)
366     {
367         struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry);
368         list_remove(&rot_entry->entry);
369         rot_entry_delete(rot_entry);
370     }
371
372     DEBUG_CLEAR_CRITSEC_NAME(&runningObjectTableInstance->lock);
373     DeleteCriticalSection(&runningObjectTableInstance->lock);
374
375     /* free the ROT structure memory */
376     HeapFree(GetProcessHeap(),0,runningObjectTableInstance);
377     runningObjectTableInstance = NULL;
378
379     old_handle = irot_handle;
380     irot_handle = NULL;
381     if (old_handle)
382         RpcBindingFree(&old_handle);
383
384     return S_OK;
385 }
386
387 /***********************************************************************
388  *        RunningObjectTable_Release
389  */
390 static ULONG WINAPI
391 RunningObjectTableImpl_Release(IRunningObjectTable* iface)
392 {
393     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
394     ULONG ref;
395
396     TRACE("(%p)\n",This);
397
398     ref = InterlockedDecrement(&This->ref);
399
400     /* uninitialize ROT structure if there's no more references to it */
401     if (ref == 0)
402     {
403         struct list *cursor, *cursor2;
404         LIST_FOR_EACH_SAFE(cursor, cursor2, &This->rot)
405         {
406             struct rot_entry *rot_entry = LIST_ENTRY(cursor, struct rot_entry, entry);
407             list_remove(&rot_entry->entry);
408             rot_entry_delete(rot_entry);
409         }
410         /*  RunningObjectTable data structure will be not destroyed here ! the destruction will be done only
411          *  when RunningObjectTableImpl_UnInitialize function is called
412          */
413     }
414
415     return ref;
416 }
417
418 /***********************************************************************
419  *        RunningObjectTable_Register
420  *
421  * PARAMS
422  * grfFlags       [in] Registration options 
423  * punkObject     [in] the object being registered
424  * pmkObjectName  [in] the moniker of the object being registered
425  * pdwRegister    [in] the value identifying the registration
426  */
427 static HRESULT WINAPI
428 RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD grfFlags,
429                IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister)
430 {
431     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
432     struct rot_entry *rot_entry;
433     HRESULT hr = S_OK;
434     IStream *pStream = NULL;
435     DWORD mshlflags;
436     IBindCtx *pbc;
437     InterfaceData *moniker = NULL;
438
439     TRACE("(%p,%d,%p,%p,%p)\n",This,grfFlags,punkObject,pmkObjectName,pdwRegister);
440
441     if (grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT))
442     {
443         ERR("Invalid grfFlags: 0x%08x\n", grfFlags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT));
444         return E_INVALIDARG;
445     }
446
447     if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
448         return E_INVALIDARG;
449
450     rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));
451     if (!rot_entry)
452         return E_OUTOFMEMORY;
453
454     /* marshal object */
455     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
456     if (hr != S_OK)
457     {
458         rot_entry_delete(rot_entry);
459         return hr;
460     }
461     mshlflags = (grfFlags & ROTFLAGS_REGISTRATIONKEEPSALIVE) ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK;
462     hr = CoMarshalInterface(pStream, &IID_IUnknown, punkObject, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, mshlflags);
463     /* FIXME: a cleaner way would be to create an IStream class that writes
464      * directly to an MInterfacePointer */
465     if (hr == S_OK)
466     {
467         HGLOBAL hglobal;
468         hr = GetHGlobalFromStream(pStream, &hglobal);
469         if (hr == S_OK)
470         {
471             SIZE_T size = GlobalSize(hglobal);
472             const void *pv = GlobalLock(hglobal);
473             rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
474             rot_entry->object->ulCntData = size;
475             memcpy(&rot_entry->object->abData, pv, size);
476             GlobalUnlock(hglobal);
477         }
478     }
479     IStream_Release(pStream);
480     if (hr != S_OK)
481     {
482         rot_entry_delete(rot_entry);
483         return hr;
484     }
485
486     hr = CreateBindCtx(0, &pbc);
487     if (FAILED(hr))
488     {
489         rot_entry_delete(rot_entry);
490         return hr;
491     }
492
493     hr = reduce_moniker(pmkObjectName, pbc, &pmkObjectName);
494     if (FAILED(hr))
495     {
496         rot_entry_delete(rot_entry);
497         IBindCtx_Release(pbc);
498         return hr;
499     }
500
501     hr = IMoniker_GetTimeOfLastChange(pmkObjectName, pbc, NULL,
502                                       &rot_entry->last_modified);
503     IBindCtx_Release(pbc);
504     if (FAILED(hr))
505     {
506         CoFileTimeNow(&rot_entry->last_modified);
507         hr = S_OK;
508     }
509
510     hr = get_moniker_comparison_data(pmkObjectName,
511                                      &rot_entry->moniker_data);
512     if (hr != S_OK)
513     {
514         rot_entry_delete(rot_entry);
515         IMoniker_Release(pmkObjectName);
516         return hr;
517     }
518
519     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
520     if (hr != S_OK)
521     {
522         rot_entry_delete(rot_entry);
523         IMoniker_Release(pmkObjectName);
524         return hr;
525     }
526     /* marshal moniker */
527     hr = CoMarshalInterface(pStream, &IID_IMoniker, (IUnknown *)pmkObjectName,
528                             MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG);
529     /* FIXME: a cleaner way would be to create an IStream class that writes
530      * directly to an MInterfacePointer */
531     if (hr == S_OK)
532     {
533         HGLOBAL hglobal;
534         hr = GetHGlobalFromStream(pStream, &hglobal);
535         if (hr == S_OK)
536         {
537             SIZE_T size = GlobalSize(hglobal);
538             const void *pv = GlobalLock(hglobal);
539             moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[size]));
540             moniker->ulCntData = size;
541             memcpy(&moniker->abData, pv, size);
542             GlobalUnlock(hglobal);
543         }
544     }
545     IStream_Release(pStream);
546     IMoniker_Release(pmkObjectName);
547     if (hr != S_OK)
548     {
549         HeapFree(GetProcessHeap(), 0, moniker);
550         rot_entry_delete(rot_entry);
551         return hr;
552     }
553
554
555     while (TRUE)
556     {
557         __TRY
558         {
559             hr = IrotRegister(get_irot_handle(), rot_entry->moniker_data,
560                               rot_entry->object, moniker,
561                               &rot_entry->last_modified, grfFlags,
562                               &rot_entry->cookie, &rot_entry->ctxt_handle);
563         }
564         __EXCEPT(rpc_filter)
565         {
566             hr = HRESULT_FROM_WIN32(GetExceptionCode());
567         }
568         __ENDTRY
569         if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
570         {
571             if (start_rpcss())
572                 continue;
573         }
574         break;
575     }
576     HeapFree(GetProcessHeap(), 0, moniker);
577     if (FAILED(hr))
578     {
579         rot_entry_delete(rot_entry);
580         return hr;
581     }
582
583     /* gives a registration identifier to the registered object*/
584     *pdwRegister = rot_entry->cookie;
585
586     EnterCriticalSection(&This->lock);
587     list_add_tail(&This->rot, &rot_entry->entry);
588     LeaveCriticalSection(&This->lock);
589
590     return hr;
591 }
592
593 /***********************************************************************
594  *        RunningObjectTable_Revoke
595  *
596  * PARAMS
597  *  dwRegister [in] Value identifying registration to be revoked
598  */
599 static HRESULT WINAPI
600 RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister) 
601 {
602     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
603     struct rot_entry *rot_entry;
604
605     TRACE("(%p,%d)\n",This,dwRegister);
606
607     EnterCriticalSection(&This->lock);
608     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
609     {
610         if (rot_entry->cookie == dwRegister)
611         {
612             list_remove(&rot_entry->entry);
613             LeaveCriticalSection(&This->lock);
614
615             rot_entry_delete(rot_entry);
616             return S_OK;
617         }
618     }
619     LeaveCriticalSection(&This->lock);
620
621     return E_INVALIDARG;
622 }
623
624 /***********************************************************************
625  *        RunningObjectTable_IsRunning
626  *
627  * PARAMS
628  *  pmkObjectName [in]  moniker of the object whose status is desired 
629  */
630 static HRESULT WINAPI
631 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName)
632 {
633     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
634     MonikerComparisonData *moniker_data;
635     HRESULT hr;
636     const struct rot_entry *rot_entry;
637
638     TRACE("(%p,%p)\n",This,pmkObjectName);
639
640     hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
641     if (FAILED(hr))
642         return hr;
643     hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
644     IMoniker_Release(pmkObjectName);
645     if (hr != S_OK)
646         return hr;
647
648     hr = S_FALSE;
649     EnterCriticalSection(&This->lock);
650     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
651     {
652         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
653             !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
654         {
655             hr = S_OK;
656             break;
657         }
658     }
659     LeaveCriticalSection(&This->lock);
660
661     if (hr == S_FALSE)
662     {
663         while (TRUE)
664         {
665             __TRY
666             {
667                 hr = IrotIsRunning(get_irot_handle(), moniker_data);
668             }
669             __EXCEPT(rpc_filter)
670             {
671                 hr = HRESULT_FROM_WIN32(GetExceptionCode());
672             }
673             __ENDTRY
674             if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
675             {
676                 if (start_rpcss())
677                     continue;
678             }
679             break;
680         }
681     }
682
683     HeapFree(GetProcessHeap(), 0, moniker_data);
684
685     return hr;
686 }
687
688 /***********************************************************************
689  *        RunningObjectTable_GetObject
690  *
691  * PARAMS
692  * pmkObjectName [in] Pointer to the moniker on the object 
693  * ppunkObject   [out] variable that receives the IUnknown interface pointer
694  */
695 static HRESULT WINAPI
696 RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
697                      IMoniker *pmkObjectName, IUnknown **ppunkObject)
698 {
699     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
700     MonikerComparisonData *moniker_data;
701     InterfaceData *object = NULL;
702     IrotCookie cookie;
703     HRESULT hr;
704     struct rot_entry *rot_entry;
705
706     TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
707
708     if (ppunkObject == NULL)
709         return E_POINTER;
710
711     *ppunkObject = NULL;
712
713     hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
714     if (FAILED(hr))
715         return hr;
716     hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
717     IMoniker_Release(pmkObjectName);
718     if (hr != S_OK)
719         return hr;
720
721     EnterCriticalSection(&This->lock);
722     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
723     {
724         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
725             !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
726         {
727             IStream *pStream;
728             hr = create_stream_on_mip_ro(rot_entry->object, &pStream);
729             if (hr == S_OK)
730             {
731                 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
732                 IStream_Release(pStream);
733             }
734
735             LeaveCriticalSection(&This->lock);
736             HeapFree(GetProcessHeap(), 0, moniker_data);
737
738             return hr;
739         }
740     }
741     LeaveCriticalSection(&This->lock);
742
743     TRACE("moniker unavailable locally, calling SCM\n");
744
745     while (TRUE)
746     {
747         __TRY
748         {
749             hr = IrotGetObject(get_irot_handle(), moniker_data, &object, &cookie);
750         }
751         __EXCEPT(rpc_filter)
752         {
753             hr = HRESULT_FROM_WIN32(GetExceptionCode());
754         }
755         __ENDTRY
756         if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
757         {
758             if (start_rpcss())
759                 continue;
760         }
761         break;
762     }
763
764     if (SUCCEEDED(hr))
765     {
766         IStream *pStream;
767         hr = create_stream_on_mip_ro(object, &pStream);
768         if (hr == S_OK)
769         {
770             hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
771             IStream_Release(pStream);
772         }
773     }
774     else
775         WARN("Moniker unavailable, IrotGetObject returned 0x%08x\n", hr);
776
777     HeapFree(GetProcessHeap(), 0, moniker_data);
778
779     return hr;
780 }
781
782 /***********************************************************************
783  *        RunningObjectTable_NoteChangeTime
784  *
785  * PARAMS
786  *  dwRegister [in] Value identifying registration being updated
787  *  pfiletime  [in] Pointer to structure containing object's last change time
788  */
789 static HRESULT WINAPI
790 RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
791                                       DWORD dwRegister, FILETIME *pfiletime)
792 {
793     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
794     struct rot_entry *rot_entry;
795     HRESULT hr = E_INVALIDARG;
796
797     TRACE("(%p,%d,%p)\n",This,dwRegister,pfiletime);
798
799     EnterCriticalSection(&This->lock);
800     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
801     {
802         if (rot_entry->cookie == dwRegister)
803         {
804             rot_entry->last_modified = *pfiletime;
805             LeaveCriticalSection(&This->lock);
806
807             while (TRUE)
808             {
809                 __TRY
810                 {
811                     hr = IrotNoteChangeTime(get_irot_handle(), dwRegister, pfiletime);
812                 }
813                 __EXCEPT(rpc_filter)
814                 {
815                     hr = HRESULT_FROM_WIN32(GetExceptionCode());
816                 }
817                 __ENDTRY
818                 if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
819                 {
820                     if (start_rpcss())
821                         continue;
822                 }
823                 break;
824             }
825
826             goto done;
827         }
828     }
829     LeaveCriticalSection(&This->lock);
830
831 done:
832     TRACE("-- 0x08%x\n", hr);
833     return hr;
834 }
835
836 /***********************************************************************
837  *        RunningObjectTable_GetTimeOfLastChange
838  *
839  * PARAMS
840  *  pmkObjectName  [in]  moniker of the object whose status is desired 
841  *  pfiletime      [out] structure that receives object's last change time
842  */
843 static HRESULT WINAPI
844 RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
845                             IMoniker *pmkObjectName, FILETIME *pfiletime)
846 {
847     HRESULT hr = MK_E_UNAVAILABLE;
848     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
849     MonikerComparisonData *moniker_data;
850     const struct rot_entry *rot_entry;
851
852     TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
853
854     if (pmkObjectName==NULL || pfiletime==NULL)
855         return E_INVALIDARG;
856
857     hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
858     if (FAILED(hr))
859         return hr;
860     hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
861     IMoniker_Release(pmkObjectName);
862     if (hr != S_OK)
863         return hr;
864
865     hr = MK_E_UNAVAILABLE;
866
867     EnterCriticalSection(&This->lock);
868     LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
869     {
870         if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
871             !memcmp(&moniker_data->abData, &rot_entry->moniker_data->abData, moniker_data->ulCntData))
872         {
873             *pfiletime = rot_entry->last_modified;
874             hr = S_OK;
875             break;
876         }
877     }
878     LeaveCriticalSection(&This->lock);
879
880     if (hr != S_OK)
881     {
882         while (TRUE)
883         {
884             __TRY
885             {
886                 hr = IrotGetTimeOfLastChange(get_irot_handle(), moniker_data, pfiletime);
887             }
888             __EXCEPT(rpc_filter)
889             {
890                 hr = HRESULT_FROM_WIN32(GetExceptionCode());
891             }
892             __ENDTRY
893             if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
894             {
895                 if (start_rpcss())
896                     continue;
897             }
898             break;
899         }
900     }
901
902     HeapFree(GetProcessHeap(), 0, moniker_data);
903
904     TRACE("-- 0x%08x\n", hr);
905     return hr;
906 }
907
908 /***********************************************************************
909  *        RunningObjectTable_EnumRunning
910  *
911  * PARAMS
912  *  ppenumMoniker  [out]  receives the IEnumMoniker interface pointer 
913  */
914 static HRESULT WINAPI
915 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
916                                    IEnumMoniker **ppenumMoniker)
917 {
918     RunningObjectTableImpl *This = (RunningObjectTableImpl *)iface;
919     InterfaceList *interface_list = NULL;
920     HRESULT hr;
921
922     TRACE("(%p, %p)\n", This, ppenumMoniker);
923
924     *ppenumMoniker = NULL;
925
926     while (TRUE)
927     {
928         __TRY
929         {
930             hr = IrotEnumRunning(get_irot_handle(), &interface_list);
931         }
932         __EXCEPT(rpc_filter)
933         {
934             hr = HRESULT_FROM_WIN32(GetExceptionCode());
935         }
936         __ENDTRY
937         if (hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE))
938         {
939             if (start_rpcss())
940                 continue;
941         }
942         break;
943     }
944
945     if (SUCCEEDED(hr))
946         hr = EnumMonikerImpl_CreateEnumROTMoniker(interface_list,
947                                                   0, ppenumMoniker);
948
949     return hr;
950 }
951
952 /* Virtual function table for the IRunningObjectTable class. */
953 static const IRunningObjectTableVtbl VT_RunningObjectTableImpl =
954 {
955     RunningObjectTableImpl_QueryInterface,
956     RunningObjectTableImpl_AddRef,
957     RunningObjectTableImpl_Release,
958     RunningObjectTableImpl_Register,
959     RunningObjectTableImpl_Revoke,
960     RunningObjectTableImpl_IsRunning,
961     RunningObjectTableImpl_GetObject,
962     RunningObjectTableImpl_NoteChangeTime,
963     RunningObjectTableImpl_GetTimeOfLastChange,
964     RunningObjectTableImpl_EnumRunning
965 };
966
967 /***********************************************************************
968  *        RunningObjectTable_Initialize
969  */
970 HRESULT WINAPI RunningObjectTableImpl_Initialize(void)
971 {
972     TRACE("\n");
973
974     /* create the unique instance of the RunningObjectTableImpl structure */
975     runningObjectTableInstance = HeapAlloc(GetProcessHeap(), 0, sizeof(RunningObjectTableImpl));
976
977     if (!runningObjectTableInstance)
978         return E_OUTOFMEMORY;
979
980     /* initialize the virtual table function */
981     runningObjectTableInstance->lpVtbl = &VT_RunningObjectTableImpl;
982
983     /* the initial reference is set to "1" ! because if set to "0" it will be not practis when */
984     /* the ROT referred many times not in the same time (all the objects in the ROT will  */
985     /* be removed every time the ROT is removed ) */
986     runningObjectTableInstance->ref = 1;
987
988     list_init(&runningObjectTableInstance->rot);
989     InitializeCriticalSection(&runningObjectTableInstance->lock);
990     DEBUG_SET_CRITSEC_NAME(&runningObjectTableInstance->lock, "RunningObjectTableImpl.lock");
991
992     return S_OK;
993 }
994
995 /***********************************************************************
996  *        RunningObjectTable_UnInitialize
997  */
998 HRESULT WINAPI RunningObjectTableImpl_UnInitialize(void)
999 {
1000     TRACE("\n");
1001
1002     if (runningObjectTableInstance==NULL)
1003         return E_POINTER;
1004
1005     RunningObjectTableImpl_Release((IRunningObjectTable*)runningObjectTableInstance);
1006
1007     RunningObjectTableImpl_Destroy();
1008
1009     return S_OK;
1010 }
1011
1012 /***********************************************************************
1013  *           GetRunningObjectTable (OLE32.@)
1014  *
1015  * Retrieves the global running object table.
1016  *
1017  * PARAMS
1018  *  reserved [I] Reserved. Set to 0.
1019  *  pprot    [O] Address that receives the pointer to the running object table.
1020  *
1021  * RETURNS
1022  *  Success: S_OK.
1023  *  Failure: Any HRESULT code.
1024  */
1025 HRESULT WINAPI
1026 GetRunningObjectTable(DWORD reserved, LPRUNNINGOBJECTTABLE *pprot)
1027 {
1028     IID riid=IID_IRunningObjectTable;
1029     HRESULT res;
1030
1031     TRACE("()\n");
1032
1033     if (reserved!=0)
1034         return E_UNEXPECTED;
1035
1036     if(runningObjectTableInstance==NULL)
1037         return CO_E_NOTINITIALIZED;
1038
1039     res = IRunningObjectTable_QueryInterface((IRunningObjectTable*)runningObjectTableInstance,&riid,(void**)pprot);
1040
1041     return res;
1042 }
1043
1044 static HRESULT get_moniker_for_progid_display_name(LPBC pbc,
1045                                                    LPCOLESTR szDisplayName,
1046                                                    LPDWORD pchEaten,
1047                                                    LPMONIKER *ppmk)
1048 {
1049     CLSID clsid;
1050     HRESULT hr;
1051     LPWSTR progid;
1052     LPCWSTR start = szDisplayName;
1053     LPCWSTR end;
1054     int len;
1055     IMoniker *class_moniker;
1056
1057     if (*start == '@')
1058         start++;
1059
1060     /* find end delimiter */
1061     for (end = start; *end; end++)
1062         if (*end == ':')
1063             break;
1064
1065     len = end - start;
1066
1067     /* must start with '@' or have a ':' somewhere and mustn't be one character
1068      * long (since that looks like an absolute path) */
1069     if (((start == szDisplayName) && (*end == '\0')) || (len <= 1))
1070         return MK_E_SYNTAX;
1071
1072     progid = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
1073     if (progid)
1074     {
1075         memcpy(progid, start, len * sizeof(WCHAR));
1076         progid[len] = '\0';
1077     }
1078     hr = CLSIDFromProgID(progid, &clsid);
1079     HeapFree(GetProcessHeap(), 0, progid);
1080     if (FAILED(hr))
1081         return MK_E_SYNTAX;
1082
1083     hr = CreateClassMoniker(&clsid, &class_moniker);
1084     if (SUCCEEDED(hr))
1085     {
1086         IParseDisplayName *pdn;
1087         hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
1088                                    &IID_IParseDisplayName, (void **)&pdn);
1089         /* fallback to using IClassFactory to get IParseDisplayName -
1090          * adsldp.dll depends on this */
1091         if (FAILED(hr))
1092         {
1093             IClassFactory *pcf;
1094             hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
1095                                        &IID_IClassFactory, (void **)&pcf);
1096             if (SUCCEEDED(hr))
1097             {
1098                 hr = IClassFactory_CreateInstance(pcf, NULL,
1099                                                   &IID_IParseDisplayName,
1100                                                   (void **)&pdn);
1101                 IClassFactory_Release(pcf);
1102             }
1103         }
1104         IMoniker_Release(class_moniker);
1105         if (SUCCEEDED(hr))
1106         {
1107             hr = IParseDisplayName_ParseDisplayName(pdn, pbc,
1108                                                     (LPOLESTR)szDisplayName,
1109                                                     pchEaten, ppmk);
1110             IParseDisplayName_Release(pdn);
1111         }
1112     }
1113     return hr;
1114 }
1115
1116 /******************************************************************************
1117  *              MkParseDisplayName        [OLE32.@]
1118  */
1119 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
1120                                 LPDWORD pchEaten, LPMONIKER *ppmk)
1121 {
1122     HRESULT hr = MK_E_SYNTAX;
1123     static const WCHAR wszClsidColon[] = {'c','l','s','i','d',':'};
1124     IMoniker *moniker;
1125     DWORD chEaten;
1126
1127     TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
1128
1129     if (!(IsValidInterface((LPUNKNOWN) pbc)))
1130         return E_INVALIDARG;
1131
1132     *pchEaten = 0;
1133     *ppmk = NULL;
1134
1135     if (!strncmpiW(szDisplayName, wszClsidColon, sizeof(wszClsidColon)/sizeof(wszClsidColon[0])))
1136     {
1137         hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
1138         if (FAILED(hr) && (hr != MK_E_SYNTAX))
1139             return hr;
1140     }
1141     else
1142     {
1143         hr = get_moniker_for_progid_display_name(pbc, szDisplayName, &chEaten, &moniker);
1144         if (FAILED(hr) && (hr != MK_E_SYNTAX))
1145             return hr;
1146     }
1147
1148     if (FAILED(hr))
1149     {
1150         hr = FileMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
1151         if (FAILED(hr) && (hr != MK_E_SYNTAX))
1152             return hr;
1153     }
1154
1155     if (SUCCEEDED(hr))
1156     {
1157         while (TRUE)
1158         {
1159             IMoniker *next_moniker;
1160             *pchEaten += chEaten;
1161             szDisplayName += chEaten;
1162             if (!*szDisplayName)
1163             {
1164                 *ppmk = moniker;
1165                 return S_OK;
1166             }
1167             chEaten = 0;
1168             hr = IMoniker_ParseDisplayName(moniker, pbc, NULL,
1169                                            (LPOLESTR)szDisplayName, &chEaten,
1170                                            &next_moniker);
1171             IMoniker_Release(moniker);
1172             if (FAILED(hr))
1173             {
1174                 *pchEaten = 0;
1175                 break;
1176             }
1177             moniker = next_moniker;
1178         }
1179     }
1180
1181     return hr;
1182 }
1183
1184 /***********************************************************************
1185  *        GetClassFile (OLE32.@)
1186  *
1187  * Retrieves the class ID associated with the given filename.
1188  *
1189  * PARAMS
1190  *  filePathName [I] Filename to retrieve the class ID for.
1191  *  pclsid       [O] Address that receives the class ID for the file.
1192  *
1193  * RETURNS
1194  *  Success: S_OK.
1195  *  Failure: Any HRESULT code.
1196  */
1197 HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
1198 {
1199     IStorage *pstg=0;
1200     HRESULT res;
1201     int nbElm, length, i;
1202     LONG sizeProgId;
1203     LPOLESTR *pathDec=0,absFile=0,progId=0;
1204     LPWSTR extension;
1205     static const WCHAR bkslashW[] = {'\\',0};
1206     static const WCHAR dotW[] = {'.',0};
1207
1208     TRACE("%s, %p\n", debugstr_w(filePathName), pclsid);
1209
1210     /* if the file contain a storage object the return the CLSID written by IStorage_SetClass method*/
1211     if((StgIsStorageFile(filePathName))==S_OK){
1212
1213         res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
1214
1215         if (SUCCEEDED(res))
1216             res=ReadClassStg(pstg,pclsid);
1217
1218         IStorage_Release(pstg);
1219
1220         return res;
1221     }
1222     /* if the file is not a storage object then attemps to match various bits in the file against a
1223        pattern in the registry. this case is not frequently used ! so I present only the psodocode for
1224        this case
1225
1226      for(i=0;i<nFileTypes;i++)
1227
1228         for(i=0;j<nPatternsForType;j++){
1229
1230             PATTERN pat;
1231             HANDLE  hFile;
1232
1233             pat=ReadPatternFromRegistry(i,j);
1234             hFile=CreateFileW(filePathName,,,,,,hFile);
1235             SetFilePosition(hFile,pat.offset);
1236             ReadFile(hFile,buf,pat.size,&r,NULL);
1237             if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
1238
1239                 *pclsid=ReadCLSIDFromRegistry(i);
1240                 return S_OK;
1241             }
1242         }
1243      */
1244
1245     /* if the above strategies fail then search for the extension key in the registry */
1246
1247     /* get the last element (absolute file) in the path name */
1248     nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec);
1249     absFile=pathDec[nbElm-1];
1250
1251     /* failed if the path represente a directory and not an absolute file name*/
1252     if (!lstrcmpW(absFile, bkslashW))
1253         return MK_E_INVALIDEXTENSION;
1254
1255     /* get the extension of the file */
1256     extension = NULL;
1257     length=lstrlenW(absFile);
1258     for(i = length-1; (i >= 0) && *(extension = &absFile[i]) != '.'; i--)
1259         /* nothing */;
1260
1261     if (!extension || !lstrcmpW(extension, dotW))
1262         return MK_E_INVALIDEXTENSION;
1263
1264     res=RegQueryValueW(HKEY_CLASSES_ROOT, extension, NULL, &sizeProgId);
1265
1266     /* get the progId associated to the extension */
1267     progId = CoTaskMemAlloc(sizeProgId);
1268     res = RegQueryValueW(HKEY_CLASSES_ROOT, extension, progId, &sizeProgId);
1269
1270     if (res==ERROR_SUCCESS)
1271         /* return the clsid associated to the progId */
1272         res= CLSIDFromProgID(progId,pclsid);
1273
1274     for(i=0; pathDec[i]!=NULL;i++)
1275         CoTaskMemFree(pathDec[i]);
1276     CoTaskMemFree(pathDec);
1277
1278     CoTaskMemFree(progId);
1279
1280     if (res==ERROR_SUCCESS)
1281         return res;
1282
1283     return MK_E_INVALIDEXTENSION;
1284 }
1285
1286 /***********************************************************************
1287  *        EnumMoniker_QueryInterface
1288  */
1289 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1290 {
1291     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1292
1293     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1294
1295     /* validate arguments */
1296     if (ppvObject == NULL)
1297         return E_INVALIDARG;
1298
1299     *ppvObject = NULL;
1300
1301     if (IsEqualIID(&IID_IUnknown, riid))
1302         *ppvObject = (IEnumMoniker*)This;
1303     else
1304         if (IsEqualIID(&IID_IEnumMoniker, riid))
1305             *ppvObject = (IEnumMoniker*)This;
1306
1307     if ((*ppvObject)==NULL)
1308         return E_NOINTERFACE;
1309
1310     IEnumMoniker_AddRef(iface);
1311
1312     return S_OK;
1313 }
1314
1315 /***********************************************************************
1316  *        EnumMoniker_AddRef
1317  */
1318 static ULONG   WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1319 {
1320     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1321
1322     TRACE("(%p)\n",This);
1323
1324     return InterlockedIncrement(&This->ref);
1325 }
1326
1327 /***********************************************************************
1328  *        EnumMoniker_release
1329  */
1330 static ULONG   WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1331 {
1332     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1333     ULONG ref;
1334
1335     TRACE("(%p)\n",This);
1336
1337     ref = InterlockedDecrement(&This->ref);
1338
1339     /* uninitialize rot structure if there's no more reference to it*/
1340     if (ref == 0)
1341     {
1342         ULONG i;
1343
1344         TRACE("(%p) Deleting\n",This);
1345
1346         for (i = 0; i < This->moniker_list->size; i++)
1347             HeapFree(GetProcessHeap(), 0, This->moniker_list->interfaces[i]);
1348         HeapFree(GetProcessHeap(), 0, This->moniker_list);
1349         HeapFree(GetProcessHeap(), 0, This);
1350     }
1351
1352     return ref;
1353 }
1354 /***********************************************************************
1355  *        EnmumMoniker_Next
1356  */
1357 static HRESULT   WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched)
1358 {
1359     ULONG i;
1360     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1361     HRESULT hr = S_OK;
1362
1363     TRACE("(%p) TabCurrentPos %d Tablastindx %d\n", This, This->pos, This->moniker_list->size);
1364
1365     /* retrieve the requested number of moniker from the current position */
1366     for(i = 0; (This->pos < This->moniker_list->size) && (i < celt); i++)
1367     {
1368         IStream *stream;
1369         hr = create_stream_on_mip_ro(This->moniker_list->interfaces[This->pos++], &stream);
1370         if (hr != S_OK) break;
1371         hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]);
1372         IStream_Release(stream);
1373         if (hr != S_OK) break;
1374     }
1375
1376     if (pceltFetched != NULL)
1377         *pceltFetched= i;
1378
1379     if (hr != S_OK)
1380         return hr;
1381
1382     if (i == celt)
1383         return S_OK;
1384     else
1385         return S_FALSE;
1386
1387 }
1388
1389 /***********************************************************************
1390  *        EnmumMoniker_Skip
1391  */
1392 static HRESULT   WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt)
1393 {
1394     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1395
1396     TRACE("(%p)\n",This);
1397
1398     if  (This->pos + celt >= This->moniker_list->size)
1399         return S_FALSE;
1400
1401     This->pos += celt;
1402
1403     return S_OK;
1404 }
1405
1406 /***********************************************************************
1407  *        EnmumMoniker_Reset
1408  */
1409 static HRESULT   WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
1410 {
1411     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1412
1413     This->pos = 0;      /* set back to start of list */
1414
1415     TRACE("(%p)\n",This);
1416
1417     return S_OK;
1418 }
1419
1420 /***********************************************************************
1421  *        EnmumMoniker_Clone
1422  */
1423 static HRESULT   WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)
1424 {
1425     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1426     InterfaceList *moniker_list;
1427     ULONG i;
1428
1429     TRACE("(%p)\n",This);
1430
1431     *ppenum = NULL;
1432
1433     moniker_list = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceList, interfaces[This->moniker_list->size]));
1434     if (!moniker_list)
1435         return E_OUTOFMEMORY;
1436
1437     moniker_list->size = This->moniker_list->size;
1438     for (i = 0; i < This->moniker_list->size; i++)
1439     {
1440         SIZE_T size = FIELD_OFFSET(InterfaceData, abData[This->moniker_list->interfaces[i]->ulCntData]);
1441         moniker_list->interfaces[i] = HeapAlloc(GetProcessHeap(), 0, size);
1442         if (!moniker_list->interfaces[i])
1443         {
1444             ULONG end = i;
1445             for (i = 0; i < end; i++)
1446                 HeapFree(GetProcessHeap(), 0, moniker_list->interfaces[i]);
1447             HeapFree(GetProcessHeap(), 0, moniker_list);
1448             return E_OUTOFMEMORY;
1449         }
1450         memcpy(moniker_list->interfaces[i], This->moniker_list->interfaces[i], size);
1451     }
1452
1453     /* copy the enum structure */ 
1454     return EnumMonikerImpl_CreateEnumROTMoniker(moniker_list, This->pos, ppenum);
1455 }
1456
1457 /* Virtual function table for the IEnumMoniker class. */
1458 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
1459 {
1460     EnumMonikerImpl_QueryInterface,
1461     EnumMonikerImpl_AddRef,
1462     EnumMonikerImpl_Release,
1463     EnumMonikerImpl_Next,
1464     EnumMonikerImpl_Skip,
1465     EnumMonikerImpl_Reset,
1466     EnumMonikerImpl_Clone
1467 };
1468
1469 /***********************************************************************
1470  *        EnumMonikerImpl_CreateEnumROTMoniker
1471  *        Used by EnumRunning to create the structure and EnumClone
1472  *        to copy the structure
1473  */
1474 static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list,
1475                                                  ULONG current_pos,
1476                                                  IEnumMoniker **ppenumMoniker)
1477 {
1478     EnumMonikerImpl* This = NULL;
1479
1480     if (!ppenumMoniker)
1481         return E_INVALIDARG;
1482
1483     This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1484     if (!This) return E_OUTOFMEMORY;
1485
1486     TRACE("(%p)\n", This);
1487
1488     /* initialize the virtual table function */
1489     This->lpVtbl = &VT_EnumMonikerImpl;
1490
1491     /* the initial reference is set to "1" */
1492     This->ref = 1;                      /* set the ref count to one         */
1493     This->pos = current_pos;            /* Set the list start posn */
1494     This->moniker_list = moniker_list;
1495
1496     *ppenumMoniker =  (IEnumMoniker*)This;
1497
1498     return S_OK;
1499 }
1500
1501
1502 /* Shared implementation of moniker marshaler based on saving and loading of
1503  * monikers */
1504
1505 typedef struct MonikerMarshal
1506 {
1507     const IUnknownVtbl *lpVtbl;
1508     const IMarshalVtbl *lpVtblMarshal;
1509     
1510     LONG ref;
1511     IMoniker *moniker;
1512 } MonikerMarshal;
1513
1514 static inline MonikerMarshal *impl_from_IMarshal( IMarshal *iface )
1515 {
1516     return (MonikerMarshal *)((char*)iface - FIELD_OFFSET(MonikerMarshal, lpVtblMarshal));
1517 }
1518
1519 static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv)
1520 {
1521     MonikerMarshal *This = (MonikerMarshal *)iface;
1522     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1523     *ppv = NULL;
1524     if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid))
1525     {
1526         *ppv = &This->lpVtblMarshal;
1527         IUnknown_AddRef((IUnknown *)&This->lpVtblMarshal);
1528         return S_OK;
1529     }
1530     FIXME("No interface for %s\n", debugstr_guid(riid));
1531     return E_NOINTERFACE;
1532 }
1533
1534 static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface)
1535 {
1536     MonikerMarshal *This = (MonikerMarshal *)iface;
1537     return InterlockedIncrement(&This->ref);
1538 }
1539
1540 static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface)
1541 {
1542     MonikerMarshal *This = (MonikerMarshal *)iface;
1543     ULONG ref = InterlockedDecrement(&This->ref);
1544
1545     if (!ref) HeapFree(GetProcessHeap(), 0, This);
1546     return ref;
1547 }
1548
1549 static const IUnknownVtbl VT_MonikerMarshalInner =
1550 {
1551     MonikerMarshalInner_QueryInterface,
1552     MonikerMarshalInner_AddRef,
1553     MonikerMarshalInner_Release
1554 };
1555
1556 static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
1557 {
1558     MonikerMarshal *This = impl_from_IMarshal(iface);
1559     return IMoniker_QueryInterface(This->moniker, riid, ppv);
1560 }
1561
1562 static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface)
1563 {
1564     MonikerMarshal *This = impl_from_IMarshal(iface);
1565     return IMoniker_AddRef(This->moniker);
1566 }
1567
1568 static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface)
1569 {
1570     MonikerMarshal *This = impl_from_IMarshal(iface);
1571     return IMoniker_Release(This->moniker);
1572 }
1573
1574 static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass(
1575   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1576   void* pvDestContext, DWORD mshlflags, CLSID* pCid)
1577 {
1578     MonikerMarshal *This = impl_from_IMarshal(iface);
1579
1580     TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
1581         dwDestContext, pvDestContext, mshlflags, pCid);
1582
1583     return IMoniker_GetClassID(This->moniker, pCid);
1584 }
1585
1586 static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax(
1587   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1588   void* pvDestContext, DWORD mshlflags, DWORD* pSize)
1589 {
1590     MonikerMarshal *This = impl_from_IMarshal(iface);
1591     HRESULT hr;
1592     ULARGE_INTEGER size;
1593
1594     TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
1595         dwDestContext, pvDestContext, mshlflags, pSize);
1596
1597     hr = IMoniker_GetSizeMax(This->moniker, &size);
1598     if (hr == S_OK)
1599         *pSize = (DWORD)size.QuadPart;
1600     return hr;
1601 }
1602
1603 static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm, 
1604     REFIID riid, void* pv, DWORD dwDestContext,
1605     void* pvDestContext, DWORD mshlflags)
1606 {
1607     MonikerMarshal *This = impl_from_IMarshal(iface);
1608
1609     TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv,
1610         dwDestContext, pvDestContext, mshlflags);
1611
1612     return IMoniker_Save(This->moniker, pStm, FALSE);
1613 }
1614
1615 static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
1616 {
1617     MonikerMarshal *This = impl_from_IMarshal(iface);
1618     HRESULT hr;
1619
1620     TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
1621
1622     hr = IMoniker_Load(This->moniker, pStm);
1623     if (hr == S_OK)
1624         hr = IMoniker_QueryInterface(This->moniker, riid, ppv);
1625     return hr;
1626 }
1627
1628 static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
1629 {
1630     TRACE("()\n");
1631     /* can't release a state-based marshal as nothing on server side to
1632      * release */
1633     return S_OK;
1634 }
1635
1636 static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)
1637 {
1638     TRACE("()\n");
1639     /* can't disconnect a state-based marshal as nothing on server side to
1640      * disconnect from */
1641     return S_OK;
1642 }
1643
1644 static const IMarshalVtbl VT_MonikerMarshal =
1645 {
1646     MonikerMarshal_QueryInterface,
1647     MonikerMarshal_AddRef,
1648     MonikerMarshal_Release,
1649     MonikerMarshal_GetUnmarshalClass,
1650     MonikerMarshal_GetMarshalSizeMax,
1651     MonikerMarshal_MarshalInterface,
1652     MonikerMarshal_UnmarshalInterface,
1653     MonikerMarshal_ReleaseMarshalData,
1654     MonikerMarshal_DisconnectObject
1655 };
1656
1657 HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer)
1658 {
1659     MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1660     if (!This) return E_OUTOFMEMORY;
1661
1662     This->lpVtbl = &VT_MonikerMarshalInner;
1663     This->lpVtblMarshal = &VT_MonikerMarshal;
1664     This->ref = 1;
1665     This->moniker = inner;
1666
1667     *outer = (IUnknown *)&This->lpVtbl;
1668     return S_OK;
1669 }
1670
1671 void * __RPC_USER MIDL_user_allocate(size_t size)
1672 {
1673     return HeapAlloc(GetProcessHeap(), 0, size);
1674 }
1675
1676 void __RPC_USER MIDL_user_free(void *p)
1677 {
1678     HeapFree(GetProcessHeap(), 0, p);
1679 }