d3dx10: Add support for ID3DX10ThreadPump parameter in D3DX10CreateTextureFromFileW.
[wine.git] / dlls / ole32 / moniker.c
blob09266a33aba5f2016860b58ff80fd9d37aafd1ac
1 /*
2 * Monikers
4 * Copyright 1998 Marcus Meissner
5 * Copyright 1999 Noomen Hamza
6 * Copyright 2005 Robert Shearman (for CodeWeavers)
7 * Copyright 2007 Robert Shearman
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.
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.
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
24 #include <stdarg.h>
25 #include <string.h>
27 #define COBJMACROS
29 #include "wine/list.h"
30 #include "wine/debug.h"
32 #include "compobj_private.h"
33 #include "moniker.h"
34 #include "irot.h"
35 #include "pathcch.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39 /* Combase exports */
40 BOOL WINAPI InternalIsProcessInitialized(void);
41 HRESULT WINAPI InternalIrotRegister(const MonikerComparisonData *moniker_data,
42 const InterfaceData *object, const InterfaceData *moniker,
43 const FILETIME *time, DWORD flags, IrotCookie *cookie, IrotContextHandle *ctxt_handle);
44 HRESULT WINAPI InternalIrotIsRunning(const MonikerComparisonData *moniker_data);
45 HRESULT WINAPI InternalIrotGetObject(const MonikerComparisonData *moniker_data, PInterfaceData *obj,
46 IrotCookie *cookie);
47 HRESULT WINAPI InternalIrotNoteChangeTime(IrotCookie cookie, const FILETIME *time);
48 HRESULT WINAPI InternalIrotGetTimeOfLastChange(const MonikerComparisonData *moniker_data, FILETIME *time);
49 HRESULT WINAPI InternalIrotEnumRunning(PInterfaceList *list);
50 HRESULT WINAPI InternalIrotRevoke(IrotCookie cookie, IrotContextHandle *ctxt_handle, PInterfaceData *object,
51 PInterfaceData *moniker);
53 /* define the structure of the running object table elements */
54 struct rot_entry
56 struct list entry;
57 InterfaceData* object; /* marshaled running object*/
58 MonikerComparisonData* moniker_data; /* moniker comparison data that identifies this object */
59 DWORD cookie; /* cookie identifying this object */
60 FILETIME last_modified;
61 IrotContextHandle ctxt_handle;
64 /* define the RunningObjectTableImpl structure */
65 typedef struct RunningObjectTableImpl
67 IRunningObjectTable IRunningObjectTable_iface;
68 struct list rot; /* list of ROT entries */
69 CRITICAL_SECTION lock;
70 } RunningObjectTableImpl;
72 /* define the EnumMonikerImpl structure */
73 typedef struct EnumMonikerImpl
75 IEnumMoniker IEnumMoniker_iface;
76 LONG ref;
78 InterfaceList *moniker_list;
79 ULONG pos;
80 } EnumMonikerImpl;
82 static inline RunningObjectTableImpl *impl_from_IRunningObjectTable(IRunningObjectTable *iface)
84 return CONTAINING_RECORD(iface, RunningObjectTableImpl, IRunningObjectTable_iface);
87 static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface)
89 return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface);
92 /* IEnumMoniker Local functions*/
93 static HRESULT EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list,
94 ULONG pos, IEnumMoniker **ppenumMoniker);
96 static HRESULT create_stream_on_mip_ro(const InterfaceData *mip, IStream **stream)
98 HGLOBAL hglobal = GlobalAlloc(0, mip->ulCntData);
99 void *pv = GlobalLock(hglobal);
100 memcpy(pv, mip->abData, mip->ulCntData);
101 GlobalUnlock(hglobal);
102 return CreateStreamOnHGlobal(hglobal, TRUE, stream);
105 static void rot_entry_delete(struct rot_entry *rot_entry)
107 if (rot_entry->cookie)
109 InterfaceData *object = NULL;
110 InterfaceData *moniker = NULL;
112 InternalIrotRevoke(rot_entry->cookie, &rot_entry->ctxt_handle, &object, &moniker);
113 MIDL_user_free(object);
114 if (moniker)
116 IStream *stream;
117 HRESULT hr;
118 hr = create_stream_on_mip_ro(moniker, &stream);
119 if (hr == S_OK)
121 CoReleaseMarshalData(stream);
122 IStream_Release(stream);
125 MIDL_user_free(moniker);
127 if (rot_entry->object)
129 IStream *stream;
130 HRESULT hr;
131 hr = create_stream_on_mip_ro(rot_entry->object, &stream);
132 if (hr == S_OK)
134 CoReleaseMarshalData(stream);
135 IStream_Release(stream);
138 HeapFree(GetProcessHeap(), 0, rot_entry->object);
139 HeapFree(GetProcessHeap(), 0, rot_entry->moniker_data);
140 HeapFree(GetProcessHeap(), 0, rot_entry);
143 /* moniker_data must be freed with HeapFree when no longer in use */
144 static HRESULT get_moniker_comparison_data(IMoniker *pMoniker, MonikerComparisonData **moniker_data)
146 HRESULT hr;
147 IROTData *pROTData = NULL;
148 hr = IMoniker_QueryInterface(pMoniker, &IID_IROTData, (void *)&pROTData);
149 if (SUCCEEDED(hr))
151 ULONG size = ROT_COMPARE_MAX;
152 *moniker_data = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MonikerComparisonData, abData[size]));
153 if (!*moniker_data)
155 IROTData_Release(pROTData);
156 return E_OUTOFMEMORY;
158 hr = IROTData_GetComparisonData(pROTData, (*moniker_data)->abData, size, &size);
159 IROTData_Release(pROTData);
160 if (hr != S_OK)
162 ERR("Failed to copy comparison data into buffer, hr = %#lx\n", hr);
163 HeapFree(GetProcessHeap(), 0, *moniker_data);
164 return hr;
166 (*moniker_data)->ulCntData = size;
168 else
170 IBindCtx *pbc;
171 LPOLESTR pszDisplayName;
172 CLSID clsid;
173 int len;
175 TRACE("generating comparison data from display name\n");
177 hr = CreateBindCtx(0, &pbc);
178 if (FAILED(hr))
179 return hr;
180 hr = IMoniker_GetDisplayName(pMoniker, pbc, NULL, &pszDisplayName);
181 IBindCtx_Release(pbc);
182 if (FAILED(hr))
183 return hr;
184 hr = IMoniker_GetClassID(pMoniker, &clsid);
185 if (FAILED(hr))
187 CoTaskMemFree(pszDisplayName);
188 return hr;
191 len = lstrlenW(pszDisplayName);
192 *moniker_data = HeapAlloc(GetProcessHeap(), 0,
193 FIELD_OFFSET(MonikerComparisonData, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)]));
194 if (!*moniker_data)
196 CoTaskMemFree(pszDisplayName);
197 return E_OUTOFMEMORY;
199 (*moniker_data)->ulCntData = sizeof(CLSID) + (len+1)*sizeof(WCHAR);
201 memcpy(&(*moniker_data)->abData[0], &clsid, sizeof(clsid));
202 memcpy(&(*moniker_data)->abData[sizeof(clsid)], pszDisplayName, (len+1)*sizeof(WCHAR));
203 CoTaskMemFree(pszDisplayName);
205 return S_OK;
208 static HRESULT reduce_moniker(IMoniker *pmk, IBindCtx *pbc, IMoniker **pmkReduced)
210 IBindCtx *pbcNew = NULL;
211 HRESULT hr;
212 if (!pbc)
214 hr = CreateBindCtx(0, &pbcNew);
215 if (FAILED(hr))
216 return hr;
217 pbc = pbcNew;
219 hr = IMoniker_Reduce(pmk, pbc, MKRREDUCE_ALL, NULL, pmkReduced);
220 if (FAILED(hr))
221 ERR("reducing moniker failed with error %#lx.\n", hr);
222 if (pbcNew) IBindCtx_Release(pbcNew);
223 return hr;
226 /***********************************************************************
227 * RunningObjectTable_QueryInterface
229 static HRESULT WINAPI
230 RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,
231 REFIID riid,void** ppvObject)
233 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
235 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
237 /* validate arguments */
239 if (ppvObject==0)
240 return E_INVALIDARG;
242 *ppvObject = 0;
244 if (IsEqualIID(&IID_IUnknown, riid) ||
245 IsEqualIID(&IID_IRunningObjectTable, riid))
246 *ppvObject = &This->IRunningObjectTable_iface;
248 if ((*ppvObject)==0)
249 return E_NOINTERFACE;
251 IRunningObjectTable_AddRef(iface);
253 return S_OK;
256 static ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable *iface)
258 TRACE("%p\n", iface);
260 return 2;
263 static ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable *iface)
265 TRACE("%p\n", iface);
267 return 1;
270 /***********************************************************************
271 * RunningObjectTable_Register
273 * PARAMS
274 * grfFlags [in] Registration options
275 * punkObject [in] the object being registered
276 * pmkObjectName [in] the moniker of the object being registered
277 * pdwRegister [out] the value identifying the registration
279 static HRESULT WINAPI
280 RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD flags,
281 IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister)
283 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
284 struct rot_entry *rot_entry;
285 HRESULT hr = S_OK;
286 IStream *pStream = NULL;
287 DWORD mshlflags;
288 IBindCtx *pbc;
289 InterfaceData *moniker = NULL;
291 TRACE("%p, %#lx, %p, %p, %p\n", iface, flags, punkObject, pmkObjectName, pdwRegister);
293 if (flags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT))
295 ERR("Invalid flags: %#lx\n", flags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT));
296 return E_INVALIDARG;
299 if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
300 return E_INVALIDARG;
302 rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));
303 if (!rot_entry)
304 return E_OUTOFMEMORY;
306 /* marshal object */
307 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
308 if (hr != S_OK)
310 rot_entry_delete(rot_entry);
311 return hr;
313 mshlflags = flags & ROTFLAGS_REGISTRATIONKEEPSALIVE ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK;
314 hr = CoMarshalInterface(pStream, &IID_IUnknown, punkObject, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, mshlflags);
315 /* FIXME: a cleaner way would be to create an IStream class that writes
316 * directly to an MInterfacePointer */
317 if (hr == S_OK)
319 HGLOBAL hglobal;
320 hr = GetHGlobalFromStream(pStream, &hglobal);
321 if (hr == S_OK)
323 SIZE_T size = GlobalSize(hglobal);
324 const void *pv = GlobalLock(hglobal);
325 rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
326 rot_entry->object->ulCntData = size;
327 memcpy(rot_entry->object->abData, pv, size);
328 GlobalUnlock(hglobal);
331 IStream_Release(pStream);
332 if (hr != S_OK)
334 rot_entry_delete(rot_entry);
335 return hr;
338 hr = CreateBindCtx(0, &pbc);
339 if (FAILED(hr))
341 rot_entry_delete(rot_entry);
342 return hr;
345 hr = reduce_moniker(pmkObjectName, pbc, &pmkObjectName);
346 if (FAILED(hr))
348 rot_entry_delete(rot_entry);
349 IBindCtx_Release(pbc);
350 return hr;
353 hr = IMoniker_GetTimeOfLastChange(pmkObjectName, pbc, NULL,
354 &rot_entry->last_modified);
355 IBindCtx_Release(pbc);
356 if (FAILED(hr))
358 CoFileTimeNow(&rot_entry->last_modified);
359 hr = S_OK;
362 hr = get_moniker_comparison_data(pmkObjectName,
363 &rot_entry->moniker_data);
364 if (hr != S_OK)
366 rot_entry_delete(rot_entry);
367 IMoniker_Release(pmkObjectName);
368 return hr;
371 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
372 if (hr != S_OK)
374 rot_entry_delete(rot_entry);
375 IMoniker_Release(pmkObjectName);
376 return hr;
378 /* marshal moniker */
379 hr = CoMarshalInterface(pStream, &IID_IMoniker, (IUnknown *)pmkObjectName,
380 MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG);
381 /* FIXME: a cleaner way would be to create an IStream class that writes
382 * directly to an MInterfacePointer */
383 if (hr == S_OK)
385 HGLOBAL hglobal;
386 hr = GetHGlobalFromStream(pStream, &hglobal);
387 if (hr == S_OK)
389 SIZE_T size = GlobalSize(hglobal);
390 const void *pv = GlobalLock(hglobal);
391 moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[size]));
392 moniker->ulCntData = size;
393 memcpy(moniker->abData, pv, size);
394 GlobalUnlock(hglobal);
397 IStream_Release(pStream);
398 IMoniker_Release(pmkObjectName);
399 if (hr != S_OK)
401 HeapFree(GetProcessHeap(), 0, moniker);
402 rot_entry_delete(rot_entry);
403 return hr;
406 hr = InternalIrotRegister(rot_entry->moniker_data, rot_entry->object, moniker,
407 &rot_entry->last_modified, flags, &rot_entry->cookie, &rot_entry->ctxt_handle);
409 HeapFree(GetProcessHeap(), 0, moniker);
410 if (FAILED(hr))
412 rot_entry_delete(rot_entry);
413 return hr;
416 /* gives a registration identifier to the registered object*/
417 *pdwRegister = rot_entry->cookie;
419 EnterCriticalSection(&This->lock);
420 list_add_tail(&This->rot, &rot_entry->entry);
421 LeaveCriticalSection(&This->lock);
423 return hr;
426 /***********************************************************************
427 * RunningObjectTable_Revoke
429 * PARAMS
430 * dwRegister [in] Value identifying registration to be revoked
432 static HRESULT WINAPI
433 RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister)
435 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
436 struct rot_entry *rot_entry;
438 TRACE("%p, %ld.\n", iface, dwRegister);
440 EnterCriticalSection(&This->lock);
441 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
443 if (rot_entry->cookie == dwRegister)
445 list_remove(&rot_entry->entry);
446 LeaveCriticalSection(&This->lock);
448 rot_entry_delete(rot_entry);
449 return S_OK;
452 LeaveCriticalSection(&This->lock);
454 return E_INVALIDARG;
457 /***********************************************************************
458 * RunningObjectTable_IsRunning
460 * PARAMS
461 * pmkObjectName [in] moniker of the object whose status is desired
463 static HRESULT WINAPI
464 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName)
466 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
467 MonikerComparisonData *moniker_data;
468 HRESULT hr;
469 const struct rot_entry *rot_entry;
471 TRACE("(%p,%p)\n",This,pmkObjectName);
473 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
474 if (FAILED(hr))
475 return hr;
476 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
477 IMoniker_Release(pmkObjectName);
478 if (hr != S_OK)
479 return hr;
481 hr = S_FALSE;
482 EnterCriticalSection(&This->lock);
483 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
485 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
486 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
488 hr = S_OK;
489 break;
492 LeaveCriticalSection(&This->lock);
494 if (hr == S_FALSE)
495 hr = InternalIrotIsRunning(moniker_data);
497 HeapFree(GetProcessHeap(), 0, moniker_data);
499 return hr;
502 /***********************************************************************
503 * RunningObjectTable_GetObject
505 * PARAMS
506 * pmkObjectName [in] Pointer to the moniker on the object
507 * ppunkObject [out] variable that receives the IUnknown interface pointer
509 static HRESULT WINAPI
510 RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
511 IMoniker *pmkObjectName, IUnknown **ppunkObject)
513 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
514 MonikerComparisonData *moniker_data;
515 InterfaceData *object = NULL;
516 IrotCookie cookie;
517 HRESULT hr;
518 struct rot_entry *rot_entry;
520 TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
522 if (ppunkObject == NULL)
523 return E_POINTER;
525 *ppunkObject = NULL;
527 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
528 if (FAILED(hr))
529 return hr;
530 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
531 IMoniker_Release(pmkObjectName);
532 if (hr != S_OK)
533 return hr;
535 EnterCriticalSection(&This->lock);
536 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
538 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
539 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
541 IStream *pStream;
542 hr = create_stream_on_mip_ro(rot_entry->object, &pStream);
543 if (hr == S_OK)
545 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
546 IStream_Release(pStream);
549 LeaveCriticalSection(&This->lock);
550 HeapFree(GetProcessHeap(), 0, moniker_data);
552 return hr;
555 LeaveCriticalSection(&This->lock);
557 TRACE("moniker unavailable locally, calling SCM\n");
559 hr = InternalIrotGetObject(moniker_data, &object, &cookie);
560 if (SUCCEEDED(hr))
562 IStream *pStream;
563 hr = create_stream_on_mip_ro(object, &pStream);
564 if (hr == S_OK)
566 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
567 IStream_Release(pStream);
570 else
571 WARN("Moniker unavailable, IrotGetObject returned %#lx\n", hr);
573 HeapFree(GetProcessHeap(), 0, moniker_data);
575 return hr;
578 /***********************************************************************
579 * RunningObjectTable_NoteChangeTime
581 * PARAMS
582 * dwRegister [in] Value identifying registration being updated
583 * pfiletime [in] Pointer to structure containing object's last change time
585 static HRESULT WINAPI
586 RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
587 DWORD dwRegister, FILETIME *pfiletime)
589 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
590 struct rot_entry *rot_entry;
591 HRESULT hr = E_INVALIDARG;
593 TRACE("%p, %ld, %p.\n", iface, dwRegister, pfiletime);
595 EnterCriticalSection(&This->lock);
596 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
598 if (rot_entry->cookie == dwRegister)
600 rot_entry->last_modified = *pfiletime;
601 LeaveCriticalSection(&This->lock);
603 hr = InternalIrotNoteChangeTime(dwRegister, pfiletime);
605 goto done;
608 LeaveCriticalSection(&This->lock);
610 done:
611 TRACE("-- %#lx\n", hr);
612 return hr;
615 /***********************************************************************
616 * RunningObjectTable_GetTimeOfLastChange
618 * PARAMS
619 * pmkObjectName [in] moniker of the object whose status is desired
620 * pfiletime [out] structure that receives object's last change time
622 static HRESULT WINAPI
623 RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
624 IMoniker *pmkObjectName, FILETIME *pfiletime)
626 HRESULT hr = MK_E_UNAVAILABLE;
627 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
628 MonikerComparisonData *moniker_data;
629 const struct rot_entry *rot_entry;
631 TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
633 if (pmkObjectName==NULL || pfiletime==NULL)
634 return E_INVALIDARG;
636 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
637 if (FAILED(hr))
638 return hr;
639 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
640 IMoniker_Release(pmkObjectName);
641 if (hr != S_OK)
642 return hr;
644 hr = MK_E_UNAVAILABLE;
646 EnterCriticalSection(&This->lock);
647 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
649 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
650 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
652 *pfiletime = rot_entry->last_modified;
653 hr = S_OK;
654 break;
657 LeaveCriticalSection(&This->lock);
659 if (hr != S_OK)
660 hr = InternalIrotGetTimeOfLastChange(moniker_data, pfiletime);
662 HeapFree(GetProcessHeap(), 0, moniker_data);
664 TRACE("-- %#lx\n", hr);
665 return hr;
668 /***********************************************************************
669 * RunningObjectTable_EnumRunning
671 * PARAMS
672 * ppenumMoniker [out] receives the IEnumMoniker interface pointer
674 static HRESULT WINAPI
675 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
676 IEnumMoniker **ppenumMoniker)
678 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
679 InterfaceList *interface_list = NULL;
680 HRESULT hr;
682 TRACE("(%p, %p)\n", This, ppenumMoniker);
684 *ppenumMoniker = NULL;
686 hr = InternalIrotEnumRunning(&interface_list);
687 if (SUCCEEDED(hr))
688 hr = EnumMonikerImpl_CreateEnumROTMoniker(interface_list, 0, ppenumMoniker);
690 return hr;
693 /* Virtual function table for the IRunningObjectTable class. */
694 static const IRunningObjectTableVtbl VT_RunningObjectTableImpl =
696 RunningObjectTableImpl_QueryInterface,
697 RunningObjectTableImpl_AddRef,
698 RunningObjectTableImpl_Release,
699 RunningObjectTableImpl_Register,
700 RunningObjectTableImpl_Revoke,
701 RunningObjectTableImpl_IsRunning,
702 RunningObjectTableImpl_GetObject,
703 RunningObjectTableImpl_NoteChangeTime,
704 RunningObjectTableImpl_GetTimeOfLastChange,
705 RunningObjectTableImpl_EnumRunning
708 static RunningObjectTableImpl rot =
710 .IRunningObjectTable_iface.lpVtbl = &VT_RunningObjectTableImpl,
711 .lock.LockCount = -1,
712 .rot = LIST_INIT(rot.rot),
715 /***********************************************************************
716 * GetRunningObjectTable (OLE32.@)
718 HRESULT WINAPI GetRunningObjectTable(DWORD reserved, IRunningObjectTable **ret)
720 TRACE("%#lx, %p\n", reserved, ret);
722 if (reserved!=0)
723 return E_UNEXPECTED;
725 if (!InternalIsProcessInitialized())
726 return CO_E_NOTINITIALIZED;
728 *ret = &rot.IRunningObjectTable_iface;
729 IRunningObjectTable_AddRef(*ret);
731 return S_OK;
734 /***********************************************************************
735 * DestroyRunningObjectTable (ole32.@)
737 void WINAPI DestroyRunningObjectTable(void)
739 struct rot_entry *rot_entry, *cursor2;
741 TRACE("\n");
743 EnterCriticalSection(&rot.lock);
744 LIST_FOR_EACH_ENTRY_SAFE(rot_entry, cursor2, &rot.rot, struct rot_entry, entry)
746 list_remove(&rot_entry->entry);
747 rot_entry_delete(rot_entry);
749 LeaveCriticalSection(&rot.lock);
752 static HRESULT get_moniker_for_progid_display_name(LPBC pbc,
753 LPCOLESTR szDisplayName,
754 LPDWORD pchEaten,
755 LPMONIKER *ppmk)
757 CLSID clsid;
758 HRESULT hr;
759 LPWSTR progid;
760 LPCWSTR start = szDisplayName;
761 LPCWSTR end;
762 int len;
763 IMoniker *class_moniker;
765 if (*start == '@')
766 start++;
768 /* find end delimiter */
769 for (end = start; *end; end++)
770 if (*end == ':')
771 break;
773 len = end - start;
775 /* must start with '@' or have a ':' somewhere and mustn't be one character
776 * long (since that looks like an absolute path) */
777 if (((start == szDisplayName) && (*end == '\0')) || (len <= 1))
778 return MK_E_SYNTAX;
780 progid = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
781 if (progid)
783 memcpy(progid, start, len * sizeof(WCHAR));
784 progid[len] = '\0';
786 hr = CLSIDFromProgID(progid, &clsid);
787 HeapFree(GetProcessHeap(), 0, progid);
788 if (FAILED(hr))
789 return MK_E_SYNTAX;
791 hr = CreateClassMoniker(&clsid, &class_moniker);
792 if (SUCCEEDED(hr))
794 IParseDisplayName *pdn;
795 hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
796 &IID_IParseDisplayName, (void **)&pdn);
797 /* fallback to using IClassFactory to get IParseDisplayName -
798 * adsldp.dll depends on this */
799 if (FAILED(hr))
801 IClassFactory *pcf;
802 hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
803 &IID_IClassFactory, (void **)&pcf);
804 if (SUCCEEDED(hr))
806 hr = IClassFactory_CreateInstance(pcf, NULL,
807 &IID_IParseDisplayName,
808 (void **)&pdn);
809 IClassFactory_Release(pcf);
812 IMoniker_Release(class_moniker);
813 if (SUCCEEDED(hr))
815 hr = IParseDisplayName_ParseDisplayName(pdn, pbc,
816 (LPOLESTR)szDisplayName,
817 pchEaten, ppmk);
818 IParseDisplayName_Release(pdn);
821 return hr;
824 /******************************************************************************
825 * MkParseDisplayName [OLE32.@]
827 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
828 LPDWORD pchEaten, LPMONIKER *ppmk)
830 HRESULT hr = MK_E_SYNTAX;
831 IMoniker *moniker;
832 DWORD chEaten;
834 TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
836 if (!pbc || !IsValidInterface((LPUNKNOWN) pbc))
837 return E_INVALIDARG;
839 if (!szDisplayName || !*szDisplayName)
840 return E_INVALIDARG;
842 if (!pchEaten || !ppmk)
843 return E_INVALIDARG;
845 *pchEaten = 0;
846 *ppmk = NULL;
848 if (!wcsnicmp(szDisplayName, L"clsid:", 6))
850 hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
851 if (FAILED(hr) && (hr != MK_E_SYNTAX))
852 return hr;
854 else
856 hr = get_moniker_for_progid_display_name(pbc, szDisplayName, &chEaten, &moniker);
857 if (FAILED(hr) && (hr != MK_E_SYNTAX))
858 return hr;
861 if (FAILED(hr))
863 hr = FileMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
864 if (FAILED(hr) && (hr != MK_E_SYNTAX))
865 return hr;
868 if (SUCCEEDED(hr))
870 while (TRUE)
872 IMoniker *next_moniker;
873 *pchEaten += chEaten;
874 szDisplayName += chEaten;
875 if (!*szDisplayName)
877 *ppmk = moniker;
878 return S_OK;
880 chEaten = 0;
881 hr = IMoniker_ParseDisplayName(moniker, pbc, NULL,
882 (LPOLESTR)szDisplayName, &chEaten,
883 &next_moniker);
884 IMoniker_Release(moniker);
885 if (FAILED(hr))
887 *pchEaten = 0;
888 break;
890 moniker = next_moniker;
894 return hr;
897 /***********************************************************************
898 * GetClassFile (OLE32.@)
900 * Retrieves the class ID associated with the given filename.
902 * PARAMS
903 * filePathName [I] Filename to retrieve the class ID for.
904 * pclsid [O] Address that receives the class ID for the file.
906 * RETURNS
907 * Success: S_OK.
908 * Failure: Any HRESULT code.
910 HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
912 IStorage *pstg=0;
913 HRESULT res;
914 LONG sizeProgId, ret;
915 LPOLESTR progId=0;
916 const WCHAR *extension;
918 TRACE("%s, %p\n", debugstr_w(filePathName), pclsid);
920 /* if the file contain a storage object the return the CLSID written by IStorage_SetClass method*/
921 if((StgIsStorageFile(filePathName))==S_OK){
923 res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
925 if (SUCCEEDED(res)) {
926 res=ReadClassStg(pstg,pclsid);
927 IStorage_Release(pstg);
930 return res;
932 /* If the file is not a storage object then attempt to match various bits in the file against a
933 pattern in the registry. This case is not frequently used, so I present only the pseudocode for
934 this case.
936 for(i=0;i<nFileTypes;i++)
938 for(i=0;j<nPatternsForType;j++){
940 PATTERN pat;
941 HANDLE hFile;
943 pat=ReadPatternFromRegistry(i,j);
944 hFile=CreateFileW(filePathName,,,,,,hFile);
945 SetFilePosition(hFile,pat.offset);
946 ReadFile(hFile,buf,pat.size,&r,NULL);
947 if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
949 *pclsid=ReadCLSIDFromRegistry(i);
950 return S_OK;
955 /* if the above strategies fail then search for the extension key in the registry */
957 res = PathCchFindExtension(filePathName, PATHCCH_MAX_CCH, &extension);
958 if (FAILED(res) || !extension || !*extension || !wcscmp(extension, L"."))
959 return MK_E_INVALIDEXTENSION;
961 ret = RegQueryValueW(HKEY_CLASSES_ROOT, extension, NULL, &sizeProgId);
962 if (!ret) {
963 /* get the progId associated to the extension */
964 progId = CoTaskMemAlloc(sizeProgId);
965 ret = RegQueryValueW(HKEY_CLASSES_ROOT, extension, progId, &sizeProgId);
966 if (!ret)
967 /* return the clsid associated to the progId */
968 res = CLSIDFromProgID(progId, pclsid);
969 else
970 res = HRESULT_FROM_WIN32(ret);
971 CoTaskMemFree(progId);
973 else
974 res = HRESULT_FROM_WIN32(ret);
976 return res != S_OK ? MK_E_INVALIDEXTENSION : res;
979 /***********************************************************************
980 * EnumMoniker_QueryInterface
982 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
984 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
986 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
988 /* validate arguments */
989 if (ppvObject == NULL)
990 return E_INVALIDARG;
992 *ppvObject = NULL;
994 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
995 *ppvObject = &This->IEnumMoniker_iface;
996 else
997 return E_NOINTERFACE;
999 IEnumMoniker_AddRef(iface);
1000 return S_OK;
1003 /***********************************************************************
1004 * EnumMoniker_AddRef
1006 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1008 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1010 TRACE("(%p)\n",This);
1012 return InterlockedIncrement(&This->ref);
1015 /***********************************************************************
1016 * EnumMoniker_release
1018 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1020 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1021 ULONG ref;
1023 TRACE("(%p)\n",This);
1025 ref = InterlockedDecrement(&This->ref);
1027 /* uninitialize ROT structure if there are no more references to it */
1028 if (ref == 0)
1030 ULONG i;
1032 TRACE("(%p) Deleting\n",This);
1034 for (i = 0; i < This->moniker_list->size; i++)
1035 HeapFree(GetProcessHeap(), 0, This->moniker_list->interfaces[i]);
1036 HeapFree(GetProcessHeap(), 0, This->moniker_list);
1037 HeapFree(GetProcessHeap(), 0, This);
1040 return ref;
1042 /***********************************************************************
1043 * EnumMoniker_Next
1045 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched)
1047 ULONG i;
1048 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1049 HRESULT hr = S_OK;
1051 TRACE("%p, %lu, %p, %p.\n", iface, celt, rgelt, pceltFetched);
1053 /* retrieve the requested number of moniker from the current position */
1054 for(i = 0; (This->pos < This->moniker_list->size) && (i < celt); i++)
1056 IStream *stream;
1057 hr = create_stream_on_mip_ro(This->moniker_list->interfaces[This->pos++], &stream);
1058 if (hr != S_OK) break;
1059 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]);
1060 IStream_Release(stream);
1061 if (hr != S_OK) break;
1064 if (pceltFetched != NULL)
1065 *pceltFetched= i;
1067 if (hr != S_OK)
1068 return hr;
1070 if (i == celt)
1071 return S_OK;
1072 else
1073 return S_FALSE;
1077 /***********************************************************************
1078 * EnumMoniker_Skip
1080 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt)
1082 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1084 TRACE("(%p)\n",This);
1086 if (This->pos + celt >= This->moniker_list->size)
1087 return S_FALSE;
1089 This->pos += celt;
1091 return S_OK;
1094 /***********************************************************************
1095 * EnumMoniker_Reset
1097 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
1099 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1101 This->pos = 0; /* set back to start of list */
1103 TRACE("(%p)\n",This);
1105 return S_OK;
1108 /***********************************************************************
1109 * EnumMoniker_Clone
1111 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)
1113 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1114 InterfaceList *moniker_list;
1115 ULONG i;
1117 TRACE("(%p)\n",This);
1119 *ppenum = NULL;
1121 moniker_list = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceList, interfaces[This->moniker_list->size]));
1122 if (!moniker_list)
1123 return E_OUTOFMEMORY;
1125 moniker_list->size = This->moniker_list->size;
1126 for (i = 0; i < This->moniker_list->size; i++)
1128 SIZE_T size = FIELD_OFFSET(InterfaceData, abData[This->moniker_list->interfaces[i]->ulCntData]);
1129 moniker_list->interfaces[i] = HeapAlloc(GetProcessHeap(), 0, size);
1130 if (!moniker_list->interfaces[i])
1132 ULONG end = i;
1133 for (i = 0; i < end; i++)
1134 HeapFree(GetProcessHeap(), 0, moniker_list->interfaces[i]);
1135 HeapFree(GetProcessHeap(), 0, moniker_list);
1136 return E_OUTOFMEMORY;
1138 memcpy(moniker_list->interfaces[i], This->moniker_list->interfaces[i], size);
1141 /* copy the enum structure */
1142 return EnumMonikerImpl_CreateEnumROTMoniker(moniker_list, This->pos, ppenum);
1145 /* Virtual function table for the IEnumMoniker class. */
1146 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
1148 EnumMonikerImpl_QueryInterface,
1149 EnumMonikerImpl_AddRef,
1150 EnumMonikerImpl_Release,
1151 EnumMonikerImpl_Next,
1152 EnumMonikerImpl_Skip,
1153 EnumMonikerImpl_Reset,
1154 EnumMonikerImpl_Clone
1157 /***********************************************************************
1158 * EnumMonikerImpl_CreateEnumROTMoniker
1159 * Used by EnumRunning to create the structure and EnumClone
1160 * to copy the structure
1162 static HRESULT EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list,
1163 ULONG current_pos,
1164 IEnumMoniker **ppenumMoniker)
1166 EnumMonikerImpl* This = NULL;
1168 if (!ppenumMoniker)
1169 return E_INVALIDARG;
1171 This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1172 if (!This) return E_OUTOFMEMORY;
1174 TRACE("(%p)\n", This);
1176 /* initialize the virtual table function */
1177 This->IEnumMoniker_iface.lpVtbl = &VT_EnumMonikerImpl;
1179 /* the initial reference is set to "1" */
1180 This->ref = 1; /* set the ref count to one */
1181 This->pos = current_pos; /* Set the list start posn */
1182 This->moniker_list = moniker_list;
1184 *ppenumMoniker = &This->IEnumMoniker_iface;
1186 return S_OK;
1190 /* Shared implementation of moniker marshaler based on saving and loading of
1191 * monikers */
1193 typedef struct MonikerMarshal
1195 IUnknown IUnknown_iface;
1196 IMarshal IMarshal_iface;
1198 LONG ref;
1199 IMoniker *moniker;
1200 } MonikerMarshal;
1202 static inline MonikerMarshal *impl_from_IUnknown(IUnknown *iface)
1204 return CONTAINING_RECORD(iface, MonikerMarshal, IUnknown_iface);
1207 static inline MonikerMarshal *impl_from_IMarshal( IMarshal *iface )
1209 return CONTAINING_RECORD(iface, MonikerMarshal, IMarshal_iface);
1212 static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv)
1214 MonikerMarshal *This = impl_from_IUnknown(iface);
1215 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1216 *ppv = NULL;
1217 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid))
1219 *ppv = &This->IMarshal_iface;
1220 IMarshal_AddRef(&This->IMarshal_iface);
1221 return S_OK;
1223 FIXME("No interface for %s\n", debugstr_guid(riid));
1224 return E_NOINTERFACE;
1227 static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface)
1229 MonikerMarshal *This = impl_from_IUnknown(iface);
1230 return InterlockedIncrement(&This->ref);
1233 static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface)
1235 MonikerMarshal *This = impl_from_IUnknown(iface);
1236 ULONG ref = InterlockedDecrement(&This->ref);
1238 if (!ref) HeapFree(GetProcessHeap(), 0, This);
1239 return ref;
1242 static const IUnknownVtbl VT_MonikerMarshalInner =
1244 MonikerMarshalInner_QueryInterface,
1245 MonikerMarshalInner_AddRef,
1246 MonikerMarshalInner_Release
1249 static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
1251 MonikerMarshal *This = impl_from_IMarshal(iface);
1252 return IMoniker_QueryInterface(This->moniker, riid, ppv);
1255 static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface)
1257 MonikerMarshal *This = impl_from_IMarshal(iface);
1258 return IMoniker_AddRef(This->moniker);
1261 static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface)
1263 MonikerMarshal *This = impl_from_IMarshal(iface);
1264 return IMoniker_Release(This->moniker);
1267 static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass(
1268 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1269 void* pvDestContext, DWORD mshlflags, CLSID* pCid)
1271 MonikerMarshal *This = impl_from_IMarshal(iface);
1273 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid), pv,
1274 dwDestContext, pvDestContext, mshlflags, pCid);
1276 return IMoniker_GetClassID(This->moniker, pCid);
1279 static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax(
1280 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1281 void* pvDestContext, DWORD mshlflags, DWORD* pSize)
1283 MonikerMarshal *This = impl_from_IMarshal(iface);
1284 HRESULT hr;
1285 ULARGE_INTEGER size;
1287 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid), pv,
1288 dwDestContext, pvDestContext, mshlflags, pSize);
1290 hr = IMoniker_GetSizeMax(This->moniker, &size);
1291 if (hr == S_OK)
1292 *pSize = (DWORD)size.QuadPart;
1293 return hr;
1296 static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm,
1297 REFIID riid, void* pv, DWORD dwDestContext,
1298 void* pvDestContext, DWORD mshlflags)
1300 MonikerMarshal *This = impl_from_IMarshal(iface);
1302 TRACE("%p, %s, %p, %lx, %p, %lx.\n", pStm, debugstr_guid(riid), pv,
1303 dwDestContext, pvDestContext, mshlflags);
1305 return IMoniker_Save(This->moniker, pStm, FALSE);
1308 static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
1310 MonikerMarshal *This = impl_from_IMarshal(iface);
1311 HRESULT hr;
1313 TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
1315 hr = IMoniker_Load(This->moniker, pStm);
1316 if (hr == S_OK)
1317 hr = IMoniker_QueryInterface(This->moniker, riid, ppv);
1318 return hr;
1321 static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
1323 TRACE("()\n");
1324 /* can't release a state-based marshal as nothing on server side to
1325 * release */
1326 return S_OK;
1329 static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)
1331 TRACE("()\n");
1332 /* can't disconnect a state-based marshal as nothing on server side to
1333 * disconnect from */
1334 return S_OK;
1337 static const IMarshalVtbl VT_MonikerMarshal =
1339 MonikerMarshal_QueryInterface,
1340 MonikerMarshal_AddRef,
1341 MonikerMarshal_Release,
1342 MonikerMarshal_GetUnmarshalClass,
1343 MonikerMarshal_GetMarshalSizeMax,
1344 MonikerMarshal_MarshalInterface,
1345 MonikerMarshal_UnmarshalInterface,
1346 MonikerMarshal_ReleaseMarshalData,
1347 MonikerMarshal_DisconnectObject
1350 HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer)
1352 MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1353 if (!This) return E_OUTOFMEMORY;
1355 This->IUnknown_iface.lpVtbl = &VT_MonikerMarshalInner;
1356 This->IMarshal_iface.lpVtbl = &VT_MonikerMarshal;
1357 This->ref = 1;
1358 This->moniker = inner;
1360 *outer = &This->IUnknown_iface;
1361 return S_OK;
1364 void * __RPC_USER MIDL_user_allocate(SIZE_T size)
1366 return HeapAlloc(GetProcessHeap(), 0, size);
1369 void __RPC_USER MIDL_user_free(void *p)
1371 HeapFree(GetProcessHeap(), 0, p);