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