msxml3: Implement get_xml.
[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         IMoniker_Release(class_moniker);
1090         if (SUCCEEDED(hr))
1091         {
1092             hr = IParseDisplayName_ParseDisplayName(pdn, pbc,
1093                                                     (LPOLESTR)szDisplayName,
1094                                                     pchEaten, ppmk);
1095             IParseDisplayName_Release(pdn);
1096         }
1097     }
1098     return hr;
1099 }
1100
1101 /******************************************************************************
1102  *              MkParseDisplayName        [OLE32.@]
1103  */
1104 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
1105                                 LPDWORD pchEaten, LPMONIKER *ppmk)
1106 {
1107     HRESULT hr = MK_E_SYNTAX;
1108     static const WCHAR wszClsidColon[] = {'c','l','s','i','d',':'};
1109     IMoniker *moniker;
1110     DWORD chEaten;
1111
1112     TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
1113
1114     if (!(IsValidInterface((LPUNKNOWN) pbc)))
1115         return E_INVALIDARG;
1116
1117     *pchEaten = 0;
1118     *ppmk = NULL;
1119
1120     if (!strncmpiW(szDisplayName, wszClsidColon, sizeof(wszClsidColon)/sizeof(wszClsidColon[0])))
1121     {
1122         hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
1123         if (FAILED(hr) && (hr != MK_E_SYNTAX))
1124             return hr;
1125     }
1126     else
1127     {
1128         hr = get_moniker_for_progid_display_name(pbc, szDisplayName, &chEaten, &moniker);
1129         if (FAILED(hr) && (hr != MK_E_SYNTAX))
1130             return hr;
1131     }
1132
1133     if (FAILED(hr))
1134     {
1135         hr = FileMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
1136         if (FAILED(hr) && (hr != MK_E_SYNTAX))
1137             return hr;
1138     }
1139
1140     if (SUCCEEDED(hr))
1141     {
1142         while (TRUE)
1143         {
1144             IMoniker *next_moniker;
1145             *pchEaten += chEaten;
1146             szDisplayName += chEaten;
1147             if (!*szDisplayName)
1148             {
1149                 *ppmk = moniker;
1150                 return S_OK;
1151             }
1152             chEaten = 0;
1153             hr = IMoniker_ParseDisplayName(moniker, pbc, NULL,
1154                                            (LPOLESTR)szDisplayName, &chEaten,
1155                                            &next_moniker);
1156             IMoniker_Release(moniker);
1157             if (FAILED(hr))
1158             {
1159                 *pchEaten = 0;
1160                 break;
1161             }
1162             moniker = next_moniker;
1163         }
1164     }
1165
1166     return hr;
1167 }
1168
1169 /***********************************************************************
1170  *        GetClassFile (OLE32.@)
1171  *
1172  * Retrieves the class ID associated with the given filename.
1173  *
1174  * PARAMS
1175  *  filePathName [I] Filename to retrieve the class ID for.
1176  *  pclsid       [O] Address that receives the class ID for the file.
1177  *
1178  * RETURNS
1179  *  Success: S_OK.
1180  *  Failure: Any HRESULT code.
1181  */
1182 HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
1183 {
1184     IStorage *pstg=0;
1185     HRESULT res;
1186     int nbElm, length, i;
1187     LONG sizeProgId;
1188     LPOLESTR *pathDec=0,absFile=0,progId=0;
1189     LPWSTR extension;
1190     static const WCHAR bkslashW[] = {'\\',0};
1191     static const WCHAR dotW[] = {'.',0};
1192
1193     TRACE("%s, %p\n", debugstr_w(filePathName), pclsid);
1194
1195     /* if the file contain a storage object the return the CLSID written by IStorage_SetClass method*/
1196     if((StgIsStorageFile(filePathName))==S_OK){
1197
1198         res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
1199
1200         if (SUCCEEDED(res))
1201             res=ReadClassStg(pstg,pclsid);
1202
1203         IStorage_Release(pstg);
1204
1205         return res;
1206     }
1207     /* if the file is not a storage object then attemps to match various bits in the file against a
1208        pattern in the registry. this case is not frequently used ! so I present only the psodocode for
1209        this case
1210
1211      for(i=0;i<nFileTypes;i++)
1212
1213         for(i=0;j<nPatternsForType;j++){
1214
1215             PATTERN pat;
1216             HANDLE  hFile;
1217
1218             pat=ReadPatternFromRegistry(i,j);
1219             hFile=CreateFileW(filePathName,,,,,,hFile);
1220             SetFilePosition(hFile,pat.offset);
1221             ReadFile(hFile,buf,pat.size,&r,NULL);
1222             if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
1223
1224                 *pclsid=ReadCLSIDFromRegistry(i);
1225                 return S_OK;
1226             }
1227         }
1228      */
1229
1230     /* if the above strategies fail then search for the extension key in the registry */
1231
1232     /* get the last element (absolute file) in the path name */
1233     nbElm=FileMonikerImpl_DecomposePath(filePathName,&pathDec);
1234     absFile=pathDec[nbElm-1];
1235
1236     /* failed if the path represente a directory and not an absolute file name*/
1237     if (!lstrcmpW(absFile, bkslashW))
1238         return MK_E_INVALIDEXTENSION;
1239
1240     /* get the extension of the file */
1241     extension = NULL;
1242     length=lstrlenW(absFile);
1243     for(i = length-1; (i >= 0) && *(extension = &absFile[i]) != '.'; i--)
1244         /* nothing */;
1245
1246     if (!extension || !lstrcmpW(extension, dotW))
1247         return MK_E_INVALIDEXTENSION;
1248
1249     res=RegQueryValueW(HKEY_CLASSES_ROOT, extension, NULL, &sizeProgId);
1250
1251     /* get the progId associated to the extension */
1252     progId = CoTaskMemAlloc(sizeProgId);
1253     res = RegQueryValueW(HKEY_CLASSES_ROOT, extension, progId, &sizeProgId);
1254
1255     if (res==ERROR_SUCCESS)
1256         /* return the clsid associated to the progId */
1257         res= CLSIDFromProgID(progId,pclsid);
1258
1259     for(i=0; pathDec[i]!=NULL;i++)
1260         CoTaskMemFree(pathDec[i]);
1261     CoTaskMemFree(pathDec);
1262
1263     CoTaskMemFree(progId);
1264
1265     if (res==ERROR_SUCCESS)
1266         return res;
1267
1268     return MK_E_INVALIDEXTENSION;
1269 }
1270
1271 /***********************************************************************
1272  *        EnumMoniker_QueryInterface
1273  */
1274 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1275 {
1276     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1277
1278     TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1279
1280     /* validate arguments */
1281     if (ppvObject == NULL)
1282         return E_INVALIDARG;
1283
1284     *ppvObject = NULL;
1285
1286     if (IsEqualIID(&IID_IUnknown, riid))
1287         *ppvObject = (IEnumMoniker*)This;
1288     else
1289         if (IsEqualIID(&IID_IEnumMoniker, riid))
1290             *ppvObject = (IEnumMoniker*)This;
1291
1292     if ((*ppvObject)==NULL)
1293         return E_NOINTERFACE;
1294
1295     IEnumMoniker_AddRef(iface);
1296
1297     return S_OK;
1298 }
1299
1300 /***********************************************************************
1301  *        EnumMoniker_AddRef
1302  */
1303 static ULONG   WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1304 {
1305     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1306
1307     TRACE("(%p)\n",This);
1308
1309     return InterlockedIncrement(&This->ref);
1310 }
1311
1312 /***********************************************************************
1313  *        EnumMoniker_release
1314  */
1315 static ULONG   WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1316 {
1317     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1318     ULONG ref;
1319
1320     TRACE("(%p)\n",This);
1321
1322     ref = InterlockedDecrement(&This->ref);
1323
1324     /* uninitialize rot structure if there's no more reference to it*/
1325     if (ref == 0)
1326     {
1327         ULONG i;
1328
1329         TRACE("(%p) Deleting\n",This);
1330
1331         for (i = 0; i < This->moniker_list->size; i++)
1332             HeapFree(GetProcessHeap(), 0, This->moniker_list->interfaces[i]);
1333         HeapFree(GetProcessHeap(), 0, This->moniker_list);
1334         HeapFree(GetProcessHeap(), 0, This);
1335     }
1336
1337     return ref;
1338 }
1339 /***********************************************************************
1340  *        EnmumMoniker_Next
1341  */
1342 static HRESULT   WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched)
1343 {
1344     ULONG i;
1345     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1346     HRESULT hr = S_OK;
1347
1348     TRACE("(%p) TabCurrentPos %d Tablastindx %d\n", This, This->pos, This->moniker_list->size);
1349
1350     /* retrieve the requested number of moniker from the current position */
1351     for(i = 0; (This->pos < This->moniker_list->size) && (i < celt); i++)
1352     {
1353         IStream *stream;
1354         hr = create_stream_on_mip_ro(This->moniker_list->interfaces[This->pos++], &stream);
1355         if (hr != S_OK) break;
1356         hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]);
1357         IStream_Release(stream);
1358         if (hr != S_OK) break;
1359     }
1360
1361     if (pceltFetched != NULL)
1362         *pceltFetched= i;
1363
1364     if (hr != S_OK)
1365         return hr;
1366
1367     if (i == celt)
1368         return S_OK;
1369     else
1370         return S_FALSE;
1371
1372 }
1373
1374 /***********************************************************************
1375  *        EnmumMoniker_Skip
1376  */
1377 static HRESULT   WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt)
1378 {
1379     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1380
1381     TRACE("(%p)\n",This);
1382
1383     if  (This->pos + celt >= This->moniker_list->size)
1384         return S_FALSE;
1385
1386     This->pos += celt;
1387
1388     return S_OK;
1389 }
1390
1391 /***********************************************************************
1392  *        EnmumMoniker_Reset
1393  */
1394 static HRESULT   WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
1395 {
1396     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1397
1398     This->pos = 0;      /* set back to start of list */
1399
1400     TRACE("(%p)\n",This);
1401
1402     return S_OK;
1403 }
1404
1405 /***********************************************************************
1406  *        EnmumMoniker_Clone
1407  */
1408 static HRESULT   WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)
1409 {
1410     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1411     InterfaceList *moniker_list;
1412     ULONG i;
1413
1414     TRACE("(%p)\n",This);
1415
1416     *ppenum = NULL;
1417
1418     moniker_list = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceList, interfaces[This->moniker_list->size]));
1419     if (!moniker_list)
1420         return E_OUTOFMEMORY;
1421
1422     moniker_list->size = This->moniker_list->size;
1423     for (i = 0; i < This->moniker_list->size; i++)
1424     {
1425         SIZE_T size = FIELD_OFFSET(InterfaceData, abData[This->moniker_list->interfaces[i]->ulCntData]);
1426         moniker_list->interfaces[i] = HeapAlloc(GetProcessHeap(), 0, size);
1427         if (!moniker_list->interfaces[i])
1428         {
1429             ULONG end = i;
1430             for (i = 0; i < end; i++)
1431                 HeapFree(GetProcessHeap(), 0, moniker_list->interfaces[i]);
1432             HeapFree(GetProcessHeap(), 0, moniker_list);
1433             return E_OUTOFMEMORY;
1434         }
1435         memcpy(moniker_list->interfaces[i], This->moniker_list->interfaces[i], size);
1436     }
1437
1438     /* copy the enum structure */ 
1439     return EnumMonikerImpl_CreateEnumROTMoniker(moniker_list, This->pos, ppenum);
1440 }
1441
1442 /* Virtual function table for the IEnumMoniker class. */
1443 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
1444 {
1445     EnumMonikerImpl_QueryInterface,
1446     EnumMonikerImpl_AddRef,
1447     EnumMonikerImpl_Release,
1448     EnumMonikerImpl_Next,
1449     EnumMonikerImpl_Skip,
1450     EnumMonikerImpl_Reset,
1451     EnumMonikerImpl_Clone
1452 };
1453
1454 /***********************************************************************
1455  *        EnumMonikerImpl_CreateEnumROTMoniker
1456  *        Used by EnumRunning to create the structure and EnumClone
1457  *        to copy the structure
1458  */
1459 static HRESULT WINAPI EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list,
1460                                                  ULONG current_pos,
1461                                                  IEnumMoniker **ppenumMoniker)
1462 {
1463     EnumMonikerImpl* This = NULL;
1464
1465     if (!ppenumMoniker)
1466         return E_INVALIDARG;
1467
1468     This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1469     if (!This) return E_OUTOFMEMORY;
1470
1471     TRACE("(%p)\n", This);
1472
1473     /* initialize the virtual table function */
1474     This->lpVtbl = &VT_EnumMonikerImpl;
1475
1476     /* the initial reference is set to "1" */
1477     This->ref = 1;                      /* set the ref count to one         */
1478     This->pos = current_pos;            /* Set the list start posn */
1479     This->moniker_list = moniker_list;
1480
1481     *ppenumMoniker =  (IEnumMoniker*)This;
1482
1483     return S_OK;
1484 }
1485
1486
1487 /* Shared implementation of moniker marshaler based on saving and loading of
1488  * monikers */
1489
1490 typedef struct MonikerMarshal
1491 {
1492     const IUnknownVtbl *lpVtbl;
1493     const IMarshalVtbl *lpVtblMarshal;
1494     
1495     LONG ref;
1496     IMoniker *moniker;
1497 } MonikerMarshal;
1498
1499 static inline MonikerMarshal *impl_from_IMarshal( IMarshal *iface )
1500 {
1501     return (MonikerMarshal *)((char*)iface - FIELD_OFFSET(MonikerMarshal, lpVtblMarshal));
1502 }
1503
1504 static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv)
1505 {
1506     MonikerMarshal *This = (MonikerMarshal *)iface;
1507     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1508     *ppv = NULL;
1509     if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid))
1510     {
1511         *ppv = &This->lpVtblMarshal;
1512         IUnknown_AddRef((IUnknown *)&This->lpVtblMarshal);
1513         return S_OK;
1514     }
1515     FIXME("No interface for %s\n", debugstr_guid(riid));
1516     return E_NOINTERFACE;
1517 }
1518
1519 static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface)
1520 {
1521     MonikerMarshal *This = (MonikerMarshal *)iface;
1522     return InterlockedIncrement(&This->ref);
1523 }
1524
1525 static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface)
1526 {
1527     MonikerMarshal *This = (MonikerMarshal *)iface;
1528     ULONG ref = InterlockedDecrement(&This->ref);
1529
1530     if (!ref) HeapFree(GetProcessHeap(), 0, This);
1531     return ref;
1532 }
1533
1534 static const IUnknownVtbl VT_MonikerMarshalInner =
1535 {
1536     MonikerMarshalInner_QueryInterface,
1537     MonikerMarshalInner_AddRef,
1538     MonikerMarshalInner_Release
1539 };
1540
1541 static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
1542 {
1543     MonikerMarshal *This = impl_from_IMarshal(iface);
1544     return IMoniker_QueryInterface(This->moniker, riid, ppv);
1545 }
1546
1547 static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface)
1548 {
1549     MonikerMarshal *This = impl_from_IMarshal(iface);
1550     return IMoniker_AddRef(This->moniker);
1551 }
1552
1553 static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface)
1554 {
1555     MonikerMarshal *This = impl_from_IMarshal(iface);
1556     return IMoniker_Release(This->moniker);
1557 }
1558
1559 static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass(
1560   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1561   void* pvDestContext, DWORD mshlflags, CLSID* pCid)
1562 {
1563     MonikerMarshal *This = impl_from_IMarshal(iface);
1564
1565     TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
1566         dwDestContext, pvDestContext, mshlflags, pCid);
1567
1568     return IMoniker_GetClassID(This->moniker, pCid);
1569 }
1570
1571 static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax(
1572   LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1573   void* pvDestContext, DWORD mshlflags, DWORD* pSize)
1574 {
1575     MonikerMarshal *This = impl_from_IMarshal(iface);
1576     HRESULT hr;
1577     ULARGE_INTEGER size;
1578
1579     TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
1580         dwDestContext, pvDestContext, mshlflags, pSize);
1581
1582     hr = IMoniker_GetSizeMax(This->moniker, &size);
1583     if (hr == S_OK)
1584         *pSize = (DWORD)size.QuadPart;
1585     return hr;
1586 }
1587
1588 static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm, 
1589     REFIID riid, void* pv, DWORD dwDestContext,
1590     void* pvDestContext, DWORD mshlflags)
1591 {
1592     MonikerMarshal *This = impl_from_IMarshal(iface);
1593
1594     TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv,
1595         dwDestContext, pvDestContext, mshlflags);
1596
1597     return IMoniker_Save(This->moniker, pStm, FALSE);
1598 }
1599
1600 static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
1601 {
1602     MonikerMarshal *This = impl_from_IMarshal(iface);
1603     HRESULT hr;
1604
1605     TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
1606
1607     hr = IMoniker_Load(This->moniker, pStm);
1608     if (hr == S_OK)
1609         hr = IMoniker_QueryInterface(This->moniker, riid, ppv);
1610     return hr;
1611 }
1612
1613 static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
1614 {
1615     TRACE("()\n");
1616     /* can't release a state-based marshal as nothing on server side to
1617      * release */
1618     return S_OK;
1619 }
1620
1621 static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)
1622 {
1623     TRACE("()\n");
1624     /* can't disconnect a state-based marshal as nothing on server side to
1625      * disconnect from */
1626     return S_OK;
1627 }
1628
1629 static const IMarshalVtbl VT_MonikerMarshal =
1630 {
1631     MonikerMarshal_QueryInterface,
1632     MonikerMarshal_AddRef,
1633     MonikerMarshal_Release,
1634     MonikerMarshal_GetUnmarshalClass,
1635     MonikerMarshal_GetMarshalSizeMax,
1636     MonikerMarshal_MarshalInterface,
1637     MonikerMarshal_UnmarshalInterface,
1638     MonikerMarshal_ReleaseMarshalData,
1639     MonikerMarshal_DisconnectObject
1640 };
1641
1642 HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer)
1643 {
1644     MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1645     if (!This) return E_OUTOFMEMORY;
1646
1647     This->lpVtbl = &VT_MonikerMarshalInner;
1648     This->lpVtblMarshal = &VT_MonikerMarshal;
1649     This->ref = 1;
1650     This->moniker = inner;
1651
1652     *outer = (IUnknown *)&This->lpVtbl;
1653     return S_OK;
1654 }
1655
1656 void * __RPC_USER MIDL_user_allocate(size_t size)
1657 {
1658     return HeapAlloc(GetProcessHeap(), 0, size);
1659 }
1660
1661 void __RPC_USER MIDL_user_free(void *p)
1662 {
1663     HeapFree(GetProcessHeap(), 0, p);
1664 }