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