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"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
38 #define CHARS_IN_GUID 39
40 /* ClassMoniker data structure */
41 typedef struct ClassMoniker
43 IMoniker IMoniker_iface
;
44 IROTData IROTData_iface
;
54 IUnknown
*pMarshal
; /* custom marshaler */
57 static inline ClassMoniker
*impl_from_IMoniker(IMoniker
*iface
)
59 return CONTAINING_RECORD(iface
, ClassMoniker
, IMoniker_iface
);
62 static inline ClassMoniker
*impl_from_IROTData(IROTData
*iface
)
64 return CONTAINING_RECORD(iface
, ClassMoniker
, IROTData_iface
);
67 static const IMonikerVtbl ClassMonikerVtbl
;
69 static ClassMoniker
*unsafe_impl_from_IMoniker(IMoniker
*iface
)
71 if (iface
->lpVtbl
!= &ClassMonikerVtbl
)
73 return CONTAINING_RECORD(iface
, ClassMoniker
, IMoniker_iface
);
76 /*******************************************************************************
77 * ClassMoniker_QueryInterface
78 *******************************************************************************/
79 static HRESULT WINAPI
ClassMoniker_QueryInterface(IMoniker
*iface
, REFIID riid
, void **ppvObject
)
81 ClassMoniker
*This
= impl_from_IMoniker(iface
);
83 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), ppvObject
);
90 if (IsEqualIID(&IID_IUnknown
, riid
) ||
91 IsEqualIID(&IID_IPersist
, riid
) ||
92 IsEqualIID(&IID_IPersistStream
, riid
) ||
93 IsEqualIID(&IID_IMoniker
, riid
) ||
94 IsEqualGUID(&CLSID_ClassMoniker
, riid
))
98 else if (IsEqualIID(&IID_IROTData
, riid
))
99 *ppvObject
= &This
->IROTData_iface
;
100 else if (IsEqualIID(&IID_IMarshal
, riid
))
104 hr
= MonikerMarshal_Create(iface
, &This
->pMarshal
);
107 return IUnknown_QueryInterface(This
->pMarshal
, riid
, ppvObject
);
111 return E_NOINTERFACE
;
113 IMoniker_AddRef(iface
);
118 /******************************************************************************
119 * ClassMoniker_AddRef
120 ******************************************************************************/
121 static ULONG WINAPI
ClassMoniker_AddRef(IMoniker
* iface
)
123 ClassMoniker
*This
= impl_from_IMoniker(iface
);
125 TRACE("(%p)\n",This
);
127 return InterlockedIncrement(&This
->ref
);
130 static ULONG WINAPI
ClassMoniker_Release(IMoniker
* iface
)
132 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
133 ULONG ref
= InterlockedDecrement(&moniker
->ref
);
135 TRACE("%p, refcount %lu.\n", iface
, ref
);
139 if (moniker
->pMarshal
) IUnknown_Release(moniker
->pMarshal
);
147 /******************************************************************************
148 * ClassMoniker_GetClassID
149 ******************************************************************************/
150 static HRESULT WINAPI
ClassMoniker_GetClassID(IMoniker
* iface
,CLSID
*pClassID
)
152 TRACE("(%p, %p)\n", iface
, pClassID
);
157 *pClassID
= CLSID_ClassMoniker
;
162 /******************************************************************************
163 * ClassMoniker_IsDirty
164 ******************************************************************************/
165 static HRESULT WINAPI
ClassMoniker_IsDirty(IMoniker
* iface
)
167 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
168 method in the OLE-provided moniker interfaces always return S_FALSE because
169 their internal state never changes. */
171 TRACE("(%p)\n",iface
);
176 static HRESULT WINAPI
ClassMoniker_Load(IMoniker
*iface
, IStream
*stream
)
178 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
182 TRACE("%p, %p\n", iface
, stream
);
184 hr
= IStream_Read(stream
, &moniker
->header
, sizeof(moniker
->header
), &length
);
185 if (hr
!= S_OK
|| length
!= sizeof(moniker
->header
)) return STG_E_READFAULT
;
187 if (moniker
->header
.data_len
)
190 if (!(moniker
->data
= malloc(moniker
->header
.data_len
)))
192 WARN("Failed to allocate moniker data of size %lu.\n", moniker
->header
.data_len
);
193 moniker
->header
.data_len
= 0;
194 return E_OUTOFMEMORY
;
196 hr
= IStream_Read(stream
, moniker
->data
, moniker
->header
.data_len
, &length
);
197 if (hr
!= S_OK
|| length
!= moniker
->header
.data_len
) return STG_E_READFAULT
;
203 static HRESULT WINAPI
ClassMoniker_Save(IMoniker
*iface
, IStream
*stream
, BOOL clear_dirty
)
205 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
208 TRACE("%p, %p, %d\n", iface
, stream
, clear_dirty
);
210 hr
= IStream_Write(stream
, &moniker
->header
, sizeof(moniker
->header
), NULL
);
212 if (SUCCEEDED(hr
) && moniker
->header
.data_len
)
213 hr
= IStream_Write(stream
, moniker
->data
, moniker
->header
.data_len
, NULL
);
218 static HRESULT WINAPI
ClassMoniker_GetSizeMax(IMoniker
*iface
, ULARGE_INTEGER
*size
)
220 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
222 TRACE("%p, %p\n", iface
, size
);
224 size
->QuadPart
= sizeof(moniker
->header
) + moniker
->header
.data_len
;
229 /******************************************************************************
230 * ClassMoniker_BindToObject
231 ******************************************************************************/
232 static HRESULT WINAPI
ClassMoniker_BindToObject(IMoniker
* iface
,
238 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
240 IClassActivator
*pActivator
;
243 TRACE("(%p, %p, %s, %p)\n", pbc
, pmkToLeft
, debugstr_guid(riid
), ppvResult
);
245 bindopts
.cbStruct
= sizeof(bindopts
);
246 IBindCtx_GetBindOptions(pbc
, (BIND_OPTS
*)&bindopts
);
249 return CoGetClassObject(&moniker
->header
.clsid
, bindopts
.dwClassContext
, NULL
,
253 hr
= IMoniker_BindToObject(pmkToLeft
, pbc
, NULL
, &IID_IClassActivator
,
254 (void **)&pActivator
);
255 if (FAILED(hr
)) return hr
;
257 hr
= IClassActivator_GetClassObject(pActivator
, &moniker
->header
.clsid
,
258 bindopts
.dwClassContext
,
259 bindopts
.locale
, riid
, ppvResult
);
261 IClassActivator_Release(pActivator
);
267 /******************************************************************************
268 * ClassMoniker_BindToStorage
269 ******************************************************************************/
270 static HRESULT WINAPI
ClassMoniker_BindToStorage(IMoniker
* iface
,
276 TRACE("(%p, %p, %s, %p)\n", pbc
, pmkToLeft
, debugstr_guid(riid
), ppvResult
);
277 return IMoniker_BindToObject(iface
, pbc
, pmkToLeft
, riid
, ppvResult
);
280 static HRESULT WINAPI
ClassMoniker_Reduce(IMoniker
* iface
, IBindCtx
*pbc
,
281 DWORD dwReduceHowFar
, IMoniker
**ppmkToLeft
, IMoniker
**ppmkReduced
)
283 TRACE("%p, %p, %ld, %p, %p.\n", iface
, pbc
, dwReduceHowFar
, ppmkToLeft
, ppmkReduced
);
288 IMoniker_AddRef(iface
);
290 *ppmkReduced
= iface
;
292 return MK_S_REDUCED_TO_SELF
;
295 static HRESULT WINAPI
ClassMoniker_ComposeWith(IMoniker
*iface
, IMoniker
*right
,
296 BOOL only_if_not_generic
, IMoniker
**result
)
300 TRACE("%p, %p, %d, %p.\n", iface
, right
, only_if_not_generic
, result
);
302 if (!result
|| !right
)
307 if (is_anti_moniker(right
, &order
))
310 return only_if_not_generic
? MK_E_NEEDGENERIC
: CreateGenericComposite(iface
, right
, result
);
313 /******************************************************************************
315 ******************************************************************************/
316 static HRESULT WINAPI
ClassMoniker_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
318 TRACE("(%p,%d,%p)\n",iface
,fForward
,ppenumMoniker
);
320 if (ppenumMoniker
== NULL
)
323 *ppenumMoniker
= NULL
;
328 static HRESULT WINAPI
ClassMoniker_IsEqual(IMoniker
*iface
, IMoniker
*other
)
330 ClassMoniker
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
332 TRACE("%p, %p.\n", iface
, other
);
337 other_moniker
= unsafe_impl_from_IMoniker(other
);
341 return IsEqualGUID(&moniker
->header
.clsid
, &other_moniker
->header
.clsid
) ? S_OK
: S_FALSE
;
344 static HRESULT WINAPI
ClassMoniker_Hash(IMoniker
*iface
, DWORD
*hash
)
346 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
348 TRACE("%p, %p\n", iface
, hash
);
350 *hash
= moniker
->header
.clsid
.Data1
;
355 /******************************************************************************
356 * ClassMoniker_IsRunning
357 ******************************************************************************/
358 static HRESULT WINAPI
ClassMoniker_IsRunning(IMoniker
* iface
,
361 IMoniker
* pmkNewlyRunning
)
363 TRACE("(%p, %p, %p)\n", pbc
, pmkToLeft
, pmkNewlyRunning
);
369 /******************************************************************************
370 * ClassMoniker_GetTimeOfLastChange
371 ******************************************************************************/
372 static HRESULT WINAPI
ClassMoniker_GetTimeOfLastChange(IMoniker
* iface
,
377 TRACE("(%p, %p, %p)\n", pbc
, pmkToLeft
, pItemTime
);
379 return MK_E_UNAVAILABLE
;
382 /******************************************************************************
383 * ClassMoniker_Inverse
384 ******************************************************************************/
385 static HRESULT WINAPI
ClassMoniker_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
387 TRACE("(%p)\n",ppmk
);
392 return CreateAntiMoniker(ppmk
);
395 static HRESULT WINAPI
ClassMoniker_CommonPrefixWith(IMoniker
*iface
, IMoniker
*other
, IMoniker
**prefix
)
397 ClassMoniker
*moniker
= impl_from_IMoniker(iface
), *other_moniker
;
399 TRACE("%p, %p, %p\n", iface
, other
, prefix
);
403 other_moniker
= unsafe_impl_from_IMoniker(other
);
407 if (!IsEqualGUID(&moniker
->header
.clsid
, &other_moniker
->header
.clsid
)) return MK_E_NOPREFIX
;
410 IMoniker_AddRef(iface
);
415 return MonikerCommonPrefixWith(iface
, other
, prefix
);
418 /******************************************************************************
419 * ClassMoniker_RelativePathTo
420 ******************************************************************************/
421 static HRESULT WINAPI
ClassMoniker_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
)
423 TRACE("(%p, %p)\n",pmOther
,ppmkRelPath
);
430 return MK_E_NOTBINDABLE
;
433 static HRESULT WINAPI
ClassMoniker_GetDisplayName(IMoniker
*iface
,
434 IBindCtx
*pbc
, IMoniker
*pmkToLeft
, LPOLESTR
*name
)
436 ClassMoniker
*moniker
= impl_from_IMoniker(iface
);
437 static const int name_len
= CHARS_IN_GUID
+ 5 /* prefix */;
438 const GUID
*guid
= &moniker
->header
.clsid
;
440 TRACE("%p, %p, %p, %p.\n", iface
, pbc
, pmkToLeft
, name
);
448 if (!(*name
= CoTaskMemAlloc(name_len
* sizeof(WCHAR
) + moniker
->header
.data_len
)))
449 return E_OUTOFMEMORY
;
451 swprintf(*name
, name_len
, L
"clsid:%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
452 guid
->Data1
, guid
->Data2
, guid
->Data3
, guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2],
453 guid
->Data4
[3], guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
455 if (moniker
->header
.data_len
)
456 lstrcatW(*name
, moniker
->data
);
457 lstrcatW(*name
, L
":");
459 TRACE("Returning %s\n", debugstr_w(*name
));
464 static HRESULT WINAPI
ClassMoniker_ParseDisplayName(IMoniker
*iface
, IBindCtx
*pbc
,
465 IMoniker
*pmkToLeft
, LPOLESTR display_name
, ULONG
*eaten
, IMoniker
**result
)
467 IParseDisplayName
*parser
;
470 TRACE("%p, %p, %p, %s, %p, %p\n", iface
, pbc
, pmkToLeft
, debugstr_w(display_name
), eaten
, result
);
472 if (SUCCEEDED(hr
= IMoniker_BindToObject(iface
, pbc
, pmkToLeft
, &IID_IParseDisplayName
, (void **)&parser
)))
474 hr
= IParseDisplayName_ParseDisplayName(parser
, pbc
, display_name
, eaten
, result
);
475 IParseDisplayName_Release(parser
);
481 /******************************************************************************
482 * ClassMoniker_IsSystemMoniker
483 ******************************************************************************/
484 static HRESULT WINAPI
ClassMoniker_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
486 TRACE("(%p,%p)\n",iface
,pwdMksys
);
491 *pwdMksys
= MKSYS_CLASSMONIKER
;
496 /*******************************************************************************
497 * ClassMonikerIROTData_QueryInterface
498 *******************************************************************************/
499 static HRESULT WINAPI
ClassMonikerROTData_QueryInterface(IROTData
*iface
,REFIID riid
,VOID
** ppvObject
)
502 ClassMoniker
*This
= impl_from_IROTData(iface
);
504 TRACE("(%p, %s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
506 return IMoniker_QueryInterface(&This
->IMoniker_iface
, riid
, ppvObject
);
509 /***********************************************************************
510 * ClassMonikerIROTData_AddRef
512 static ULONG WINAPI
ClassMonikerROTData_AddRef(IROTData
*iface
)
514 ClassMoniker
*This
= impl_from_IROTData(iface
);
516 TRACE("(%p)\n",iface
);
518 return IMoniker_AddRef(&This
->IMoniker_iface
);
521 /***********************************************************************
522 * ClassMonikerIROTData_Release
524 static ULONG WINAPI
ClassMonikerROTData_Release(IROTData
* iface
)
526 ClassMoniker
*This
= impl_from_IROTData(iface
);
528 TRACE("(%p)\n",iface
);
530 return IMoniker_Release(&This
->IMoniker_iface
);
533 /******************************************************************************
534 * ClassMonikerIROTData_GetComparisonData
535 ******************************************************************************/
536 static HRESULT WINAPI
ClassMonikerROTData_GetComparisonData(IROTData
* iface
,
541 ClassMoniker
*This
= impl_from_IROTData(iface
);
543 TRACE("%p, %p, %lu, %p.\n", iface
, pbData
, cbMax
, pcbData
);
545 *pcbData
= 2*sizeof(CLSID
);
546 if (cbMax
< *pcbData
)
547 return E_OUTOFMEMORY
;
549 /* write CLSID of the moniker */
550 memcpy(pbData
, &CLSID_ClassMoniker
, sizeof(CLSID
));
551 /* write CLSID the moniker represents */
552 memcpy(pbData
+sizeof(CLSID
), &This
->header
.clsid
, sizeof(CLSID
));
557 static const IMonikerVtbl ClassMonikerVtbl
=
559 ClassMoniker_QueryInterface
,
561 ClassMoniker_Release
,
562 ClassMoniker_GetClassID
,
563 ClassMoniker_IsDirty
,
566 ClassMoniker_GetSizeMax
,
567 ClassMoniker_BindToObject
,
568 ClassMoniker_BindToStorage
,
570 ClassMoniker_ComposeWith
,
572 ClassMoniker_IsEqual
,
574 ClassMoniker_IsRunning
,
575 ClassMoniker_GetTimeOfLastChange
,
576 ClassMoniker_Inverse
,
577 ClassMoniker_CommonPrefixWith
,
578 ClassMoniker_RelativePathTo
,
579 ClassMoniker_GetDisplayName
,
580 ClassMoniker_ParseDisplayName
,
581 ClassMoniker_IsSystemMoniker
584 /********************************************************************************/
585 /* Virtual function table for the IROTData class. */
586 static const IROTDataVtbl ROTDataVtbl
=
588 ClassMonikerROTData_QueryInterface
,
589 ClassMonikerROTData_AddRef
,
590 ClassMonikerROTData_Release
,
591 ClassMonikerROTData_GetComparisonData
594 static HRESULT
create_class_moniker(const CLSID
*clsid
, const WCHAR
*data
,
595 unsigned int data_len
, IMoniker
**moniker
)
597 ClassMoniker
*object
;
599 if (!(object
= calloc(1, sizeof(*object
))))
600 return E_OUTOFMEMORY
;
602 object
->IMoniker_iface
.lpVtbl
= &ClassMonikerVtbl
;
603 object
->IROTData_iface
.lpVtbl
= &ROTDataVtbl
;
605 object
->header
.clsid
= *clsid
;
608 object
->header
.data_len
= (data_len
+ 1) * sizeof(WCHAR
);
610 if (!(object
->data
= malloc(object
->header
.data_len
)))
612 IMoniker_Release(&object
->IMoniker_iface
);
613 return E_OUTOFMEMORY
;
615 memcpy(object
->data
, data
, data_len
* sizeof(WCHAR
));
616 object
->data
[data_len
] = 0;
619 *moniker
= &object
->IMoniker_iface
;
624 /******************************************************************************
625 * CreateClassMoniker [OLE32.@]
626 ******************************************************************************/
627 HRESULT WINAPI
CreateClassMoniker(REFCLSID rclsid
, IMoniker
**moniker
)
629 TRACE("%s, %p\n", debugstr_guid(rclsid
), moniker
);
631 return create_class_moniker(rclsid
, NULL
, 0, moniker
);
634 HRESULT
ClassMoniker_CreateFromDisplayName(LPBC pbc
, const WCHAR
*display_name
,
635 DWORD
*eaten
, IMoniker
**moniker
)
637 const WCHAR
*end
, *s
;
647 if (wcsnicmp(s
, L
"clsid:", 6)) return MK_E_SYNTAX
;
650 /* Terminating marker is optional */
651 if (!(end
= wcschr(s
, ':')))
652 end
= s
+ lstrlenW(s
);
658 if ((has_braces
= *s
== '{')) s
++;
660 memcpy(uuid
, s
, 36 * sizeof(WCHAR
));
663 if (UuidFromStringW(uuid
, &clsid
))
665 WARN("Failed to parse clsid string.\n");
672 if (*s
!= '}') return MK_E_SYNTAX
;
676 /* Consume terminal marker */
678 if (*end
== ':') end
++;
680 hr
= create_class_moniker(&clsid
, len
? s
: NULL
, len
, moniker
);
682 *eaten
= end
- display_name
;
686 HRESULT WINAPI
ClassMoniker_CreateInstance(IClassFactory
*iface
,
687 IUnknown
*pUnk
, REFIID riid
, void **ppv
)
692 TRACE("(%p, %s, %p)\n", pUnk
, debugstr_guid(riid
), ppv
);
697 return CLASS_E_NOAGGREGATION
;
699 hr
= CreateClassMoniker(&CLSID_NULL
, &pmk
);
700 if (FAILED(hr
)) return hr
;
702 hr
= IMoniker_QueryInterface(pmk
, riid
, ppv
);
703 IMoniker_Release(pmk
);