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