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