win32u: Respect per-monitor thread dpi awareness when getting window from point.
[wine.git] / dlls / ole32 / moniker.c
blobb81033c6c4e7803267b1b4e7aa3edd5a81bd2c14
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 *moniker_data = NULL;
165 return hr;
167 (*moniker_data)->ulCntData = size;
169 else
171 IBindCtx *pbc;
172 LPOLESTR pszDisplayName;
173 CLSID clsid;
174 int len;
176 TRACE("generating comparison data from display name\n");
178 hr = CreateBindCtx(0, &pbc);
179 if (FAILED(hr))
180 return hr;
181 hr = IMoniker_GetDisplayName(pMoniker, pbc, NULL, &pszDisplayName);
182 IBindCtx_Release(pbc);
183 if (FAILED(hr))
184 return hr;
185 hr = IMoniker_GetClassID(pMoniker, &clsid);
186 if (FAILED(hr))
188 CoTaskMemFree(pszDisplayName);
189 return hr;
192 len = lstrlenW(pszDisplayName);
193 *moniker_data = HeapAlloc(GetProcessHeap(), 0,
194 FIELD_OFFSET(MonikerComparisonData, abData[sizeof(CLSID) + (len+1)*sizeof(WCHAR)]));
195 if (!*moniker_data)
197 CoTaskMemFree(pszDisplayName);
198 return E_OUTOFMEMORY;
200 (*moniker_data)->ulCntData = sizeof(CLSID) + (len+1)*sizeof(WCHAR);
202 memcpy(&(*moniker_data)->abData[0], &clsid, sizeof(clsid));
203 memcpy(&(*moniker_data)->abData[sizeof(clsid)], pszDisplayName, (len+1)*sizeof(WCHAR));
204 CoTaskMemFree(pszDisplayName);
206 return S_OK;
209 static HRESULT reduce_moniker(IMoniker *pmk, IBindCtx *pbc, IMoniker **pmkReduced)
211 IBindCtx *pbcNew = NULL;
212 HRESULT hr;
213 if (!pbc)
215 hr = CreateBindCtx(0, &pbcNew);
216 if (FAILED(hr))
217 return hr;
218 pbc = pbcNew;
220 hr = IMoniker_Reduce(pmk, pbc, MKRREDUCE_ALL, NULL, pmkReduced);
221 if (FAILED(hr))
222 ERR("reducing moniker failed with error %#lx.\n", hr);
223 if (pbcNew) IBindCtx_Release(pbcNew);
224 return hr;
227 /***********************************************************************
228 * RunningObjectTable_QueryInterface
230 static HRESULT WINAPI
231 RunningObjectTableImpl_QueryInterface(IRunningObjectTable* iface,
232 REFIID riid,void** ppvObject)
234 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
236 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
238 /* validate arguments */
240 if (ppvObject==0)
241 return E_INVALIDARG;
243 *ppvObject = 0;
245 if (IsEqualIID(&IID_IUnknown, riid) ||
246 IsEqualIID(&IID_IRunningObjectTable, riid))
247 *ppvObject = &This->IRunningObjectTable_iface;
249 if ((*ppvObject)==0)
250 return E_NOINTERFACE;
252 IRunningObjectTable_AddRef(iface);
254 return S_OK;
257 static ULONG WINAPI RunningObjectTableImpl_AddRef(IRunningObjectTable *iface)
259 TRACE("%p\n", iface);
261 return 2;
264 static ULONG WINAPI RunningObjectTableImpl_Release(IRunningObjectTable *iface)
266 TRACE("%p\n", iface);
268 return 1;
271 /***********************************************************************
272 * RunningObjectTable_Register
274 * PARAMS
275 * grfFlags [in] Registration options
276 * punkObject [in] the object being registered
277 * pmkObjectName [in] the moniker of the object being registered
278 * pdwRegister [out] the value identifying the registration
280 static HRESULT WINAPI
281 RunningObjectTableImpl_Register(IRunningObjectTable* iface, DWORD flags,
282 IUnknown *punkObject, IMoniker *pmkObjectName, DWORD *pdwRegister)
284 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
285 struct rot_entry *rot_entry;
286 HRESULT hr = S_OK;
287 IStream *pStream = NULL;
288 DWORD mshlflags;
289 IBindCtx *pbc;
290 InterfaceData *moniker = NULL;
292 TRACE("%p, %#lx, %p, %p, %p\n", iface, flags, punkObject, pmkObjectName, pdwRegister);
294 if (flags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT))
296 ERR("Invalid flags: %#lx\n", flags & ~(ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT));
297 return E_INVALIDARG;
300 if (punkObject==NULL || pmkObjectName==NULL || pdwRegister==NULL)
301 return E_INVALIDARG;
303 rot_entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rot_entry));
304 if (!rot_entry)
305 return E_OUTOFMEMORY;
307 /* marshal object */
308 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
309 if (hr != S_OK)
311 rot_entry_delete(rot_entry);
312 return hr;
314 mshlflags = flags & ROTFLAGS_REGISTRATIONKEEPSALIVE ? MSHLFLAGS_TABLESTRONG : MSHLFLAGS_TABLEWEAK;
315 hr = CoMarshalInterface(pStream, &IID_IUnknown, punkObject, MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, mshlflags);
316 /* FIXME: a cleaner way would be to create an IStream class that writes
317 * directly to an MInterfacePointer */
318 if (hr == S_OK)
320 HGLOBAL hglobal;
321 hr = GetHGlobalFromStream(pStream, &hglobal);
322 if (hr == S_OK)
324 SIZE_T size = GlobalSize(hglobal);
325 const void *pv = GlobalLock(hglobal);
326 rot_entry->object = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(MInterfacePointer, abData[size]));
327 rot_entry->object->ulCntData = size;
328 memcpy(rot_entry->object->abData, pv, size);
329 GlobalUnlock(hglobal);
332 IStream_Release(pStream);
333 if (hr != S_OK)
335 rot_entry_delete(rot_entry);
336 return hr;
339 hr = CreateBindCtx(0, &pbc);
340 if (FAILED(hr))
342 rot_entry_delete(rot_entry);
343 return hr;
346 hr = reduce_moniker(pmkObjectName, pbc, &pmkObjectName);
347 if (FAILED(hr))
349 rot_entry_delete(rot_entry);
350 IBindCtx_Release(pbc);
351 return hr;
354 hr = IMoniker_GetTimeOfLastChange(pmkObjectName, pbc, NULL,
355 &rot_entry->last_modified);
356 IBindCtx_Release(pbc);
357 if (FAILED(hr))
359 CoFileTimeNow(&rot_entry->last_modified);
360 hr = S_OK;
363 hr = get_moniker_comparison_data(pmkObjectName,
364 &rot_entry->moniker_data);
365 if (hr != S_OK)
367 rot_entry_delete(rot_entry);
368 IMoniker_Release(pmkObjectName);
369 return hr;
372 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
373 if (hr != S_OK)
375 rot_entry_delete(rot_entry);
376 IMoniker_Release(pmkObjectName);
377 return hr;
379 /* marshal moniker */
380 hr = CoMarshalInterface(pStream, &IID_IMoniker, (IUnknown *)pmkObjectName,
381 MSHCTX_LOCAL | MSHCTX_NOSHAREDMEM, NULL, MSHLFLAGS_TABLESTRONG);
382 /* FIXME: a cleaner way would be to create an IStream class that writes
383 * directly to an MInterfacePointer */
384 if (hr == S_OK)
386 HGLOBAL hglobal;
387 hr = GetHGlobalFromStream(pStream, &hglobal);
388 if (hr == S_OK)
390 SIZE_T size = GlobalSize(hglobal);
391 const void *pv = GlobalLock(hglobal);
392 moniker = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(InterfaceData, abData[size]));
393 moniker->ulCntData = size;
394 memcpy(moniker->abData, pv, size);
395 GlobalUnlock(hglobal);
398 IStream_Release(pStream);
399 IMoniker_Release(pmkObjectName);
400 if (hr != S_OK)
402 HeapFree(GetProcessHeap(), 0, moniker);
403 rot_entry_delete(rot_entry);
404 return hr;
407 hr = InternalIrotRegister(rot_entry->moniker_data, rot_entry->object, moniker,
408 &rot_entry->last_modified, flags, &rot_entry->cookie, &rot_entry->ctxt_handle);
410 HeapFree(GetProcessHeap(), 0, moniker);
411 if (FAILED(hr))
413 rot_entry_delete(rot_entry);
414 return hr;
417 /* gives a registration identifier to the registered object*/
418 *pdwRegister = rot_entry->cookie;
420 EnterCriticalSection(&This->lock);
421 list_add_tail(&This->rot, &rot_entry->entry);
422 LeaveCriticalSection(&This->lock);
424 return hr;
427 /***********************************************************************
428 * RunningObjectTable_Revoke
430 * PARAMS
431 * dwRegister [in] Value identifying registration to be revoked
433 static HRESULT WINAPI
434 RunningObjectTableImpl_Revoke( IRunningObjectTable* iface, DWORD dwRegister)
436 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
437 struct rot_entry *rot_entry;
439 TRACE("%p, %ld.\n", iface, dwRegister);
441 EnterCriticalSection(&This->lock);
442 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
444 if (rot_entry->cookie == dwRegister)
446 list_remove(&rot_entry->entry);
447 LeaveCriticalSection(&This->lock);
449 rot_entry_delete(rot_entry);
450 return S_OK;
453 LeaveCriticalSection(&This->lock);
455 return E_INVALIDARG;
458 /***********************************************************************
459 * RunningObjectTable_IsRunning
461 * PARAMS
462 * pmkObjectName [in] moniker of the object whose status is desired
464 static HRESULT WINAPI
465 RunningObjectTableImpl_IsRunning( IRunningObjectTable* iface, IMoniker *pmkObjectName)
467 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
468 MonikerComparisonData *moniker_data;
469 HRESULT hr;
470 const struct rot_entry *rot_entry;
472 TRACE("(%p,%p)\n",This,pmkObjectName);
474 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
475 if (FAILED(hr))
476 return hr;
477 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
478 IMoniker_Release(pmkObjectName);
479 if (hr != S_OK)
480 return hr;
482 hr = S_FALSE;
483 EnterCriticalSection(&This->lock);
484 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
486 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
487 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
489 hr = S_OK;
490 break;
493 LeaveCriticalSection(&This->lock);
495 if (hr == S_FALSE)
496 hr = InternalIrotIsRunning(moniker_data);
498 HeapFree(GetProcessHeap(), 0, moniker_data);
500 return hr;
503 /***********************************************************************
504 * RunningObjectTable_GetObject
506 * PARAMS
507 * pmkObjectName [in] Pointer to the moniker on the object
508 * ppunkObject [out] variable that receives the IUnknown interface pointer
510 static HRESULT WINAPI
511 RunningObjectTableImpl_GetObject( IRunningObjectTable* iface,
512 IMoniker *pmkObjectName, IUnknown **ppunkObject)
514 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
515 MonikerComparisonData *moniker_data;
516 InterfaceData *object = NULL;
517 IrotCookie cookie;
518 HRESULT hr;
519 struct rot_entry *rot_entry;
521 TRACE("(%p,%p,%p)\n",This,pmkObjectName,ppunkObject);
523 if (ppunkObject == NULL)
524 return E_POINTER;
526 *ppunkObject = NULL;
528 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
529 if (FAILED(hr))
530 return hr;
531 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
532 IMoniker_Release(pmkObjectName);
533 if (hr != S_OK)
534 return hr;
536 EnterCriticalSection(&This->lock);
537 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
539 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
540 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
542 IStream *pStream;
543 hr = create_stream_on_mip_ro(rot_entry->object, &pStream);
544 LeaveCriticalSection(&This->lock);
546 if (hr == S_OK)
548 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
549 IStream_Release(pStream);
552 HeapFree(GetProcessHeap(), 0, moniker_data);
554 return hr;
557 LeaveCriticalSection(&This->lock);
559 TRACE("moniker unavailable locally, calling SCM\n");
561 hr = InternalIrotGetObject(moniker_data, &object, &cookie);
562 if (SUCCEEDED(hr))
564 IStream *pStream;
565 hr = create_stream_on_mip_ro(object, &pStream);
566 if (hr == S_OK)
568 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
569 IStream_Release(pStream);
572 else
573 WARN("Moniker unavailable, IrotGetObject returned %#lx\n", hr);
575 HeapFree(GetProcessHeap(), 0, moniker_data);
577 return hr;
580 /***********************************************************************
581 * RunningObjectTable_NoteChangeTime
583 * PARAMS
584 * dwRegister [in] Value identifying registration being updated
585 * pfiletime [in] Pointer to structure containing object's last change time
587 static HRESULT WINAPI
588 RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
589 DWORD dwRegister, FILETIME *pfiletime)
591 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
592 struct rot_entry *rot_entry;
593 HRESULT hr = E_INVALIDARG;
595 TRACE("%p, %ld, %p.\n", iface, dwRegister, pfiletime);
597 EnterCriticalSection(&This->lock);
598 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
600 if (rot_entry->cookie == dwRegister)
602 rot_entry->last_modified = *pfiletime;
603 LeaveCriticalSection(&This->lock);
605 hr = InternalIrotNoteChangeTime(dwRegister, pfiletime);
607 goto done;
610 LeaveCriticalSection(&This->lock);
612 done:
613 TRACE("-- %#lx\n", hr);
614 return hr;
617 /***********************************************************************
618 * RunningObjectTable_GetTimeOfLastChange
620 * PARAMS
621 * pmkObjectName [in] moniker of the object whose status is desired
622 * pfiletime [out] structure that receives object's last change time
624 static HRESULT WINAPI
625 RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
626 IMoniker *pmkObjectName, FILETIME *pfiletime)
628 HRESULT hr = MK_E_UNAVAILABLE;
629 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
630 MonikerComparisonData *moniker_data;
631 const struct rot_entry *rot_entry;
633 TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
635 if (pmkObjectName==NULL || pfiletime==NULL)
636 return E_INVALIDARG;
638 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
639 if (FAILED(hr))
640 return hr;
641 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
642 IMoniker_Release(pmkObjectName);
643 if (hr != S_OK)
644 return hr;
646 hr = MK_E_UNAVAILABLE;
648 EnterCriticalSection(&This->lock);
649 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
651 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
652 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
654 *pfiletime = rot_entry->last_modified;
655 hr = S_OK;
656 break;
659 LeaveCriticalSection(&This->lock);
661 if (hr != S_OK)
662 hr = InternalIrotGetTimeOfLastChange(moniker_data, pfiletime);
664 HeapFree(GetProcessHeap(), 0, moniker_data);
666 TRACE("-- %#lx\n", hr);
667 return hr;
670 /***********************************************************************
671 * RunningObjectTable_EnumRunning
673 * PARAMS
674 * ppenumMoniker [out] receives the IEnumMoniker interface pointer
676 static HRESULT WINAPI
677 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
678 IEnumMoniker **ppenumMoniker)
680 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
681 InterfaceList *interface_list = NULL;
682 HRESULT hr;
684 TRACE("(%p, %p)\n", This, ppenumMoniker);
686 *ppenumMoniker = NULL;
688 hr = InternalIrotEnumRunning(&interface_list);
689 if (SUCCEEDED(hr))
690 hr = EnumMonikerImpl_CreateEnumROTMoniker(interface_list, 0, ppenumMoniker);
692 return hr;
695 /* Virtual function table for the IRunningObjectTable class. */
696 static const IRunningObjectTableVtbl VT_RunningObjectTableImpl =
698 RunningObjectTableImpl_QueryInterface,
699 RunningObjectTableImpl_AddRef,
700 RunningObjectTableImpl_Release,
701 RunningObjectTableImpl_Register,
702 RunningObjectTableImpl_Revoke,
703 RunningObjectTableImpl_IsRunning,
704 RunningObjectTableImpl_GetObject,
705 RunningObjectTableImpl_NoteChangeTime,
706 RunningObjectTableImpl_GetTimeOfLastChange,
707 RunningObjectTableImpl_EnumRunning
710 static RunningObjectTableImpl rot;
712 static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
714 0, 0, &rot.lock,
715 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
716 0, 0, { (DWORD_PTR)(__FILE__ ": RunningObjectTable_section") }
719 static RunningObjectTableImpl rot =
721 .IRunningObjectTable_iface.lpVtbl = &VT_RunningObjectTableImpl,
722 .lock = { &critsect_debug, -1, 0, 0, 0, 0 },
723 .rot = LIST_INIT(rot.rot),
726 /***********************************************************************
727 * GetRunningObjectTable (OLE32.@)
729 HRESULT WINAPI GetRunningObjectTable(DWORD reserved, IRunningObjectTable **ret)
731 TRACE("%#lx, %p\n", reserved, ret);
733 if (reserved!=0)
734 return E_UNEXPECTED;
736 if (!InternalIsProcessInitialized())
737 return CO_E_NOTINITIALIZED;
739 *ret = &rot.IRunningObjectTable_iface;
740 IRunningObjectTable_AddRef(*ret);
742 return S_OK;
745 /***********************************************************************
746 * DestroyRunningObjectTable (ole32.@)
748 void WINAPI DestroyRunningObjectTable(void)
750 struct rot_entry *rot_entry, *cursor2;
752 TRACE("\n");
754 EnterCriticalSection(&rot.lock);
755 LIST_FOR_EACH_ENTRY_SAFE(rot_entry, cursor2, &rot.rot, struct rot_entry, entry)
757 list_remove(&rot_entry->entry);
758 rot_entry_delete(rot_entry);
760 LeaveCriticalSection(&rot.lock);
763 static HRESULT get_moniker_for_progid_display_name(LPBC pbc,
764 LPCOLESTR szDisplayName,
765 LPDWORD pchEaten,
766 LPMONIKER *ppmk)
768 CLSID clsid;
769 HRESULT hr;
770 LPWSTR progid;
771 LPCWSTR start = szDisplayName;
772 LPCWSTR end;
773 int len;
774 IMoniker *class_moniker;
776 if (*start == '@')
777 start++;
779 /* find end delimiter */
780 for (end = start; *end; end++)
781 if (*end == ':')
782 break;
784 len = end - start;
786 /* must start with '@' or have a ':' somewhere and mustn't be one character
787 * long (since that looks like an absolute path) */
788 if (((start == szDisplayName) && (*end == '\0')) || (len <= 1))
789 return MK_E_SYNTAX;
791 progid = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
792 if (progid)
794 memcpy(progid, start, len * sizeof(WCHAR));
795 progid[len] = '\0';
797 hr = CLSIDFromProgID(progid, &clsid);
798 HeapFree(GetProcessHeap(), 0, progid);
799 if (FAILED(hr))
800 return MK_E_SYNTAX;
802 hr = CreateClassMoniker(&clsid, &class_moniker);
803 if (SUCCEEDED(hr))
805 IParseDisplayName *pdn;
806 hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
807 &IID_IParseDisplayName, (void **)&pdn);
808 /* fallback to using IClassFactory to get IParseDisplayName -
809 * adsldp.dll depends on this */
810 if (FAILED(hr))
812 IClassFactory *pcf;
813 hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
814 &IID_IClassFactory, (void **)&pcf);
815 if (SUCCEEDED(hr))
817 hr = IClassFactory_CreateInstance(pcf, NULL,
818 &IID_IParseDisplayName,
819 (void **)&pdn);
820 IClassFactory_Release(pcf);
823 IMoniker_Release(class_moniker);
824 if (SUCCEEDED(hr))
826 hr = IParseDisplayName_ParseDisplayName(pdn, pbc,
827 (LPOLESTR)szDisplayName,
828 pchEaten, ppmk);
829 IParseDisplayName_Release(pdn);
832 return hr;
835 /******************************************************************************
836 * MkParseDisplayName [OLE32.@]
838 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
839 LPDWORD pchEaten, LPMONIKER *ppmk)
841 HRESULT hr = MK_E_SYNTAX;
842 IMoniker *moniker;
843 DWORD chEaten;
845 TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
847 if (!pbc || !IsValidInterface((LPUNKNOWN) pbc))
848 return E_INVALIDARG;
850 if (!szDisplayName || !*szDisplayName)
851 return E_INVALIDARG;
853 if (!pchEaten || !ppmk)
854 return E_INVALIDARG;
856 *pchEaten = 0;
857 *ppmk = NULL;
859 if (!wcsnicmp(szDisplayName, L"clsid:", 6))
861 hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
862 if (FAILED(hr) && (hr != MK_E_SYNTAX))
863 return hr;
865 else
867 hr = get_moniker_for_progid_display_name(pbc, szDisplayName, &chEaten, &moniker);
868 if (FAILED(hr) && (hr != MK_E_SYNTAX))
869 return hr;
872 if (FAILED(hr))
874 hr = FileMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
875 if (FAILED(hr) && (hr != MK_E_SYNTAX))
876 return hr;
879 if (SUCCEEDED(hr))
881 while (TRUE)
883 IMoniker *next_moniker;
884 *pchEaten += chEaten;
885 szDisplayName += chEaten;
886 if (!*szDisplayName)
888 *ppmk = moniker;
889 return S_OK;
891 chEaten = 0;
892 hr = IMoniker_ParseDisplayName(moniker, pbc, NULL,
893 (LPOLESTR)szDisplayName, &chEaten,
894 &next_moniker);
895 IMoniker_Release(moniker);
896 if (FAILED(hr))
898 *pchEaten = 0;
899 break;
901 moniker = next_moniker;
905 return hr;
908 /***********************************************************************
909 * GetClassFile (OLE32.@)
911 * Retrieves the class ID associated with the given filename.
913 * PARAMS
914 * filePathName [I] Filename to retrieve the class ID for.
915 * pclsid [O] Address that receives the class ID for the file.
917 * RETURNS
918 * Success: S_OK.
919 * Failure: Any HRESULT code.
921 HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
923 IStorage *pstg=0;
924 HRESULT res;
925 LONG sizeProgId, ret;
926 LPOLESTR progId=0;
927 const WCHAR *extension;
929 TRACE("%s, %p\n", debugstr_w(filePathName), pclsid);
931 /* if the file contain a storage object the return the CLSID written by IStorage_SetClass method*/
932 if((StgIsStorageFile(filePathName))==S_OK){
934 res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
936 if (SUCCEEDED(res)) {
937 res=ReadClassStg(pstg,pclsid);
938 IStorage_Release(pstg);
941 return res;
943 /* If the file is not a storage object then attempt to match various bits in the file against a
944 pattern in the registry. This case is not frequently used, so I present only the pseudocode for
945 this case.
947 for(i=0;i<nFileTypes;i++)
949 for(i=0;j<nPatternsForType;j++){
951 PATTERN pat;
952 HANDLE hFile;
954 pat=ReadPatternFromRegistry(i,j);
955 hFile=CreateFileW(filePathName,,,,,,hFile);
956 SetFilePosition(hFile,pat.offset);
957 ReadFile(hFile,buf,pat.size,&r,NULL);
958 if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
960 *pclsid=ReadCLSIDFromRegistry(i);
961 return S_OK;
966 /* if the above strategies fail then search for the extension key in the registry */
968 res = PathCchFindExtension(filePathName, PATHCCH_MAX_CCH, &extension);
969 if (FAILED(res) || !extension || !*extension || !wcscmp(extension, L"."))
970 return MK_E_INVALIDEXTENSION;
972 ret = RegQueryValueW(HKEY_CLASSES_ROOT, extension, NULL, &sizeProgId);
973 if (!ret) {
974 /* get the progId associated to the extension */
975 progId = CoTaskMemAlloc(sizeProgId);
976 ret = RegQueryValueW(HKEY_CLASSES_ROOT, extension, progId, &sizeProgId);
977 if (!ret)
978 /* return the clsid associated to the progId */
979 res = CLSIDFromProgID(progId, pclsid);
980 else
981 res = HRESULT_FROM_WIN32(ret);
982 CoTaskMemFree(progId);
984 else
985 res = HRESULT_FROM_WIN32(ret);
987 return res != S_OK ? MK_E_INVALIDEXTENSION : res;
990 /***********************************************************************
991 * EnumMoniker_QueryInterface
993 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
995 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
997 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
999 /* validate arguments */
1000 if (ppvObject == NULL)
1001 return E_INVALIDARG;
1003 *ppvObject = NULL;
1005 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1006 *ppvObject = &This->IEnumMoniker_iface;
1007 else
1008 return E_NOINTERFACE;
1010 IEnumMoniker_AddRef(iface);
1011 return S_OK;
1014 /***********************************************************************
1015 * EnumMoniker_AddRef
1017 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1019 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1021 TRACE("(%p)\n",This);
1023 return InterlockedIncrement(&This->ref);
1026 /***********************************************************************
1027 * EnumMoniker_release
1029 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1031 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1032 ULONG ref;
1034 TRACE("(%p)\n",This);
1036 ref = InterlockedDecrement(&This->ref);
1038 /* uninitialize ROT structure if there are no more references to it */
1039 if (ref == 0)
1041 ULONG i;
1043 TRACE("(%p) Deleting\n",This);
1045 for (i = 0; i < This->moniker_list->size; i++)
1046 free(This->moniker_list->interfaces[i]);
1047 free(This->moniker_list);
1048 HeapFree(GetProcessHeap(), 0, This);
1051 return ref;
1053 /***********************************************************************
1054 * EnumMoniker_Next
1056 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched)
1058 ULONG i;
1059 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1060 HRESULT hr = S_OK;
1062 TRACE("%p, %lu, %p, %p.\n", iface, celt, rgelt, pceltFetched);
1064 /* retrieve the requested number of moniker from the current position */
1065 for(i = 0; (This->pos < This->moniker_list->size) && (i < celt); i++)
1067 IStream *stream;
1068 hr = create_stream_on_mip_ro(This->moniker_list->interfaces[This->pos++], &stream);
1069 if (hr != S_OK) break;
1070 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]);
1071 IStream_Release(stream);
1072 if (hr != S_OK) break;
1075 if (pceltFetched != NULL)
1076 *pceltFetched= i;
1078 if (hr != S_OK)
1079 return hr;
1081 if (i == celt)
1082 return S_OK;
1083 else
1084 return S_FALSE;
1088 /***********************************************************************
1089 * EnumMoniker_Skip
1091 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt)
1093 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1095 TRACE("(%p)\n",This);
1097 if (This->pos + celt >= This->moniker_list->size)
1098 return S_FALSE;
1100 This->pos += celt;
1102 return S_OK;
1105 /***********************************************************************
1106 * EnumMoniker_Reset
1108 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
1110 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1112 This->pos = 0; /* set back to start of list */
1114 TRACE("(%p)\n",This);
1116 return S_OK;
1119 /***********************************************************************
1120 * EnumMoniker_Clone
1122 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)
1124 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1125 InterfaceList *moniker_list;
1126 ULONG i;
1128 TRACE("(%p)\n",This);
1130 *ppenum = NULL;
1132 moniker_list = malloc(FIELD_OFFSET(InterfaceList, interfaces[This->moniker_list->size]));
1133 if (!moniker_list)
1134 return E_OUTOFMEMORY;
1136 moniker_list->size = This->moniker_list->size;
1137 for (i = 0; i < This->moniker_list->size; i++)
1139 SIZE_T size = FIELD_OFFSET(InterfaceData, abData[This->moniker_list->interfaces[i]->ulCntData]);
1140 moniker_list->interfaces[i] = malloc(size);
1141 if (!moniker_list->interfaces[i])
1143 ULONG end = i;
1144 for (i = 0; i < end; i++)
1145 free(moniker_list->interfaces[i]);
1146 free(moniker_list);
1147 return E_OUTOFMEMORY;
1149 memcpy(moniker_list->interfaces[i], This->moniker_list->interfaces[i], size);
1152 /* copy the enum structure */
1153 return EnumMonikerImpl_CreateEnumROTMoniker(moniker_list, This->pos, ppenum);
1156 /* Virtual function table for the IEnumMoniker class. */
1157 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
1159 EnumMonikerImpl_QueryInterface,
1160 EnumMonikerImpl_AddRef,
1161 EnumMonikerImpl_Release,
1162 EnumMonikerImpl_Next,
1163 EnumMonikerImpl_Skip,
1164 EnumMonikerImpl_Reset,
1165 EnumMonikerImpl_Clone
1168 /***********************************************************************
1169 * EnumMonikerImpl_CreateEnumROTMoniker
1170 * Used by EnumRunning to create the structure and EnumClone
1171 * to copy the structure
1173 static HRESULT EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list,
1174 ULONG current_pos,
1175 IEnumMoniker **ppenumMoniker)
1177 EnumMonikerImpl* This = NULL;
1179 if (!ppenumMoniker)
1180 return E_INVALIDARG;
1182 This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1183 if (!This) return E_OUTOFMEMORY;
1185 TRACE("(%p)\n", This);
1187 /* initialize the virtual table function */
1188 This->IEnumMoniker_iface.lpVtbl = &VT_EnumMonikerImpl;
1190 /* the initial reference is set to "1" */
1191 This->ref = 1; /* set the ref count to one */
1192 This->pos = current_pos; /* Set the list start posn */
1193 This->moniker_list = moniker_list;
1195 *ppenumMoniker = &This->IEnumMoniker_iface;
1197 return S_OK;
1201 /* Shared implementation of moniker marshaler based on saving and loading of
1202 * monikers */
1204 typedef struct MonikerMarshal
1206 IUnknown IUnknown_iface;
1207 IMarshal IMarshal_iface;
1209 LONG ref;
1210 IMoniker *moniker;
1211 } MonikerMarshal;
1213 static inline MonikerMarshal *impl_from_IUnknown(IUnknown *iface)
1215 return CONTAINING_RECORD(iface, MonikerMarshal, IUnknown_iface);
1218 static inline MonikerMarshal *impl_from_IMarshal( IMarshal *iface )
1220 return CONTAINING_RECORD(iface, MonikerMarshal, IMarshal_iface);
1223 static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv)
1225 MonikerMarshal *This = impl_from_IUnknown(iface);
1226 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1227 *ppv = NULL;
1228 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid))
1230 *ppv = &This->IMarshal_iface;
1231 IMarshal_AddRef(&This->IMarshal_iface);
1232 return S_OK;
1234 FIXME("No interface for %s\n", debugstr_guid(riid));
1235 return E_NOINTERFACE;
1238 static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface)
1240 MonikerMarshal *This = impl_from_IUnknown(iface);
1241 return InterlockedIncrement(&This->ref);
1244 static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface)
1246 MonikerMarshal *This = impl_from_IUnknown(iface);
1247 ULONG ref = InterlockedDecrement(&This->ref);
1249 if (!ref) HeapFree(GetProcessHeap(), 0, This);
1250 return ref;
1253 static const IUnknownVtbl VT_MonikerMarshalInner =
1255 MonikerMarshalInner_QueryInterface,
1256 MonikerMarshalInner_AddRef,
1257 MonikerMarshalInner_Release
1260 static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
1262 MonikerMarshal *This = impl_from_IMarshal(iface);
1263 return IMoniker_QueryInterface(This->moniker, riid, ppv);
1266 static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface)
1268 MonikerMarshal *This = impl_from_IMarshal(iface);
1269 return IMoniker_AddRef(This->moniker);
1272 static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface)
1274 MonikerMarshal *This = impl_from_IMarshal(iface);
1275 return IMoniker_Release(This->moniker);
1278 static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass(
1279 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1280 void* pvDestContext, DWORD mshlflags, CLSID* pCid)
1282 MonikerMarshal *This = impl_from_IMarshal(iface);
1284 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid), pv,
1285 dwDestContext, pvDestContext, mshlflags, pCid);
1287 return IMoniker_GetClassID(This->moniker, pCid);
1290 static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax(
1291 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1292 void* pvDestContext, DWORD mshlflags, DWORD* pSize)
1294 MonikerMarshal *This = impl_from_IMarshal(iface);
1295 HRESULT hr;
1296 ULARGE_INTEGER size;
1298 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid), pv,
1299 dwDestContext, pvDestContext, mshlflags, pSize);
1301 hr = IMoniker_GetSizeMax(This->moniker, &size);
1302 if (hr == S_OK)
1303 *pSize = (DWORD)size.QuadPart;
1304 return hr;
1307 static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm,
1308 REFIID riid, void* pv, DWORD dwDestContext,
1309 void* pvDestContext, DWORD mshlflags)
1311 MonikerMarshal *This = impl_from_IMarshal(iface);
1313 TRACE("%p, %s, %p, %lx, %p, %lx.\n", pStm, debugstr_guid(riid), pv,
1314 dwDestContext, pvDestContext, mshlflags);
1316 return IMoniker_Save(This->moniker, pStm, FALSE);
1319 static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
1321 MonikerMarshal *This = impl_from_IMarshal(iface);
1322 HRESULT hr;
1324 TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
1326 hr = IMoniker_Load(This->moniker, pStm);
1327 if (hr == S_OK)
1328 hr = IMoniker_QueryInterface(This->moniker, riid, ppv);
1329 return hr;
1332 static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
1334 TRACE("()\n");
1335 /* can't release a state-based marshal as nothing on server side to
1336 * release */
1337 return S_OK;
1340 static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)
1342 TRACE("()\n");
1343 /* can't disconnect a state-based marshal as nothing on server side to
1344 * disconnect from */
1345 return S_OK;
1348 static const IMarshalVtbl VT_MonikerMarshal =
1350 MonikerMarshal_QueryInterface,
1351 MonikerMarshal_AddRef,
1352 MonikerMarshal_Release,
1353 MonikerMarshal_GetUnmarshalClass,
1354 MonikerMarshal_GetMarshalSizeMax,
1355 MonikerMarshal_MarshalInterface,
1356 MonikerMarshal_UnmarshalInterface,
1357 MonikerMarshal_ReleaseMarshalData,
1358 MonikerMarshal_DisconnectObject
1361 HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer)
1363 MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1364 if (!This) return E_OUTOFMEMORY;
1366 This->IUnknown_iface.lpVtbl = &VT_MonikerMarshalInner;
1367 This->IMarshal_iface.lpVtbl = &VT_MonikerMarshal;
1368 This->ref = 1;
1369 This->moniker = inner;
1371 *outer = &This->IUnknown_iface;
1372 return S_OK;
1375 void * __RPC_USER MIDL_user_allocate(SIZE_T size)
1377 return malloc(size);
1380 void __RPC_USER MIDL_user_free(void *p)
1382 free(p);