4 * Copyright 1999 Noomen Hamza
5 * Copyright 2005-2007 Robert Shearman
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/debug.h"
33 #include "wine/heap.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
39 #define CHARS_IN_GUID 39
41 /* ClassMoniker data structure */
42 typedef struct ClassMoniker
44 IMoniker IMoniker_iface
;
45 IROTData IROTData_iface
;
55 IUnknown
*pMarshal
; /* custom marshaler */
58 static inline ClassMoniker
*impl_from_IMoniker(IMoniker
*iface
)
60 return CONTAINING_RECORD(iface
, ClassMoniker
, IMoniker_iface
);
63 static inline ClassMoniker
*impl_from_IROTData(IROTData
*iface
)
65 return CONTAINING_RECORD(iface
, ClassMoniker
, IROTData_iface
);
68 static const IMonikerVtbl ClassMonikerVtbl
;
70 static ClassMoniker
*unsafe_impl_from_IMoniker(IMoniker
*iface
)
72 if (iface
->lpVtbl
!= &ClassMonikerVtbl
)
74 return CONTAINING_RECORD(iface
, ClassMoniker
, IMoniker_iface
);
77 /*******************************************************************************
78 * ClassMoniker_QueryInterface
79 *******************************************************************************/
80 static HRESULT WINAPI
ClassMoniker_QueryInterface(IMoniker
*iface
, REFIID riid
, void **ppvObject
)
82 ClassMoniker
*This
= impl_from_IMoniker(iface
);
84 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppvObject
);
91 if (IsEqualIID(&IID_IUnknown
, riid
) ||
92 IsEqualIID(&IID_IPersist
, riid
) ||
93 IsEqualIID(&IID_IPersistStream
, riid
) ||
94 IsEqualIID(&IID_IMoniker
, riid
) ||
95 IsEqualGUID(&CLSID_ClassMoniker
, riid
))
99 else if (IsEqualIID(&IID_IROTData
, riid
))
100 *ppvObject
= &This
->IROTData_iface
;
101 else if (IsEqualIID(&IID_IMarshal
, riid
))
105 hr
= MonikerMarshal_Create(iface
, &This
->pMarshal
);
108 return IUnknown_QueryInterface(This
->pMarshal
, riid
, ppvObject
);
112 return E_NOINTERFACE
;
114 IMoniker_AddRef(iface
);
119 /******************************************************************************
120 * ClassMoniker_AddRef
121 ******************************************************************************/
122 static ULONG WINAPI
ClassMoniker_AddRef(IMoniker
* iface
)
124 ClassMoniker
*This
= impl_from_IMoniker(iface
);
126 TRACE("(%p)\n",This
);
128 return InterlockedIncrement(&This
->ref
);
131 static ULONG WINAPI
ClassMoniker_Release(IMoniker
* iface
)
133 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
134 ULONG ref
= InterlockedDecrement(&moniker
->ref
);
136 TRACE("%p, refcount %lu.\n", iface
, ref
);
140 if (moniker
->pMarshal
) IUnknown_Release(moniker
->pMarshal
);
141 heap_free(moniker
->data
);
148 /******************************************************************************
149 * ClassMoniker_GetClassID
150 ******************************************************************************/
151 static HRESULT WINAPI
ClassMoniker_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
153 TRACE("(%p, %p)\n", iface
, pClassID
);
158 *pClassID
= CLSID_ClassMoniker
;
163 /******************************************************************************
164 * ClassMoniker_IsDirty
165 ******************************************************************************/
166 static HRESULT WINAPI
ClassMoniker_IsDirty(IMoniker
* iface
)
168 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
169 method in the OLE-provided moniker interfaces always return S_FALSE because
170 their internal state never changes. */
172 TRACE("(%p)\n",iface
);
177 static HRESULT WINAPI
ClassMoniker_Load(IMoniker
*iface
, IStream
*stream
)
179 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
183 TRACE("%p, %p\n", iface
, stream
);
185 hr
= IStream_Read(stream
, &moniker
->header
, sizeof(moniker
->header
), &length
);
186 if (hr
!= S_OK
|| length
!= sizeof(moniker
->header
)) return STG_E_READFAULT
;
188 if (moniker
->header
.data_len
)
190 heap_free(moniker
->data
);
191 if (!(moniker
->data
= heap_alloc(moniker
->header
.data_len
)))
193 WARN("Failed to allocate moniker data of size %lu.\n", moniker
->header
.data_len
);
194 moniker
->header
.data_len
= 0;
195 return E_OUTOFMEMORY
;
197 hr
= IStream_Read(stream
, moniker
->data
, moniker
->header
.data_len
, &length
);
198 if (hr
!= S_OK
|| length
!= moniker
->header
.data_len
) return STG_E_READFAULT
;
204 static HRESULT WINAPI
ClassMoniker_Save(IMoniker
*iface
, IStream
*stream
, BOOL clear_dirty
)
206 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
209 TRACE("%p, %p, %d\n", iface
, stream
, clear_dirty
);
211 hr
= IStream_Write(stream
, &moniker
->header
, sizeof(moniker
->header
), NULL
);
213 if (SUCCEEDED(hr
) && moniker
->header
.data_len
)
214 hr
= IStream_Write(stream
, moniker
->data
, moniker
->header
.data_len
, NULL
);
219 static HRESULT WINAPI
ClassMoniker_GetSizeMax(IMoniker
*iface
, ULARGE_INTEGER
*size
)
221 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
223 TRACE("%p, %p\n", iface
, size
);
225 size
->QuadPart
= sizeof(moniker
->header
) + moniker
->header
.data_len
;
230 /******************************************************************************
231 * ClassMoniker_BindToObject
232 ******************************************************************************/
233 static HRESULT WINAPI
ClassMoniker_BindToObject(IMoniker
* iface
,
239 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
241 IClassActivator
*pActivator
;
244 TRACE("(%p, %p, %s, %p)\n", pbc
, pmkToLeft
, debugstr_guid(riid
), ppvResult
);
246 bindopts
.cbStruct
= sizeof(bindopts
);
247 IBindCtx_GetBindOptions(pbc
, (BIND_OPTS
*)&bindopts
);
250 return CoGetClassObject(&moniker
->header
.clsid
, bindopts
.dwClassContext
, NULL
,
254 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IClassActivator
,
255 (void **)&pActivator
);
256 if (FAILED(hr
)) return hr
;
258 hr
= IClassActivator_GetClassObject(pActivator
, &moniker
->header
.clsid
,
259 bindopts
.dwClassContext
,
260 bindopts
.locale
, riid
, ppvResult
);
262 IClassActivator_Release(pActivator
);
268 /******************************************************************************
269 * ClassMoniker_BindToStorage
270 ******************************************************************************/
271 static HRESULT WINAPI
ClassMoniker_BindToStorage(IMoniker
* iface
,
277 TRACE("(%p, %p, %s, %p)\n", pbc
, pmkToLeft
, debugstr_guid(riid
), ppvResult
);
278 return IMoniker_BindToObject(iface
, pbc
, pmkToLeft
, riid
, ppvResult
);
281 static HRESULT WINAPI
ClassMoniker_Reduce(IMoniker
* iface
, IBindCtx
*pbc
,
282 DWORD dwReduceHowFar
, IMoniker
**ppmkToLeft
, IMoniker
**ppmkReduced
)
284 TRACE("%p, %p, %ld, %p, %p.\n", iface
, pbc
, dwReduceHowFar
, ppmkToLeft
, ppmkReduced
);
289 IMoniker_AddRef(iface
);
291 *ppmkReduced
= iface
;
293 return MK_S_REDUCED_TO_SELF
;
296 static HRESULT WINAPI
ClassMoniker_ComposeWith(IMoniker
*iface
, IMoniker
*right
,
297 BOOL only_if_not_generic
, IMoniker
**result
)
301 TRACE("%p, %p, %d, %p.\n", iface
, right
, only_if_not_generic
, result
);
303 if (!result
|| !right
)
308 if (is_anti_moniker(right
, &order
))
311 return only_if_not_generic
? MK_E_NEEDGENERIC
: CreateGenericComposite(iface
, right
, result
);
314 /******************************************************************************
316 ******************************************************************************/
317 static HRESULT WINAPI
ClassMoniker_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
319 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
321 if (ppenumMoniker
== NULL
)
324 *ppenumMoniker
= NULL
;
329 static HRESULT WINAPI
ClassMoniker_IsEqual(IMoniker
*iface
, IMoniker
*other
)
331 ClassMoniker
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
333 TRACE("%p, %p.\n", iface
, other
);
338 other_moniker
= unsafe_impl_from_IMoniker(other
);
342 return IsEqualGUID(&moniker
->header
.clsid
, &other_moniker
->header
.clsid
) ? S_OK
: S_FALSE
;
345 static HRESULT WINAPI
ClassMoniker_Hash(IMoniker
*iface
, DWORD
*hash
)
347 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
349 TRACE("%p, %p\n", iface
, hash
);
351 *hash
= moniker
->header
.clsid
.Data1
;
356 /******************************************************************************
357 * ClassMoniker_IsRunning
358 ******************************************************************************/
359 static HRESULT WINAPI
ClassMoniker_IsRunning(IMoniker
* iface
,
362 IMoniker
* pmkNewlyRunning
)
364 TRACE("(%p, %p, %p)\n", pbc
, pmkToLeft
, pmkNewlyRunning
);
370 /******************************************************************************
371 * ClassMoniker_GetTimeOfLastChange
372 ******************************************************************************/
373 static HRESULT WINAPI
ClassMoniker_GetTimeOfLastChange(IMoniker
* iface
,
378 TRACE("(%p, %p, %p)\n", pbc
, pmkToLeft
, pItemTime
);
380 return MK_E_UNAVAILABLE
;
383 /******************************************************************************
384 * ClassMoniker_Inverse
385 ******************************************************************************/
386 static HRESULT WINAPI
ClassMoniker_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
388 TRACE("(%p)\n",ppmk
);
393 return CreateAntiMoniker(ppmk
);
396 static HRESULT WINAPI
ClassMoniker_CommonPrefixWith(IMoniker
*iface
, IMoniker
*other
, IMoniker
**prefix
)
398 ClassMoniker
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
400 TRACE("%p, %p, %p\n", iface
, other
, prefix
);
404 other_moniker
= unsafe_impl_from_IMoniker(other
);
408 if (!IsEqualGUID(&moniker
->header
.clsid
, &other_moniker
->header
.clsid
)) return MK_E_NOPREFIX
;
411 IMoniker_AddRef(iface
);
416 return MonikerCommonPrefixWith(iface
, other
, prefix
);
419 /******************************************************************************
420 * ClassMoniker_RelativePathTo
421 ******************************************************************************/
422 static HRESULT WINAPI
ClassMoniker_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
)
424 TRACE("(%p, %p)\n",pmOther
,ppmkRelPath
);
431 return MK_E_NOTBINDABLE
;
434 static HRESULT WINAPI
ClassMoniker_GetDisplayName(IMoniker
*iface
,
435 IBindCtx
*pbc
, IMoniker
*pmkToLeft
, LPOLESTR
*name
)
437 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
438 static const int name_len
= CHARS_IN_GUID
+ 5 /* prefix */;
439 const GUID
*guid
= &moniker
->header
.clsid
;
441 TRACE("%p, %p, %p, %p.\n", iface
, pbc
, pmkToLeft
, name
);
449 if (!(*name
= CoTaskMemAlloc(name_len
* sizeof(WCHAR
) + moniker
->header
.data_len
)))
450 return E_OUTOFMEMORY
;
452 swprintf(*name
, name_len
, L
"clsid:%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
453 guid
->Data1
, guid
->Data2
, guid
->Data3
, guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2],
454 guid
->Data4
[3], guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
456 if (moniker
->header
.data_len
)
457 lstrcatW(*name
, moniker
->data
);
458 lstrcatW(*name
, L
":");
460 TRACE("Returning %s\n", debugstr_w(*name
));
465 static HRESULT WINAPI
ClassMoniker_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
466 IMoniker
*pmkToLeft
, LPOLESTR display_name
, ULONG
*eaten
, IMoniker
**result
)
468 IParseDisplayName
*parser
;
471 TRACE("%p, %p, %p, %s, %p, %p\n", iface
, pbc
, pmkToLeft
, debugstr_w(display_name
), eaten
, result
);
473 if (SUCCEEDED(hr
= IMoniker_BindToObject(iface
, pbc
, pmkToLeft
, &IID_IParseDisplayName
, (void **)&parser
)))
475 hr
= IParseDisplayName_ParseDisplayName(parser
, pbc
, display_name
, eaten
, result
);
476 IParseDisplayName_Release(parser
);
482 /******************************************************************************
483 * ClassMoniker_IsSystemMoniker
484 ******************************************************************************/
485 static HRESULT WINAPI
ClassMoniker_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
487 TRACE("(%p,%p)\n",iface
,pwdMksys
);
492 *pwdMksys
= MKSYS_CLASSMONIKER
;
497 /*******************************************************************************
498 * ClassMonikerIROTData_QueryInterface
499 *******************************************************************************/
500 static HRESULT WINAPI
ClassMonikerROTData_QueryInterface(IROTData
*iface
,REFIID riid
,VOID
** ppvObject
)
503 ClassMoniker
*This
= impl_from_IROTData(iface
);
505 TRACE("(%p, %s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
507 return IMoniker_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
510 /***********************************************************************
511 * ClassMonikerIROTData_AddRef
513 static ULONG WINAPI
ClassMonikerROTData_AddRef(IROTData
*iface
)
515 ClassMoniker
*This
= impl_from_IROTData(iface
);
517 TRACE("(%p)\n",iface
);
519 return IMoniker_AddRef(&This
->IMoniker_iface
);
522 /***********************************************************************
523 * ClassMonikerIROTData_Release
525 static ULONG WINAPI
ClassMonikerROTData_Release(IROTData
* iface
)
527 ClassMoniker
*This
= impl_from_IROTData(iface
);
529 TRACE("(%p)\n",iface
);
531 return IMoniker_Release(&This
->IMoniker_iface
);
534 /******************************************************************************
535 * ClassMonikerIROTData_GetComparisonData
536 ******************************************************************************/
537 static HRESULT WINAPI
ClassMonikerROTData_GetComparisonData(IROTData
* iface
,
542 ClassMoniker
*This
= impl_from_IROTData(iface
);
544 TRACE("%p, %p, %lu, %p.\n", iface
, pbData
, cbMax
, pcbData
);
546 *pcbData
= 2*sizeof(CLSID
);
547 if (cbMax
< *pcbData
)
548 return E_OUTOFMEMORY
;
550 /* write CLSID of the moniker */
551 memcpy(pbData
, &CLSID_ClassMoniker
, sizeof(CLSID
));
552 /* write CLSID the moniker represents */
553 memcpy(pbData
+sizeof(CLSID
), &This
->header
.clsid
, sizeof(CLSID
));
558 static const IMonikerVtbl ClassMonikerVtbl
=
560 ClassMoniker_QueryInterface
,
562 ClassMoniker_Release
,
563 ClassMoniker_GetClassID
,
564 ClassMoniker_IsDirty
,
567 ClassMoniker_GetSizeMax
,
568 ClassMoniker_BindToObject
,
569 ClassMoniker_BindToStorage
,
571 ClassMoniker_ComposeWith
,
573 ClassMoniker_IsEqual
,
575 ClassMoniker_IsRunning
,
576 ClassMoniker_GetTimeOfLastChange
,
577 ClassMoniker_Inverse
,
578 ClassMoniker_CommonPrefixWith
,
579 ClassMoniker_RelativePathTo
,
580 ClassMoniker_GetDisplayName
,
581 ClassMoniker_ParseDisplayName
,
582 ClassMoniker_IsSystemMoniker
585 /********************************************************************************/
586 /* Virtual function table for the IROTData class. */
587 static const IROTDataVtbl ROTDataVtbl
=
589 ClassMonikerROTData_QueryInterface
,
590 ClassMonikerROTData_AddRef
,
591 ClassMonikerROTData_Release
,
592 ClassMonikerROTData_GetComparisonData
595 static HRESULT
create_class_moniker(const CLSID
*clsid
, const WCHAR
*data
,
596 unsigned int data_len
, IMoniker
**moniker
)
598 ClassMoniker
*object
;
600 if (!(object
= heap_alloc_zero(sizeof(*object
))))
601 return E_OUTOFMEMORY
;
603 object
->IMoniker_iface
.lpVtbl
= &ClassMonikerVtbl
;
604 object
->IROTData_iface
.lpVtbl
= &ROTDataVtbl
;
606 object
->header
.clsid
= *clsid
;
609 object
->header
.data_len
= (data_len
+ 1) * sizeof(WCHAR
);
611 if (!(object
->data
= heap_alloc(object
->header
.data_len
)))
613 IMoniker_Release(&object
->IMoniker_iface
);
614 return E_OUTOFMEMORY
;
616 memcpy(object
->data
, data
, data_len
* sizeof(WCHAR
));
617 object
->data
[data_len
] = 0;
620 *moniker
= &object
->IMoniker_iface
;
625 /******************************************************************************
626 * CreateClassMoniker [OLE32.@]
627 ******************************************************************************/
628 HRESULT WINAPI
CreateClassMoniker(REFCLSID rclsid
, IMoniker
**moniker
)
630 TRACE("%s, %p\n", debugstr_guid(rclsid
), moniker
);
632 return create_class_moniker(rclsid
, NULL
, 0, moniker
);
635 HRESULT
ClassMoniker_CreateFromDisplayName(LPBC pbc
, const WCHAR
*display_name
,
636 DWORD
*eaten
, IMoniker
**moniker
)
638 const WCHAR
*end
, *s
;
648 if (wcsnicmp(s
, L
"clsid:", 6)) return MK_E_SYNTAX
;
651 /* Terminating marker is optional */
652 if (!(end
= wcschr(s
, ':')))
653 end
= s
+ lstrlenW(s
);
659 if ((has_braces
= *s
== '{')) s
++;
661 memcpy(uuid
, s
, 36 * sizeof(WCHAR
));
664 if (UuidFromStringW(uuid
, &clsid
))
666 WARN("Failed to parse clsid string.\n");
673 if (*s
!= '}') return MK_E_SYNTAX
;
677 /* Consume terminal marker */
679 if (*end
== ':') end
++;
681 hr
= create_class_moniker(&clsid
, len
? s
: NULL
, len
, moniker
);
683 *eaten
= end
- display_name
;
687 HRESULT WINAPI
ClassMoniker_CreateInstance(IClassFactory
*iface
,
688 IUnknown
*pUnk
, REFIID riid
, void **ppv
)
693 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
698 return CLASS_E_NOAGGREGATION
;
700 hr
= CreateClassMoniker(&CLSID_NULL
, &pmk
);
701 if (FAILED(hr
)) return hr
;
703 hr
= IMoniker_QueryInterface(pmk
, riid
, ppv
);
704 IMoniker_Release(pmk
);