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