[OLE32]
[reactos.git] / reactos / dll / win32 / ole32 / classmoniker.c
1 /*
2 * Class Monikers
3 *
4 * Copyright 1999 Noomen Hamza
5 * Copyright 2005-2007 Robert Shearman
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #include "precomp.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(ole);
25
26 #define CHARS_IN_GUID 39
27
28 /* ClassMoniker data structure */
29 typedef struct ClassMoniker
30 {
31 IMoniker IMoniker_iface;
32 IROTData IROTData_iface;
33 LONG ref;
34 CLSID clsid; /* clsid identified by this moniker */
35 IUnknown *pMarshal; /* custom marshaler */
36 } ClassMoniker;
37
38 static inline ClassMoniker *impl_from_IMoniker(IMoniker *iface)
39 {
40 return CONTAINING_RECORD(iface, ClassMoniker, IMoniker_iface);
41 }
42
43 static inline ClassMoniker *impl_from_IROTData(IROTData *iface)
44 {
45 return CONTAINING_RECORD(iface, ClassMoniker, IROTData_iface);
46 }
47
48 /*******************************************************************************
49 * ClassMoniker_QueryInterface
50 *******************************************************************************/
51 static HRESULT WINAPI ClassMoniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
52 {
53 ClassMoniker *This = impl_from_IMoniker(iface);
54
55 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
56
57 /* Perform a sanity check on the parameters.*/
58 if (!ppvObject)
59 return E_POINTER;
60
61 /* Initialize the return parameter */
62 *ppvObject = 0;
63
64 /* Compare the riid with the interface IDs implemented by this object.*/
65 if (IsEqualIID(&IID_IUnknown, riid) ||
66 IsEqualIID(&IID_IPersist, riid) ||
67 IsEqualIID(&IID_IPersistStream, riid) ||
68 IsEqualIID(&IID_IMoniker, riid))
69 {
70 *ppvObject = iface;
71 }
72 else if (IsEqualIID(&IID_IROTData, riid))
73 *ppvObject = &This->IROTData_iface;
74 else if (IsEqualIID(&IID_IMarshal, riid))
75 {
76 HRESULT hr = S_OK;
77 if (!This->pMarshal)
78 hr = MonikerMarshal_Create(iface, &This->pMarshal);
79 if (hr != S_OK)
80 return hr;
81 return IUnknown_QueryInterface(This->pMarshal, riid, ppvObject);
82 }
83
84 /* Check that we obtained an interface.*/
85 if (!*ppvObject)
86 return E_NOINTERFACE;
87
88 /* Query Interface always increases the reference count by one when it is successful */
89 IMoniker_AddRef(iface);
90
91 return S_OK;
92 }
93
94 /******************************************************************************
95 * ClassMoniker_AddRef
96 ******************************************************************************/
97 static ULONG WINAPI ClassMoniker_AddRef(IMoniker* iface)
98 {
99 ClassMoniker *This = impl_from_IMoniker(iface);
100
101 TRACE("(%p)\n",This);
102
103 return InterlockedIncrement(&This->ref);
104 }
105
106 /******************************************************************************
107 * ClassMoniker_Destroy (local function)
108 *******************************************************************************/
109 static HRESULT ClassMoniker_Destroy(ClassMoniker* This)
110 {
111 TRACE("(%p)\n",This);
112
113 if (This->pMarshal) IUnknown_Release(This->pMarshal);
114
115 HeapFree(GetProcessHeap(),0,This);
116
117 return S_OK;
118 }
119
120 /******************************************************************************
121 * ClassMoniker_Release
122 ******************************************************************************/
123 static ULONG WINAPI ClassMoniker_Release(IMoniker* iface)
124 {
125 ClassMoniker *This = impl_from_IMoniker(iface);
126 ULONG ref;
127
128 TRACE("(%p)\n",This);
129
130 ref = InterlockedDecrement(&This->ref);
131
132 /* destroy the object if there's no more reference on it */
133 if (ref == 0) ClassMoniker_Destroy(This);
134
135 return ref;
136 }
137
138 /******************************************************************************
139 * ClassMoniker_GetClassID
140 ******************************************************************************/
141 static HRESULT WINAPI ClassMoniker_GetClassID(IMoniker* iface,CLSID *pClassID)
142 {
143 TRACE("(%p,%p),stub!\n",iface,pClassID);
144
145 if (pClassID==NULL)
146 return E_POINTER;
147
148 *pClassID = CLSID_ClassMoniker;
149
150 return S_OK;
151 }
152
153 /******************************************************************************
154 * ClassMoniker_IsDirty
155 ******************************************************************************/
156 static HRESULT WINAPI ClassMoniker_IsDirty(IMoniker* iface)
157 {
158 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
159 method in the OLE-provided moniker interfaces always return S_FALSE because
160 their internal state never changes. */
161
162 TRACE("(%p)\n",iface);
163
164 return S_FALSE;
165 }
166
167 /******************************************************************************
168 * ClassMoniker_Load
169 ******************************************************************************/
170 static HRESULT WINAPI ClassMoniker_Load(IMoniker* iface,IStream* pStm)
171 {
172 ClassMoniker *This = impl_from_IMoniker(iface);
173 HRESULT hr;
174 DWORD zero;
175
176 TRACE("(%p)\n", pStm);
177
178 hr = IStream_Read(pStm, &This->clsid, sizeof(This->clsid), NULL);
179 if (hr != S_OK) return STG_E_READFAULT;
180
181 hr = IStream_Read(pStm, &zero, sizeof(zero), NULL);
182 if ((hr != S_OK) || (zero != 0)) return STG_E_READFAULT;
183
184 return S_OK;
185 }
186
187 /******************************************************************************
188 * ClassMoniker_Save
189 ******************************************************************************/
190 static HRESULT WINAPI ClassMoniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
191 {
192 ClassMoniker *This = impl_from_IMoniker(iface);
193 HRESULT hr;
194 DWORD zero = 0;
195
196 TRACE("(%p, %s)\n", pStm, fClearDirty ? "TRUE" : "FALSE");
197
198 hr = IStream_Write(pStm, &This->clsid, sizeof(This->clsid), NULL);
199 if (FAILED(hr)) return hr;
200
201 return IStream_Write(pStm, &zero, sizeof(zero), NULL);
202 }
203
204 /******************************************************************************
205 * ClassMoniker_GetSizeMax
206 ******************************************************************************/
207 static HRESULT WINAPI ClassMoniker_GetSizeMax(IMoniker* iface,
208 ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
209 {
210 TRACE("(%p)\n", pcbSize);
211
212 pcbSize->QuadPart = sizeof(CLSID) + sizeof(DWORD);
213
214 return S_OK;
215 }
216
217 /******************************************************************************
218 * ClassMoniker_BindToObject
219 ******************************************************************************/
220 static HRESULT WINAPI ClassMoniker_BindToObject(IMoniker* iface,
221 IBindCtx* pbc,
222 IMoniker* pmkToLeft,
223 REFIID riid,
224 VOID** ppvResult)
225 {
226 ClassMoniker *This = impl_from_IMoniker(iface);
227 BIND_OPTS2 bindopts;
228 IClassActivator *pActivator;
229 HRESULT hr;
230
231 TRACE("(%p,%p,%p,%p)\n", pbc, pmkToLeft, riid, ppvResult);
232
233 bindopts.cbStruct = sizeof(bindopts);
234 IBindCtx_GetBindOptions(pbc, (BIND_OPTS *)&bindopts);
235
236 if (!pmkToLeft)
237 return CoGetClassObject(&This->clsid, bindopts.dwClassContext, NULL,
238 riid, ppvResult);
239 else
240 {
241 hr = IMoniker_BindToObject(pmkToLeft, pbc, NULL, &IID_IClassActivator,
242 (void **)&pActivator);
243 if (FAILED(hr)) return hr;
244
245 hr = IClassActivator_GetClassObject(pActivator, &This->clsid,
246 bindopts.dwClassContext,
247 bindopts.locale, riid, ppvResult);
248
249 IClassActivator_Release(pActivator);
250
251 return hr;
252 }
253 }
254
255 /******************************************************************************
256 * ClassMoniker_BindToStorage
257 ******************************************************************************/
258 static HRESULT WINAPI ClassMoniker_BindToStorage(IMoniker* iface,
259 IBindCtx* pbc,
260 IMoniker* pmkToLeft,
261 REFIID riid,
262 VOID** ppvResult)
263 {
264 TRACE("(%p,%p,%p,%p)\n",pbc, pmkToLeft, riid, ppvResult);
265 return ClassMoniker_BindToObject(iface, pbc, pmkToLeft, riid, ppvResult);
266 }
267
268 /******************************************************************************
269 * ClassMoniker_Reduce
270 ******************************************************************************/
271 static HRESULT WINAPI ClassMoniker_Reduce(IMoniker* iface,
272 IBindCtx* pbc,
273 DWORD dwReduceHowFar,
274 IMoniker** ppmkToLeft,
275 IMoniker** ppmkReduced)
276 {
277 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
278
279 if (!ppmkReduced)
280 return E_POINTER;
281
282 ClassMoniker_AddRef(iface);
283
284 *ppmkReduced = iface;
285
286 return MK_S_REDUCED_TO_SELF;
287 }
288 /******************************************************************************
289 * ClassMoniker_ComposeWith
290 ******************************************************************************/
291 static HRESULT WINAPI ClassMoniker_ComposeWith(IMoniker* iface,
292 IMoniker* pmkRight,
293 BOOL fOnlyIfNotGeneric,
294 IMoniker** ppmkComposite)
295 {
296 HRESULT res=S_OK;
297 DWORD mkSys,mkSys2;
298 IEnumMoniker* penumMk=0;
299 IMoniker *pmostLeftMk=0;
300 IMoniker* tempMkComposite=0;
301
302 TRACE("(%p,%d,%p)\n", pmkRight, fOnlyIfNotGeneric, ppmkComposite);
303
304 if ((ppmkComposite==NULL)||(pmkRight==NULL))
305 return E_POINTER;
306
307 *ppmkComposite=0;
308
309 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
310
311 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
312 if(mkSys==MKSYS_ANTIMONIKER)
313 return res;
314
315 else
316 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
317 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
318
319 if(mkSys==MKSYS_GENERICCOMPOSITE){
320
321 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
322
323 if (FAILED(res))
324 return res;
325
326 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
327
328 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
329
330 if(mkSys2==MKSYS_ANTIMONIKER){
331
332 IMoniker_Release(pmostLeftMk);
333
334 tempMkComposite=iface;
335 IMoniker_AddRef(iface);
336
337 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
338
339 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
340
341 IMoniker_Release(tempMkComposite);
342 IMoniker_Release(pmostLeftMk);
343
344 tempMkComposite=*ppmkComposite;
345 IMoniker_AddRef(tempMkComposite);
346 }
347 return res;
348 }
349 else
350 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
351 }
352 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
353 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
354 a NULL moniker and a return value of MK_E_NEEDGENERIC */
355 else
356 if (!fOnlyIfNotGeneric)
357 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
358
359 else
360 return MK_E_NEEDGENERIC;
361 }
362
363 /******************************************************************************
364 * ClassMoniker_Enum
365 ******************************************************************************/
366 static HRESULT WINAPI ClassMoniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
367 {
368 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
369
370 if (ppenumMoniker == NULL)
371 return E_POINTER;
372
373 *ppenumMoniker = NULL;
374
375 return S_OK;
376 }
377
378 /******************************************************************************
379 * ClassMoniker_IsEqual
380 ******************************************************************************/
381 static HRESULT WINAPI ClassMoniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
382 {
383
384 CLSID clsid;
385 LPOLESTR dispName1,dispName2;
386 IBindCtx* bind;
387 HRESULT res = S_FALSE;
388
389 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
390
391 if (!pmkOtherMoniker) return S_FALSE;
392
393
394 /* check if both are ClassMoniker */
395 if(FAILED (IMoniker_GetClassID(pmkOtherMoniker,&clsid))) return S_FALSE;
396 if(!IsEqualCLSID(&clsid,&CLSID_ClassMoniker)) return S_FALSE;
397
398 /* check if both displaynames are the same */
399 if(SUCCEEDED ((res = CreateBindCtx(0,&bind)))) {
400 if(SUCCEEDED (IMoniker_GetDisplayName(iface,bind,NULL,&dispName1))) {
401 if(SUCCEEDED (IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2))) {
402 if(lstrcmpW(dispName1,dispName2)==0) res = S_OK;
403 CoTaskMemFree(dispName2);
404 }
405 CoTaskMemFree(dispName1);
406 }
407 }
408 return res;
409 }
410
411 /******************************************************************************
412 * ClassMoniker_Hash
413 ******************************************************************************/
414 static HRESULT WINAPI ClassMoniker_Hash(IMoniker* iface,DWORD* pdwHash)
415 {
416 ClassMoniker *This = impl_from_IMoniker(iface);
417
418 TRACE("(%p)\n", pdwHash);
419
420 *pdwHash = This->clsid.Data1;
421
422 return S_OK;
423 }
424
425 /******************************************************************************
426 * ClassMoniker_IsRunning
427 ******************************************************************************/
428 static HRESULT WINAPI ClassMoniker_IsRunning(IMoniker* iface,
429 IBindCtx* pbc,
430 IMoniker* pmkToLeft,
431 IMoniker* pmkNewlyRunning)
432 {
433 TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, pmkNewlyRunning);
434
435 /* as in native */
436 return E_NOTIMPL;
437 }
438
439 /******************************************************************************
440 * ClassMoniker_GetTimeOfLastChange
441 ******************************************************************************/
442 static HRESULT WINAPI ClassMoniker_GetTimeOfLastChange(IMoniker* iface,
443 IBindCtx* pbc,
444 IMoniker* pmkToLeft,
445 FILETIME* pItemTime)
446 {
447 TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, pItemTime);
448
449 return MK_E_UNAVAILABLE;
450 }
451
452 /******************************************************************************
453 * ClassMoniker_Inverse
454 ******************************************************************************/
455 static HRESULT WINAPI ClassMoniker_Inverse(IMoniker* iface,IMoniker** ppmk)
456 {
457 TRACE("(%p)\n",ppmk);
458
459 if (!ppmk)
460 return E_POINTER;
461
462 return CreateAntiMoniker(ppmk);
463 }
464
465 /******************************************************************************
466 * ClassMoniker_CommonPrefixWith
467 ******************************************************************************/
468 static HRESULT WINAPI ClassMoniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
469 {
470 DWORD mkSys;
471
472 TRACE("(%p, %p)\n", pmkOther, ppmkPrefix);
473
474 *ppmkPrefix = NULL;
475
476 IMoniker_IsSystemMoniker(pmkOther, &mkSys);
477
478 /* If the other moniker is an class moniker that is equal to this moniker, this method sets *ppmkPrefix */
479 /* to this moniker and returns MK_S_US */
480
481 if (mkSys == MKSYS_CLASSMONIKER)
482 {
483 if (IMoniker_IsEqual(iface, pmkOther) == S_OK)
484 {
485 *ppmkPrefix = iface;
486
487 IMoniker_AddRef(iface);
488
489 return MK_S_US;
490 }
491 else
492 return MK_E_NOPREFIX;
493 }
494 else
495 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
496 /* the case where the other moniker is a generic composite. */
497 return MonikerCommonPrefixWith(iface, pmkOther, ppmkPrefix);
498 }
499
500 /******************************************************************************
501 * ClassMoniker_RelativePathTo
502 ******************************************************************************/
503 static HRESULT WINAPI ClassMoniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
504 {
505 TRACE("(%p, %p)\n",pmOther,ppmkRelPath);
506
507 if (!ppmkRelPath)
508 return E_POINTER;
509
510 *ppmkRelPath = NULL;
511
512 return MK_E_NOTBINDABLE;
513 }
514
515 /******************************************************************************
516 * ClassMoniker_GetDisplayName
517 ******************************************************************************/
518 static HRESULT WINAPI ClassMoniker_GetDisplayName(IMoniker* iface,
519 IBindCtx* pbc,
520 IMoniker* pmkToLeft,
521 LPOLESTR *ppszDisplayName)
522 {
523 ClassMoniker *This = impl_from_IMoniker(iface);
524 static const WCHAR wszClsidPrefix[] = {'c','l','s','i','d',':',0};
525
526 TRACE("(%p, %p, %p)\n", pbc, pmkToLeft, ppszDisplayName);
527
528 if (!ppszDisplayName)
529 return E_POINTER;
530
531 if (pmkToLeft)
532 return E_INVALIDARG;
533
534 *ppszDisplayName = CoTaskMemAlloc(sizeof(wszClsidPrefix) + (CHARS_IN_GUID-2) * sizeof(WCHAR));
535
536 StringFromGUID2(&This->clsid, *ppszDisplayName+sizeof(wszClsidPrefix)/sizeof(WCHAR)-2, CHARS_IN_GUID);
537
538 /* note: this overwrites the opening curly bracket of the CLSID string generated above */
539 memcpy(*ppszDisplayName, wszClsidPrefix, sizeof(wszClsidPrefix)-sizeof(WCHAR));
540
541 /* note: this overwrites the closing curly bracket of the CLSID string generated above */
542 (*ppszDisplayName)[sizeof(wszClsidPrefix)/sizeof(WCHAR)-2+CHARS_IN_GUID-2] = ':';
543 (*ppszDisplayName)[sizeof(wszClsidPrefix)/sizeof(WCHAR)-2+CHARS_IN_GUID-1] = '\0';
544
545 TRACE("string is %s\n", debugstr_w(*ppszDisplayName));
546 return S_OK;
547 }
548
549 /******************************************************************************
550 * ClassMoniker_ParseDisplayName
551 ******************************************************************************/
552 static HRESULT WINAPI ClassMoniker_ParseDisplayName(IMoniker* iface,
553 IBindCtx* pbc,
554 IMoniker* pmkToLeft,
555 LPOLESTR pszDisplayName,
556 ULONG* pchEaten,
557 IMoniker** ppmkOut)
558 {
559 FIXME("(%p, %p, %s, %p, %p)\n", pbc, pmkToLeft, debugstr_w(pszDisplayName), pchEaten, ppmkOut);
560 return E_NOTIMPL;
561 }
562
563 /******************************************************************************
564 * ClassMoniker_IsSystemMoniker
565 ******************************************************************************/
566 static HRESULT WINAPI ClassMoniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
567 {
568 TRACE("(%p,%p)\n",iface,pwdMksys);
569
570 if (!pwdMksys)
571 return E_POINTER;
572
573 *pwdMksys = MKSYS_CLASSMONIKER;
574
575 return S_OK;
576 }
577
578 /*******************************************************************************
579 * ClassMonikerIROTData_QueryInterface
580 *******************************************************************************/
581 static HRESULT WINAPI ClassMonikerROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
582 {
583
584 ClassMoniker *This = impl_from_IROTData(iface);
585
586 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
587
588 return ClassMoniker_QueryInterface(&This->IMoniker_iface, riid, ppvObject);
589 }
590
591 /***********************************************************************
592 * ClassMonikerIROTData_AddRef
593 */
594 static ULONG WINAPI ClassMonikerROTData_AddRef(IROTData *iface)
595 {
596 ClassMoniker *This = impl_from_IROTData(iface);
597
598 TRACE("(%p)\n",iface);
599
600 return ClassMoniker_AddRef(&This->IMoniker_iface);
601 }
602
603 /***********************************************************************
604 * ClassMonikerIROTData_Release
605 */
606 static ULONG WINAPI ClassMonikerROTData_Release(IROTData* iface)
607 {
608 ClassMoniker *This = impl_from_IROTData(iface);
609
610 TRACE("(%p)\n",iface);
611
612 return ClassMoniker_Release(&This->IMoniker_iface);
613 }
614
615 /******************************************************************************
616 * ClassMonikerIROTData_GetComparisonData
617 ******************************************************************************/
618 static HRESULT WINAPI ClassMonikerROTData_GetComparisonData(IROTData* iface,
619 BYTE* pbData,
620 ULONG cbMax,
621 ULONG* pcbData)
622 {
623 ClassMoniker *This = impl_from_IROTData(iface);
624
625 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
626
627 *pcbData = 2*sizeof(CLSID);
628 if (cbMax < *pcbData)
629 return E_OUTOFMEMORY;
630
631 /* write CLSID of the moniker */
632 memcpy(pbData, &CLSID_ClassMoniker, sizeof(CLSID));
633 /* write CLSID the moniker represents */
634 memcpy(pbData+sizeof(CLSID), &This->clsid, sizeof(CLSID));
635
636 return S_OK;
637 }
638
639 /********************************************************************************/
640 /* Virtual function table for the ClassMoniker class which include IPersist,*/
641 /* IPersistStream and IMoniker functions. */
642 static const IMonikerVtbl ClassMonikerVtbl =
643 {
644 ClassMoniker_QueryInterface,
645 ClassMoniker_AddRef,
646 ClassMoniker_Release,
647 ClassMoniker_GetClassID,
648 ClassMoniker_IsDirty,
649 ClassMoniker_Load,
650 ClassMoniker_Save,
651 ClassMoniker_GetSizeMax,
652 ClassMoniker_BindToObject,
653 ClassMoniker_BindToStorage,
654 ClassMoniker_Reduce,
655 ClassMoniker_ComposeWith,
656 ClassMoniker_Enum,
657 ClassMoniker_IsEqual,
658 ClassMoniker_Hash,
659 ClassMoniker_IsRunning,
660 ClassMoniker_GetTimeOfLastChange,
661 ClassMoniker_Inverse,
662 ClassMoniker_CommonPrefixWith,
663 ClassMoniker_RelativePathTo,
664 ClassMoniker_GetDisplayName,
665 ClassMoniker_ParseDisplayName,
666 ClassMoniker_IsSystemMoniker
667 };
668
669 /********************************************************************************/
670 /* Virtual function table for the IROTData class. */
671 static const IROTDataVtbl ROTDataVtbl =
672 {
673 ClassMonikerROTData_QueryInterface,
674 ClassMonikerROTData_AddRef,
675 ClassMonikerROTData_Release,
676 ClassMonikerROTData_GetComparisonData
677 };
678
679 /******************************************************************************
680 * ClassMoniker_Construct (local function)
681 *******************************************************************************/
682 static HRESULT ClassMoniker_Construct(ClassMoniker* This, REFCLSID rclsid)
683 {
684 TRACE("(%p,%s)\n",This,debugstr_guid(rclsid));
685
686 /* Initialize the virtual function table. */
687 This->IMoniker_iface.lpVtbl = &ClassMonikerVtbl;
688 This->IROTData_iface.lpVtbl = &ROTDataVtbl;
689 This->ref = 0;
690 This->clsid = *rclsid;
691 This->pMarshal = NULL;
692
693 return S_OK;
694 }
695
696 /******************************************************************************
697 * CreateClassMoniker [OLE32.@]
698 ******************************************************************************/
699 HRESULT WINAPI CreateClassMoniker(REFCLSID rclsid, IMoniker **ppmk)
700 {
701 ClassMoniker* newClassMoniker;
702 HRESULT hr;
703
704 TRACE("(%s,%p)\n", debugstr_guid(rclsid), ppmk);
705
706 newClassMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ClassMoniker));
707
708 if (!newClassMoniker)
709 return STG_E_INSUFFICIENTMEMORY;
710
711 hr = ClassMoniker_Construct(newClassMoniker, rclsid);
712
713 if (FAILED(hr))
714 {
715 HeapFree(GetProcessHeap(), 0, newClassMoniker);
716 return hr;
717 }
718
719 return ClassMoniker_QueryInterface(&newClassMoniker->IMoniker_iface, &IID_IMoniker,
720 (void**)ppmk);
721 }
722
723 HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName, LPDWORD pchEaten,
724 IMoniker **ppmk)
725 {
726 HRESULT hr;
727 LPCWSTR s = strchrW(szDisplayName, ':');
728 LPCWSTR end;
729 CLSID clsid;
730 BYTE table[256];
731 int i;
732
733 if (!s)
734 return MK_E_SYNTAX;
735
736 s++;
737
738 for (end = s; *end && (*end != ':'); end++)
739 ;
740
741 TRACE("parsing %s\n", debugstr_wn(s, end - s));
742
743 /* validate the CLSID string */
744 if (s[0] == '{')
745 {
746 if ((end - s != 38) || (s[37] != '}'))
747 return MK_E_SYNTAX;
748 s++;
749 }
750 else
751 {
752 if (end - s != 36)
753 return MK_E_SYNTAX;
754 }
755
756 for (i=0; i<36; i++)
757 {
758 if ((i == 8)||(i == 13)||(i == 18)||(i == 23))
759 {
760 if (s[i] != '-')
761 return MK_E_SYNTAX;
762 continue;
763 }
764 if (!(((s[i] >= '0') && (s[i] <= '9')) ||
765 ((s[i] >= 'a') && (s[i] <= 'f')) ||
766 ((s[i] >= 'A') && (s[i] <= 'F'))))
767 return MK_E_SYNTAX;
768 }
769
770 /* quick lookup table */
771 memset(table, 0, 256);
772
773 for (i = 0; i < 10; i++)
774 table['0' + i] = i;
775 for (i = 0; i < 6; i++)
776 {
777 table['A' + i] = i+10;
778 table['a' + i] = i+10;
779 }
780
781 /* in form XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX */
782
783 clsid.Data1 = (table[s[0]] << 28 | table[s[1]] << 24 | table[s[2]] << 20 | table[s[3]] << 16 |
784 table[s[4]] << 12 | table[s[5]] << 8 | table[s[6]] << 4 | table[s[7]]);
785 clsid.Data2 = table[s[9]] << 12 | table[s[10]] << 8 | table[s[11]] << 4 | table[s[12]];
786 clsid.Data3 = table[s[14]] << 12 | table[s[15]] << 8 | table[s[16]] << 4 | table[s[17]];
787
788 /* these are just sequential bytes */
789 clsid.Data4[0] = table[s[19]] << 4 | table[s[20]];
790 clsid.Data4[1] = table[s[21]] << 4 | table[s[22]];
791 clsid.Data4[2] = table[s[24]] << 4 | table[s[25]];
792 clsid.Data4[3] = table[s[26]] << 4 | table[s[27]];
793 clsid.Data4[4] = table[s[28]] << 4 | table[s[29]];
794 clsid.Data4[5] = table[s[30]] << 4 | table[s[31]];
795 clsid.Data4[6] = table[s[32]] << 4 | table[s[33]];
796 clsid.Data4[7] = table[s[34]] << 4 | table[s[35]];
797
798 hr = CreateClassMoniker(&clsid, ppmk);
799 if (SUCCEEDED(hr))
800 *pchEaten = (*end == ':' ? end + 1 : end) - szDisplayName;
801 return hr;
802 }
803
804 static HRESULT WINAPI ClassMonikerCF_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
805 {
806 *ppv = NULL;
807 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
808 {
809 *ppv = iface;
810 IClassFactory_AddRef(iface);
811 return S_OK;
812 }
813 return E_NOINTERFACE;
814 }
815
816 static ULONG WINAPI ClassMonikerCF_AddRef(LPCLASSFACTORY iface)
817 {
818 return 2; /* non-heap based object */
819 }
820
821 static ULONG WINAPI ClassMonikerCF_Release(LPCLASSFACTORY iface)
822 {
823 return 1; /* non-heap based object */
824 }
825
826 static HRESULT WINAPI ClassMonikerCF_CreateInstance(LPCLASSFACTORY iface,
827 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
828 {
829 HRESULT hr;
830 IMoniker *pmk;
831
832 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
833
834 *ppv = NULL;
835
836 if (pUnk)
837 return CLASS_E_NOAGGREGATION;
838
839 hr = CreateClassMoniker(&CLSID_NULL, &pmk);
840 if (FAILED(hr)) return hr;
841
842 hr = IMoniker_QueryInterface(pmk, riid, ppv);
843 IMoniker_Release(pmk);
844
845 return hr;
846 }
847
848 static HRESULT WINAPI ClassMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
849 {
850 FIXME("(%d), stub!\n",fLock);
851 return S_OK;
852 }
853
854 static const IClassFactoryVtbl ClassMonikerCFVtbl =
855 {
856 ClassMonikerCF_QueryInterface,
857 ClassMonikerCF_AddRef,
858 ClassMonikerCF_Release,
859 ClassMonikerCF_CreateInstance,
860 ClassMonikerCF_LockServer
861 };
862 static const IClassFactoryVtbl *ClassMonikerCF = &ClassMonikerCFVtbl;
863
864 HRESULT ClassMonikerCF_Create(REFIID riid, LPVOID *ppv)
865 {
866 return IClassFactory_QueryInterface((IClassFactory *)&ClassMonikerCF, riid, ppv);
867 }