msado15: Semi-stub _Recordset get/put Filter.
[wine.git] / dlls / ole32 / moniker.c
blobec026758b2f231a1c8bc1f10f99a5690093bdd9f
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 if (hr == S_OK)
546 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
547 IStream_Release(pStream);
550 LeaveCriticalSection(&This->lock);
551 HeapFree(GetProcessHeap(), 0, moniker_data);
553 return hr;
556 LeaveCriticalSection(&This->lock);
558 TRACE("moniker unavailable locally, calling SCM\n");
560 hr = InternalIrotGetObject(moniker_data, &object, &cookie);
561 if (SUCCEEDED(hr))
563 IStream *pStream;
564 hr = create_stream_on_mip_ro(object, &pStream);
565 if (hr == S_OK)
567 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)ppunkObject);
568 IStream_Release(pStream);
571 else
572 WARN("Moniker unavailable, IrotGetObject returned %#lx\n", hr);
574 HeapFree(GetProcessHeap(), 0, moniker_data);
576 return hr;
579 /***********************************************************************
580 * RunningObjectTable_NoteChangeTime
582 * PARAMS
583 * dwRegister [in] Value identifying registration being updated
584 * pfiletime [in] Pointer to structure containing object's last change time
586 static HRESULT WINAPI
587 RunningObjectTableImpl_NoteChangeTime(IRunningObjectTable* iface,
588 DWORD dwRegister, FILETIME *pfiletime)
590 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
591 struct rot_entry *rot_entry;
592 HRESULT hr = E_INVALIDARG;
594 TRACE("%p, %ld, %p.\n", iface, dwRegister, pfiletime);
596 EnterCriticalSection(&This->lock);
597 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, struct rot_entry, entry)
599 if (rot_entry->cookie == dwRegister)
601 rot_entry->last_modified = *pfiletime;
602 LeaveCriticalSection(&This->lock);
604 hr = InternalIrotNoteChangeTime(dwRegister, pfiletime);
606 goto done;
609 LeaveCriticalSection(&This->lock);
611 done:
612 TRACE("-- %#lx\n", hr);
613 return hr;
616 /***********************************************************************
617 * RunningObjectTable_GetTimeOfLastChange
619 * PARAMS
620 * pmkObjectName [in] moniker of the object whose status is desired
621 * pfiletime [out] structure that receives object's last change time
623 static HRESULT WINAPI
624 RunningObjectTableImpl_GetTimeOfLastChange(IRunningObjectTable* iface,
625 IMoniker *pmkObjectName, FILETIME *pfiletime)
627 HRESULT hr = MK_E_UNAVAILABLE;
628 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
629 MonikerComparisonData *moniker_data;
630 const struct rot_entry *rot_entry;
632 TRACE("(%p,%p,%p)\n",This,pmkObjectName,pfiletime);
634 if (pmkObjectName==NULL || pfiletime==NULL)
635 return E_INVALIDARG;
637 hr = reduce_moniker(pmkObjectName, NULL, &pmkObjectName);
638 if (FAILED(hr))
639 return hr;
640 hr = get_moniker_comparison_data(pmkObjectName, &moniker_data);
641 IMoniker_Release(pmkObjectName);
642 if (hr != S_OK)
643 return hr;
645 hr = MK_E_UNAVAILABLE;
647 EnterCriticalSection(&This->lock);
648 LIST_FOR_EACH_ENTRY(rot_entry, &This->rot, const struct rot_entry, entry)
650 if ((rot_entry->moniker_data->ulCntData == moniker_data->ulCntData) &&
651 !memcmp(moniker_data->abData, rot_entry->moniker_data->abData, moniker_data->ulCntData))
653 *pfiletime = rot_entry->last_modified;
654 hr = S_OK;
655 break;
658 LeaveCriticalSection(&This->lock);
660 if (hr != S_OK)
661 hr = InternalIrotGetTimeOfLastChange(moniker_data, pfiletime);
663 HeapFree(GetProcessHeap(), 0, moniker_data);
665 TRACE("-- %#lx\n", hr);
666 return hr;
669 /***********************************************************************
670 * RunningObjectTable_EnumRunning
672 * PARAMS
673 * ppenumMoniker [out] receives the IEnumMoniker interface pointer
675 static HRESULT WINAPI
676 RunningObjectTableImpl_EnumRunning(IRunningObjectTable* iface,
677 IEnumMoniker **ppenumMoniker)
679 RunningObjectTableImpl *This = impl_from_IRunningObjectTable(iface);
680 InterfaceList *interface_list = NULL;
681 HRESULT hr;
683 TRACE("(%p, %p)\n", This, ppenumMoniker);
685 *ppenumMoniker = NULL;
687 hr = InternalIrotEnumRunning(&interface_list);
688 if (SUCCEEDED(hr))
689 hr = EnumMonikerImpl_CreateEnumROTMoniker(interface_list, 0, ppenumMoniker);
691 return hr;
694 /* Virtual function table for the IRunningObjectTable class. */
695 static const IRunningObjectTableVtbl VT_RunningObjectTableImpl =
697 RunningObjectTableImpl_QueryInterface,
698 RunningObjectTableImpl_AddRef,
699 RunningObjectTableImpl_Release,
700 RunningObjectTableImpl_Register,
701 RunningObjectTableImpl_Revoke,
702 RunningObjectTableImpl_IsRunning,
703 RunningObjectTableImpl_GetObject,
704 RunningObjectTableImpl_NoteChangeTime,
705 RunningObjectTableImpl_GetTimeOfLastChange,
706 RunningObjectTableImpl_EnumRunning
709 static RunningObjectTableImpl rot =
711 .IRunningObjectTable_iface.lpVtbl = &VT_RunningObjectTableImpl,
712 .lock.LockCount = -1,
713 .rot = LIST_INIT(rot.rot),
716 /***********************************************************************
717 * GetRunningObjectTable (OLE32.@)
719 HRESULT WINAPI GetRunningObjectTable(DWORD reserved, IRunningObjectTable **ret)
721 TRACE("%#lx, %p\n", reserved, ret);
723 if (reserved!=0)
724 return E_UNEXPECTED;
726 if (!InternalIsProcessInitialized())
727 return CO_E_NOTINITIALIZED;
729 *ret = &rot.IRunningObjectTable_iface;
730 IRunningObjectTable_AddRef(*ret);
732 return S_OK;
735 /***********************************************************************
736 * DestroyRunningObjectTable (ole32.@)
738 void WINAPI DestroyRunningObjectTable(void)
740 struct rot_entry *rot_entry, *cursor2;
742 TRACE("\n");
744 EnterCriticalSection(&rot.lock);
745 LIST_FOR_EACH_ENTRY_SAFE(rot_entry, cursor2, &rot.rot, struct rot_entry, entry)
747 list_remove(&rot_entry->entry);
748 rot_entry_delete(rot_entry);
750 LeaveCriticalSection(&rot.lock);
753 static HRESULT get_moniker_for_progid_display_name(LPBC pbc,
754 LPCOLESTR szDisplayName,
755 LPDWORD pchEaten,
756 LPMONIKER *ppmk)
758 CLSID clsid;
759 HRESULT hr;
760 LPWSTR progid;
761 LPCWSTR start = szDisplayName;
762 LPCWSTR end;
763 int len;
764 IMoniker *class_moniker;
766 if (*start == '@')
767 start++;
769 /* find end delimiter */
770 for (end = start; *end; end++)
771 if (*end == ':')
772 break;
774 len = end - start;
776 /* must start with '@' or have a ':' somewhere and mustn't be one character
777 * long (since that looks like an absolute path) */
778 if (((start == szDisplayName) && (*end == '\0')) || (len <= 1))
779 return MK_E_SYNTAX;
781 progid = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR));
782 if (progid)
784 memcpy(progid, start, len * sizeof(WCHAR));
785 progid[len] = '\0';
787 hr = CLSIDFromProgID(progid, &clsid);
788 HeapFree(GetProcessHeap(), 0, progid);
789 if (FAILED(hr))
790 return MK_E_SYNTAX;
792 hr = CreateClassMoniker(&clsid, &class_moniker);
793 if (SUCCEEDED(hr))
795 IParseDisplayName *pdn;
796 hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
797 &IID_IParseDisplayName, (void **)&pdn);
798 /* fallback to using IClassFactory to get IParseDisplayName -
799 * adsldp.dll depends on this */
800 if (FAILED(hr))
802 IClassFactory *pcf;
803 hr = IMoniker_BindToObject(class_moniker, pbc, NULL,
804 &IID_IClassFactory, (void **)&pcf);
805 if (SUCCEEDED(hr))
807 hr = IClassFactory_CreateInstance(pcf, NULL,
808 &IID_IParseDisplayName,
809 (void **)&pdn);
810 IClassFactory_Release(pcf);
813 IMoniker_Release(class_moniker);
814 if (SUCCEEDED(hr))
816 hr = IParseDisplayName_ParseDisplayName(pdn, pbc,
817 (LPOLESTR)szDisplayName,
818 pchEaten, ppmk);
819 IParseDisplayName_Release(pdn);
822 return hr;
825 /******************************************************************************
826 * MkParseDisplayName [OLE32.@]
828 HRESULT WINAPI MkParseDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
829 LPDWORD pchEaten, LPMONIKER *ppmk)
831 HRESULT hr = MK_E_SYNTAX;
832 IMoniker *moniker;
833 DWORD chEaten;
835 TRACE("(%p, %s, %p, %p)\n", pbc, debugstr_w(szDisplayName), pchEaten, ppmk);
837 if (!pbc || !IsValidInterface((LPUNKNOWN) pbc))
838 return E_INVALIDARG;
840 if (!szDisplayName || !*szDisplayName)
841 return E_INVALIDARG;
843 if (!pchEaten || !ppmk)
844 return E_INVALIDARG;
846 *pchEaten = 0;
847 *ppmk = NULL;
849 if (!wcsnicmp(szDisplayName, L"clsid:", 6))
851 hr = ClassMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
852 if (FAILED(hr) && (hr != MK_E_SYNTAX))
853 return hr;
855 else
857 hr = get_moniker_for_progid_display_name(pbc, szDisplayName, &chEaten, &moniker);
858 if (FAILED(hr) && (hr != MK_E_SYNTAX))
859 return hr;
862 if (FAILED(hr))
864 hr = FileMoniker_CreateFromDisplayName(pbc, szDisplayName, &chEaten, &moniker);
865 if (FAILED(hr) && (hr != MK_E_SYNTAX))
866 return hr;
869 if (SUCCEEDED(hr))
871 while (TRUE)
873 IMoniker *next_moniker;
874 *pchEaten += chEaten;
875 szDisplayName += chEaten;
876 if (!*szDisplayName)
878 *ppmk = moniker;
879 return S_OK;
881 chEaten = 0;
882 hr = IMoniker_ParseDisplayName(moniker, pbc, NULL,
883 (LPOLESTR)szDisplayName, &chEaten,
884 &next_moniker);
885 IMoniker_Release(moniker);
886 if (FAILED(hr))
888 *pchEaten = 0;
889 break;
891 moniker = next_moniker;
895 return hr;
898 /***********************************************************************
899 * GetClassFile (OLE32.@)
901 * Retrieves the class ID associated with the given filename.
903 * PARAMS
904 * filePathName [I] Filename to retrieve the class ID for.
905 * pclsid [O] Address that receives the class ID for the file.
907 * RETURNS
908 * Success: S_OK.
909 * Failure: Any HRESULT code.
911 HRESULT WINAPI GetClassFile(LPCOLESTR filePathName,CLSID *pclsid)
913 IStorage *pstg=0;
914 HRESULT res;
915 LONG sizeProgId, ret;
916 LPOLESTR progId=0;
917 const WCHAR *extension;
919 TRACE("%s, %p\n", debugstr_w(filePathName), pclsid);
921 /* if the file contain a storage object the return the CLSID written by IStorage_SetClass method*/
922 if((StgIsStorageFile(filePathName))==S_OK){
924 res=StgOpenStorage(filePathName,NULL,STGM_READ | STGM_SHARE_DENY_WRITE,NULL,0,&pstg);
926 if (SUCCEEDED(res)) {
927 res=ReadClassStg(pstg,pclsid);
928 IStorage_Release(pstg);
931 return res;
933 /* If the file is not a storage object then attempt to match various bits in the file against a
934 pattern in the registry. This case is not frequently used, so I present only the pseudocode for
935 this case.
937 for(i=0;i<nFileTypes;i++)
939 for(i=0;j<nPatternsForType;j++){
941 PATTERN pat;
942 HANDLE hFile;
944 pat=ReadPatternFromRegistry(i,j);
945 hFile=CreateFileW(filePathName,,,,,,hFile);
946 SetFilePosition(hFile,pat.offset);
947 ReadFile(hFile,buf,pat.size,&r,NULL);
948 if (memcmp(buf&pat.mask,pat.pattern.pat.size)==0){
950 *pclsid=ReadCLSIDFromRegistry(i);
951 return S_OK;
956 /* if the above strategies fail then search for the extension key in the registry */
958 res = PathCchFindExtension(filePathName, PATHCCH_MAX_CCH, &extension);
959 if (FAILED(res) || !extension || !*extension || !wcscmp(extension, L"."))
960 return MK_E_INVALIDEXTENSION;
962 ret = RegQueryValueW(HKEY_CLASSES_ROOT, extension, NULL, &sizeProgId);
963 if (!ret) {
964 /* get the progId associated to the extension */
965 progId = CoTaskMemAlloc(sizeProgId);
966 ret = RegQueryValueW(HKEY_CLASSES_ROOT, extension, progId, &sizeProgId);
967 if (!ret)
968 /* return the clsid associated to the progId */
969 res = CLSIDFromProgID(progId, pclsid);
970 else
971 res = HRESULT_FROM_WIN32(ret);
972 CoTaskMemFree(progId);
974 else
975 res = HRESULT_FROM_WIN32(ret);
977 return res != S_OK ? MK_E_INVALIDEXTENSION : res;
980 /***********************************************************************
981 * EnumMoniker_QueryInterface
983 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
985 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
987 TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppvObject);
989 /* validate arguments */
990 if (ppvObject == NULL)
991 return E_INVALIDARG;
993 *ppvObject = NULL;
995 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
996 *ppvObject = &This->IEnumMoniker_iface;
997 else
998 return E_NOINTERFACE;
1000 IEnumMoniker_AddRef(iface);
1001 return S_OK;
1004 /***********************************************************************
1005 * EnumMoniker_AddRef
1007 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1009 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1011 TRACE("(%p)\n",This);
1013 return InterlockedIncrement(&This->ref);
1016 /***********************************************************************
1017 * EnumMoniker_release
1019 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1021 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1022 ULONG ref;
1024 TRACE("(%p)\n",This);
1026 ref = InterlockedDecrement(&This->ref);
1028 /* uninitialize ROT structure if there are no more references to it */
1029 if (ref == 0)
1031 ULONG i;
1033 TRACE("(%p) Deleting\n",This);
1035 for (i = 0; i < This->moniker_list->size; i++)
1036 free(This->moniker_list->interfaces[i]);
1037 free(This->moniker_list);
1038 HeapFree(GetProcessHeap(), 0, This);
1041 return ref;
1043 /***********************************************************************
1044 * EnumMoniker_Next
1046 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface, ULONG celt, IMoniker** rgelt, ULONG * pceltFetched)
1048 ULONG i;
1049 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1050 HRESULT hr = S_OK;
1052 TRACE("%p, %lu, %p, %p.\n", iface, celt, rgelt, pceltFetched);
1054 /* retrieve the requested number of moniker from the current position */
1055 for(i = 0; (This->pos < This->moniker_list->size) && (i < celt); i++)
1057 IStream *stream;
1058 hr = create_stream_on_mip_ro(This->moniker_list->interfaces[This->pos++], &stream);
1059 if (hr != S_OK) break;
1060 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&rgelt[i]);
1061 IStream_Release(stream);
1062 if (hr != S_OK) break;
1065 if (pceltFetched != NULL)
1066 *pceltFetched= i;
1068 if (hr != S_OK)
1069 return hr;
1071 if (i == celt)
1072 return S_OK;
1073 else
1074 return S_FALSE;
1078 /***********************************************************************
1079 * EnumMoniker_Skip
1081 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface, ULONG celt)
1083 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1085 TRACE("(%p)\n",This);
1087 if (This->pos + celt >= This->moniker_list->size)
1088 return S_FALSE;
1090 This->pos += celt;
1092 return S_OK;
1095 /***********************************************************************
1096 * EnumMoniker_Reset
1098 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface)
1100 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1102 This->pos = 0; /* set back to start of list */
1104 TRACE("(%p)\n",This);
1106 return S_OK;
1109 /***********************************************************************
1110 * EnumMoniker_Clone
1112 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface, IEnumMoniker ** ppenum)
1114 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
1115 InterfaceList *moniker_list;
1116 ULONG i;
1118 TRACE("(%p)\n",This);
1120 *ppenum = NULL;
1122 moniker_list = malloc(FIELD_OFFSET(InterfaceList, interfaces[This->moniker_list->size]));
1123 if (!moniker_list)
1124 return E_OUTOFMEMORY;
1126 moniker_list->size = This->moniker_list->size;
1127 for (i = 0; i < This->moniker_list->size; i++)
1129 SIZE_T size = FIELD_OFFSET(InterfaceData, abData[This->moniker_list->interfaces[i]->ulCntData]);
1130 moniker_list->interfaces[i] = malloc(size);
1131 if (!moniker_list->interfaces[i])
1133 ULONG end = i;
1134 for (i = 0; i < end; i++)
1135 free(moniker_list->interfaces[i]);
1136 free(moniker_list);
1137 return E_OUTOFMEMORY;
1139 memcpy(moniker_list->interfaces[i], This->moniker_list->interfaces[i], size);
1142 /* copy the enum structure */
1143 return EnumMonikerImpl_CreateEnumROTMoniker(moniker_list, This->pos, ppenum);
1146 /* Virtual function table for the IEnumMoniker class. */
1147 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
1149 EnumMonikerImpl_QueryInterface,
1150 EnumMonikerImpl_AddRef,
1151 EnumMonikerImpl_Release,
1152 EnumMonikerImpl_Next,
1153 EnumMonikerImpl_Skip,
1154 EnumMonikerImpl_Reset,
1155 EnumMonikerImpl_Clone
1158 /***********************************************************************
1159 * EnumMonikerImpl_CreateEnumROTMoniker
1160 * Used by EnumRunning to create the structure and EnumClone
1161 * to copy the structure
1163 static HRESULT EnumMonikerImpl_CreateEnumROTMoniker(InterfaceList *moniker_list,
1164 ULONG current_pos,
1165 IEnumMoniker **ppenumMoniker)
1167 EnumMonikerImpl* This = NULL;
1169 if (!ppenumMoniker)
1170 return E_INVALIDARG;
1172 This = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1173 if (!This) return E_OUTOFMEMORY;
1175 TRACE("(%p)\n", This);
1177 /* initialize the virtual table function */
1178 This->IEnumMoniker_iface.lpVtbl = &VT_EnumMonikerImpl;
1180 /* the initial reference is set to "1" */
1181 This->ref = 1; /* set the ref count to one */
1182 This->pos = current_pos; /* Set the list start posn */
1183 This->moniker_list = moniker_list;
1185 *ppenumMoniker = &This->IEnumMoniker_iface;
1187 return S_OK;
1191 /* Shared implementation of moniker marshaler based on saving and loading of
1192 * monikers */
1194 typedef struct MonikerMarshal
1196 IUnknown IUnknown_iface;
1197 IMarshal IMarshal_iface;
1199 LONG ref;
1200 IMoniker *moniker;
1201 } MonikerMarshal;
1203 static inline MonikerMarshal *impl_from_IUnknown(IUnknown *iface)
1205 return CONTAINING_RECORD(iface, MonikerMarshal, IUnknown_iface);
1208 static inline MonikerMarshal *impl_from_IMarshal( IMarshal *iface )
1210 return CONTAINING_RECORD(iface, MonikerMarshal, IMarshal_iface);
1213 static HRESULT WINAPI MonikerMarshalInner_QueryInterface(IUnknown *iface, REFIID riid, LPVOID *ppv)
1215 MonikerMarshal *This = impl_from_IUnknown(iface);
1216 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
1217 *ppv = NULL;
1218 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMarshal, riid))
1220 *ppv = &This->IMarshal_iface;
1221 IMarshal_AddRef(&This->IMarshal_iface);
1222 return S_OK;
1224 FIXME("No interface for %s\n", debugstr_guid(riid));
1225 return E_NOINTERFACE;
1228 static ULONG WINAPI MonikerMarshalInner_AddRef(IUnknown *iface)
1230 MonikerMarshal *This = impl_from_IUnknown(iface);
1231 return InterlockedIncrement(&This->ref);
1234 static ULONG WINAPI MonikerMarshalInner_Release(IUnknown *iface)
1236 MonikerMarshal *This = impl_from_IUnknown(iface);
1237 ULONG ref = InterlockedDecrement(&This->ref);
1239 if (!ref) HeapFree(GetProcessHeap(), 0, This);
1240 return ref;
1243 static const IUnknownVtbl VT_MonikerMarshalInner =
1245 MonikerMarshalInner_QueryInterface,
1246 MonikerMarshalInner_AddRef,
1247 MonikerMarshalInner_Release
1250 static HRESULT WINAPI MonikerMarshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
1252 MonikerMarshal *This = impl_from_IMarshal(iface);
1253 return IMoniker_QueryInterface(This->moniker, riid, ppv);
1256 static ULONG WINAPI MonikerMarshal_AddRef(IMarshal *iface)
1258 MonikerMarshal *This = impl_from_IMarshal(iface);
1259 return IMoniker_AddRef(This->moniker);
1262 static ULONG WINAPI MonikerMarshal_Release(IMarshal *iface)
1264 MonikerMarshal *This = impl_from_IMarshal(iface);
1265 return IMoniker_Release(This->moniker);
1268 static HRESULT WINAPI MonikerMarshal_GetUnmarshalClass(
1269 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1270 void* pvDestContext, DWORD mshlflags, CLSID* pCid)
1272 MonikerMarshal *This = impl_from_IMarshal(iface);
1274 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid), pv,
1275 dwDestContext, pvDestContext, mshlflags, pCid);
1277 return IMoniker_GetClassID(This->moniker, pCid);
1280 static HRESULT WINAPI MonikerMarshal_GetMarshalSizeMax(
1281 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1282 void* pvDestContext, DWORD mshlflags, DWORD* pSize)
1284 MonikerMarshal *This = impl_from_IMarshal(iface);
1285 HRESULT hr;
1286 ULARGE_INTEGER size;
1288 TRACE("%s, %p, %lx, %p, %lx, %p.\n", debugstr_guid(riid), pv,
1289 dwDestContext, pvDestContext, mshlflags, pSize);
1291 hr = IMoniker_GetSizeMax(This->moniker, &size);
1292 if (hr == S_OK)
1293 *pSize = (DWORD)size.QuadPart;
1294 return hr;
1297 static HRESULT WINAPI MonikerMarshal_MarshalInterface(LPMARSHAL iface, IStream *pStm,
1298 REFIID riid, void* pv, DWORD dwDestContext,
1299 void* pvDestContext, DWORD mshlflags)
1301 MonikerMarshal *This = impl_from_IMarshal(iface);
1303 TRACE("%p, %s, %p, %lx, %p, %lx.\n", pStm, debugstr_guid(riid), pv,
1304 dwDestContext, pvDestContext, mshlflags);
1306 return IMoniker_Save(This->moniker, pStm, FALSE);
1309 static HRESULT WINAPI MonikerMarshal_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
1311 MonikerMarshal *This = impl_from_IMarshal(iface);
1312 HRESULT hr;
1314 TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
1316 hr = IMoniker_Load(This->moniker, pStm);
1317 if (hr == S_OK)
1318 hr = IMoniker_QueryInterface(This->moniker, riid, ppv);
1319 return hr;
1322 static HRESULT WINAPI MonikerMarshal_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
1324 TRACE("()\n");
1325 /* can't release a state-based marshal as nothing on server side to
1326 * release */
1327 return S_OK;
1330 static HRESULT WINAPI MonikerMarshal_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)
1332 TRACE("()\n");
1333 /* can't disconnect a state-based marshal as nothing on server side to
1334 * disconnect from */
1335 return S_OK;
1338 static const IMarshalVtbl VT_MonikerMarshal =
1340 MonikerMarshal_QueryInterface,
1341 MonikerMarshal_AddRef,
1342 MonikerMarshal_Release,
1343 MonikerMarshal_GetUnmarshalClass,
1344 MonikerMarshal_GetMarshalSizeMax,
1345 MonikerMarshal_MarshalInterface,
1346 MonikerMarshal_UnmarshalInterface,
1347 MonikerMarshal_ReleaseMarshalData,
1348 MonikerMarshal_DisconnectObject
1351 HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer)
1353 MonikerMarshal *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1354 if (!This) return E_OUTOFMEMORY;
1356 This->IUnknown_iface.lpVtbl = &VT_MonikerMarshalInner;
1357 This->IMarshal_iface.lpVtbl = &VT_MonikerMarshal;
1358 This->ref = 1;
1359 This->moniker = inner;
1361 *outer = &This->IUnknown_iface;
1362 return S_OK;
1365 void * __RPC_USER MIDL_user_allocate(SIZE_T size)
1367 return malloc(size);
1370 void __RPC_USER MIDL_user_free(void *p)
1372 free(p);