1 /*
2 * CompositeMonikers implementation
3 *
4 * Copyright 1999 Noomen Hamza
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <string.h>
24
25 #define COBJMACROS
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "winerror.h"
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
35 #include "ole2.h"
36 #include "moniker.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39
40 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
41
42 /* CompositeMoniker data structure */
43 typedef struct CompositeMonikerImpl{
44
45 const IMonikerVtbl* lpvtbl1; /* VTable relative to the IMoniker interface.*/
46
47 /* The ROT (RunningObjectTable implementation) uses the IROTData
48 * interface to test whether two monikers are equal. That's why IROTData
49 * interface is implemented by monikers.
50 */
51 const IROTDataVtbl* lpvtbl2; /* VTable relative to the IROTData interface.*/
52
53 const IMarshalVtbl* lpvtblMarshal; /* VTable relative to the IMarshal interface.*/
54
55 LONG ref; /* reference counter for this object */
56
57 IMoniker** tabMoniker; /* dynamic table containing all components (monikers) of this composite moniker */
58
59 ULONG tabSize; /* size of tabMoniker */
60
61 ULONG tabLastIndex; /* first free index in tabMoniker */
62
63 } CompositeMonikerImpl;
64
65
66 /* EnumMoniker data structure */
67 typedef struct EnumMonikerImpl{
68
69 const IEnumMonikerVtbl *lpVtbl; /* VTable relative to the IEnumMoniker interface.*/
70
71 LONG ref; /* reference counter for this object */
72
73 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
74
75 ULONG tabSize; /* size of tabMoniker */
76
77 ULONG currentPos; /* index pointer on the current moniker */
78
79 } EnumMonikerImpl;
80
81 static inline IMoniker *impl_from_IROTData( IROTData *iface )
82 {
83 return (IMoniker *)((char*)iface - FIELD_OFFSET(CompositeMonikerImpl, lpvtbl2));
84 }
85
86 static inline IMoniker *impl_from_IMarshal( IMarshal *iface )
87 {
88 return (IMoniker *)((char*)iface - FIELD_OFFSET(CompositeMonikerImpl, lpvtblMarshal));
89 }
90
91 static HRESULT EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
92
93 /*******************************************************************************
94 * CompositeMoniker_QueryInterface
95 *******************************************************************************/
96 static HRESULT WINAPI
97 CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
98 {
99 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
100
101 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
102
103 /* Perform a sanity check on the parameters.*/
104 if ( (This==0) || (ppvObject==0) )
105 return E_INVALIDARG;
106
107 /* Initialize the return parameter */
108 *ppvObject = 0;
109
110 /* Compare the riid with the interface IDs implemented by this object.*/
111 if (IsEqualIID(&IID_IUnknown, riid) ||
112 IsEqualIID(&IID_IPersist, riid) ||
113 IsEqualIID(&IID_IPersistStream, riid) ||
114 IsEqualIID(&IID_IMoniker, riid)
115 )
116 *ppvObject = iface;
117 else if (IsEqualIID(&IID_IROTData, riid))
118 *ppvObject = &This->lpvtbl2;
119 else if (IsEqualIID(&IID_IMarshal, riid))
120 *ppvObject = &This->lpvtblMarshal;
121
122 /* Check that we obtained an interface.*/
123 if ((*ppvObject)==0)
124 return E_NOINTERFACE;
125
126 /* Query Interface always increases the reference count by one when it is successful */
127 IMoniker_AddRef(iface);
128
129 return S_OK;
130 }
131
132 /******************************************************************************
133 * CompositeMoniker_AddRef
134 ******************************************************************************/
135 static ULONG WINAPI
136 CompositeMonikerImpl_AddRef(IMoniker* iface)
137 {
138 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
139
140 TRACE("(%p)\n",This);
141
142 return InterlockedIncrement(&This->ref);
143 }
144
145 static void CompositeMonikerImpl_ReleaseMonikersInTable(CompositeMonikerImpl *This)
146 {
147 ULONG i;
148
149 for (i = 0; i < This->tabLastIndex; i++)
150 IMoniker_Release(This->tabMoniker[i]);
151
152 This->tabLastIndex = 0;
153 }
154
155 /******************************************************************************
156 * CompositeMoniker_Release
157 ******************************************************************************/
158 static ULONG WINAPI
159 CompositeMonikerImpl_Release(IMoniker* iface)
160 {
161 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
162 ULONG ref;
163
164 TRACE("(%p)\n",This);
165
166 ref = InterlockedDecrement(&This->ref);
167
168 /* destroy the object if there's no more reference on it */
169 if (ref == 0){
170
171 /* release all the components before destroying this object */
172 CompositeMonikerImpl_ReleaseMonikersInTable(This);
173
174 HeapFree(GetProcessHeap(),0,This->tabMoniker);
175 HeapFree(GetProcessHeap(),0,This);
176 }
177 return ref;
178 }
179
180 /******************************************************************************
181 * CompositeMoniker_GetClassID
182 ******************************************************************************/
183 static HRESULT WINAPI
184 CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
185 {
186 TRACE("(%p,%p)\n",iface,pClassID);
187
188 if (pClassID==NULL)
189 return E_POINTER;
190
191 *pClassID = CLSID_CompositeMoniker;
192
193 return S_OK;
194 }
195
196 /******************************************************************************
197 * CompositeMoniker_IsDirty
198 ******************************************************************************/
199 static HRESULT WINAPI
200 CompositeMonikerImpl_IsDirty(IMoniker* iface)
201 {
202 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
203 method in the OLE-provided moniker interfaces always return S_FALSE because
204 their internal state never changes. */
205
206 TRACE("(%p)\n",iface);
207
208 return S_FALSE;
209 }
210
211 /******************************************************************************
212 * CompositeMoniker_Load
213 ******************************************************************************/
214 static HRESULT WINAPI
215 CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
216 {
217 HRESULT res;
218 DWORD moniker_count;
219 DWORD i;
220
221 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
222
223 TRACE("(%p,%p)\n",iface,pStm);
224
225 /* this function call OleLoadFromStream function for each moniker within this object */
226
227 res=IStream_Read(pStm,&moniker_count,sizeof(DWORD),NULL);
228 if (res != S_OK)
229 {
230 ERR("couldn't reading moniker count from stream\n");
231 return E_FAIL;
232 }
233
234 CompositeMonikerImpl_ReleaseMonikersInTable(This);
235
236 for (i = 0; i < moniker_count; i++)
237 {
238 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
239 if (FAILED(res))
240 {
241 ERR("couldn't load moniker from stream, res = 0x%08x\n", res);
242 break;
243 }
244
245 /* resize the table if needed */
246 if (++This->tabLastIndex==This->tabSize){
247
248 This->tabSize+=BLOCK_TAB_SIZE;
249 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
250
251 if (This->tabMoniker==NULL)
252 return E_OUTOFMEMORY;
253 }
254 }
255
256 return res;
257 }
258
259 /******************************************************************************
260 * CompositeMoniker_Save
261 ******************************************************************************/
262 static HRESULT WINAPI
263 CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
264 {
265 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
266 HRESULT res;
267 IEnumMoniker *enumMk;
268 IMoniker *pmk;
269 DWORD moniker_count = This->tabLastIndex;
270
271 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
272
273 /* This function calls OleSaveToStream function for each moniker within
274 * this object.
275 * When I tested this function in windows, I usually found this constant
276 * at the beginning of the stream. I don't known why (there's no
277 * indication in the specification) !
278 */
279 res=IStream_Write(pStm,&moniker_count,sizeof(moniker_count),NULL);
280 if (FAILED(res)) return res;
281
282 IMoniker_Enum(iface,TRUE,&enumMk);
283
284 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
285
286 res=OleSaveToStream((IPersistStream*)pmk,pStm);
287
288 IMoniker_Release(pmk);
289
290 if (FAILED(res)){
291
292 IEnumMoniker_Release(enumMk);
293 return res;
294 }
295 }
296
297 IEnumMoniker_Release(enumMk);
298
299 return S_OK;
300 }
301
302 /******************************************************************************
303 * CompositeMoniker_GetSizeMax
304 ******************************************************************************/
305 static HRESULT WINAPI
306 CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
307 {
308 IEnumMoniker *enumMk;
309 IMoniker *pmk;
310 ULARGE_INTEGER ptmpSize;
311
312 /* The sizeMax of this object is calculated by calling GetSizeMax on
313 * each moniker within this object then summing all returned values
314 */
315
316 TRACE("(%p,%p)\n",iface,pcbSize);
317
318 if (!pcbSize)
319 return E_POINTER;
320
321 pcbSize->QuadPart = sizeof(DWORD);
322
323 IMoniker_Enum(iface,TRUE,&enumMk);
324
325 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
326
327 IMoniker_GetSizeMax(pmk,&ptmpSize);
328
329 IMoniker_Release(pmk);
330
331 pcbSize->QuadPart = ptmpSize.QuadPart + sizeof(CLSID);
332 }
333
334 IEnumMoniker_Release(enumMk);
335
336 return S_OK;
337 }
338
339 /******************************************************************************
340 * CompositeMoniker_BindToObject
341 ******************************************************************************/
342 static HRESULT WINAPI
343 CompositeMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc,
344 IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
345 {
346 HRESULT res;
347 IRunningObjectTable *prot;
348 IMoniker *tempMk,*antiMk,*mostRigthMk;
349 IEnumMoniker *enumMoniker;
350
351 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
352
353 if (ppvResult==NULL)
354 return E_POINTER;
355
356 *ppvResult=0;
357 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
358 /* object for the requested interface pointer. */
359 if(pmkToLeft==NULL){
360
361 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
362
363 if (SUCCEEDED(res)){
364
365 /* if the requested class was loaded before ! we don't need to reload it */
366 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
367
368 if (res==S_OK)
369 return res;
370 }
371 }
372 else{
373 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
374 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
375
376 IMoniker_Enum(iface,FALSE,&enumMoniker);
377 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
378 IEnumMoniker_Release(enumMoniker);
379
380 res=CreateAntiMoniker(&antiMk);
381 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
382 IMoniker_Release(antiMk);
383
384 res=IMoniker_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
385
386 IMoniker_Release(tempMk);
387 IMoniker_Release(mostRigthMk);
388 }
389
390 return res;
391 }
392
393 /******************************************************************************
394 * CompositeMoniker_BindToStorage
395 ******************************************************************************/
396 static HRESULT WINAPI
397 CompositeMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc,
398 IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
399 {
400 HRESULT res;
401 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftMk;
402 IEnumMoniker *enumMoniker;
403
404 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
405
406 *ppvResult=0;
407
408 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
409 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
410
411 if (pmkToLeft)
412 {
413 res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk);
414 if (FAILED(res)) return res;
415 }
416 else
417 leftMk = iface;
418
419 IMoniker_Enum(iface, FALSE, &enumMoniker);
420 IEnumMoniker_Next(enumMoniker, 1, &mostRigthMk, NULL);
421 IEnumMoniker_Release(enumMoniker);
422
423 res = CreateAntiMoniker(&antiMk);
424 if (FAILED(res)) return res;
425 res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk);
426 if (FAILED(res)) return res;
427 IMoniker_Release(antiMk);
428
429 res = IMoniker_BindToStorage(mostRigthMk, pbc, tempMk, riid, ppvResult);
430
431 IMoniker_Release(tempMk);
432
433 IMoniker_Release(mostRigthMk);
434
435 if (pmkToLeft)
436 IMoniker_Release(leftMk);
437
438 return res;
439 }
440
441 /******************************************************************************
442 * CompositeMoniker_Reduce
443 ******************************************************************************/
444 static HRESULT WINAPI
445 CompositeMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
446 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
447 {
448 HRESULT res;
449 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
450 IEnumMoniker *enumMoniker;
451
452 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
453
454 if (ppmkReduced==NULL)
455 return E_POINTER;
456
457 /* This method recursively calls Reduce for each of its component monikers. */
458
459 if (ppmkToLeft==NULL){
460
461 IMoniker_Enum(iface,FALSE,&enumMoniker);
462 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
463 IEnumMoniker_Release(enumMoniker);
464
465 res=CreateAntiMoniker(&antiMk);
466 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
467 IMoniker_Release(antiMk);
468
469 return IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
470 }
471 else if (*ppmkToLeft==NULL)
472
473 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
474
475 else{
476
477 /* separate the composite moniker in to left and right moniker */
478 IMoniker_Enum(iface,FALSE,&enumMoniker);
479 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
480 IEnumMoniker_Release(enumMoniker);
481
482 res=CreateAntiMoniker(&antiMk);
483 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
484 IMoniker_Release(antiMk);
485
486 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
487 /* of the reduced components */
488 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
489 IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
490 )
491
492 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
493
494 else{
495 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
496
497 IMoniker_AddRef(iface);
498
499 *ppmkReduced=iface;
500
501 return MK_S_REDUCED_TO_SELF;
502 }
503 }
504 }
505
506 /******************************************************************************
507 * CompositeMoniker_ComposeWith
508 ******************************************************************************/
509 static HRESULT WINAPI
510 CompositeMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
511 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
512 {
513 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
514
515 if ((ppmkComposite==NULL)||(pmkRight==NULL))
516 return E_POINTER;
517
518 *ppmkComposite=0;
519
520 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
521 /* otherwise, the method returns the result of combining the two monikers by calling the */
522 /* CreateGenericComposite function */
523
524 if (fOnlyIfNotGeneric)
525 return MK_E_NEEDGENERIC;
526
527 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
528 }
529
530 /******************************************************************************
531 * CompositeMoniker_Enum
532 ******************************************************************************/
533 static HRESULT WINAPI
534 CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
535 {
536 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
537
538 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
539
540 if (ppenumMoniker == NULL)
541 return E_POINTER;
542
543 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
544 }
545
546 /******************************************************************************
547 * CompositeMoniker_IsEqual
548 ******************************************************************************/
549 static HRESULT WINAPI
550 CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
551 {
552 IEnumMoniker *enumMoniker1,*enumMoniker2;
553 IMoniker *tempMk1,*tempMk2;
554 HRESULT res1,res2,res;
555 BOOL done;
556
557 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
558
559 if (pmkOtherMoniker==NULL)
560 return S_FALSE;
561
562 /* This method returns S_OK if the components of both monikers are equal when compared in the */
563 /* left-to-right order.*/
564 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
565
566 if (enumMoniker1==NULL)
567 return S_FALSE;
568
569 IMoniker_Enum(iface,TRUE,&enumMoniker2);
570
571 do {
572
573 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
574 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
575
576 if((res1==S_OK)&&(res2==S_OK)){
577 done = (res = IMoniker_IsEqual(tempMk1,tempMk2)) == S_FALSE;
578 }
579 else
580 {
581 res = (res1==S_FALSE) && (res2==S_FALSE);
582 done = TRUE;
583 }
584
585 if (res1==S_OK)
586 IMoniker_Release(tempMk1);
587
588 if (res2==S_OK)
589 IMoniker_Release(tempMk2);
590 } while (!done);
591
592 IEnumMoniker_Release(enumMoniker1);
593 IEnumMoniker_Release(enumMoniker2);
594
595 return res;
596 }
597 /******************************************************************************
598 * CompositeMoniker_Hash
599 ******************************************************************************/
600 static HRESULT WINAPI
601 CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
602 {
603 IEnumMoniker *enumMoniker;
604 IMoniker *tempMk;
605 HRESULT res;
606 DWORD tempHash;
607
608 TRACE("(%p,%p)\n",iface,pdwHash);
609
610 if (pdwHash==NULL)
611 return E_POINTER;
612
613 res = IMoniker_Enum(iface,TRUE,&enumMoniker);
614 if(FAILED(res))
615 return res;
616
617 *pdwHash = 0;
618
619 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
620 res = IMoniker_Hash(tempMk, &tempHash);
621 if(FAILED(res))
622 break;
623 *pdwHash = *pdwHash ^ tempHash;
624
625 IMoniker_Release(tempMk);
626 }
627
628 IEnumMoniker_Release(enumMoniker);
629
630 return res;
631 }
632
633 /******************************************************************************
634 * CompositeMoniker_IsRunning
635 ******************************************************************************/
636 static HRESULT WINAPI
637 CompositeMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc,
638 IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning)
639 {
640 IRunningObjectTable* rot;
641 HRESULT res;
642 IMoniker *tempMk,*antiMk,*mostRigthMk;
643 IEnumMoniker *enumMoniker;
644
645 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
646
647 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
648 if (pmkToLeft!=NULL){
649
650 CreateGenericComposite(pmkToLeft,iface,&tempMk);
651
652 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
653
654 IMoniker_Release(tempMk);
655
656 return res;
657 }
658 else
659 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
660 /* to this moniker */
661
662 if (pmkNewlyRunning!=NULL)
663
664 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
665 return S_OK;
666
667 else
668 return S_FALSE;
669
670 else{
671
672 if (pbc==NULL)
673 return E_POINTER;
674
675 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
676 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
677 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
678 /* the composite as the pmkToLeft parameter for that call. */
679
680 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
681
682 if (FAILED(res))
683 return res;
684
685 res = IRunningObjectTable_IsRunning(rot,iface);
686 IRunningObjectTable_Release(rot);
687
688 if(res==S_OK)
689 return S_OK;
690
691 else{
692
693 IMoniker_Enum(iface,FALSE,&enumMoniker);
694 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
695 IEnumMoniker_Release(enumMoniker);
696
697 res=CreateAntiMoniker(&antiMk);
698 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
699 IMoniker_Release(antiMk);
700
701 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
702
703 IMoniker_Release(tempMk);
704 IMoniker_Release(mostRigthMk);
705
706 return res;
707 }
708 }
709 }
710
711 /******************************************************************************
712 * CompositeMoniker_GetTimeOfLastChange
713 ******************************************************************************/
714 static HRESULT WINAPI
715 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
716 IMoniker* pmkToLeft, FILETIME* pCompositeTime)
717 {
718 HRESULT res;
719 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftMk;
720 IEnumMoniker *enumMoniker;
721
722 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
723
724 if (pCompositeTime==NULL)
725 return E_INVALIDARG;
726
727 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
728 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
729 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
730 /* of the composite as the pmkToLeft parameter for that call. */
731 if (pmkToLeft)
732 {
733 IRunningObjectTable* rot;
734
735 res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk);
736
737 res = IBindCtx_GetRunningObjectTable(pbc,&rot);
738 if (FAILED(res))
739 {
740 IMoniker_Release(leftMk);
741 return res;
742 }
743
744 if (IRunningObjectTable_GetTimeOfLastChange(rot,leftMk,pCompositeTime)==S_OK)
745 {
746 IMoniker_Release(leftMk);
747 return res;
748 }
749 }
750 else
751 leftMk = iface;
752
753 IMoniker_Enum(iface, FALSE, &enumMoniker);
754 IEnumMoniker_Next(enumMoniker, 1, &mostRigthMk, NULL);
755 IEnumMoniker_Release(enumMoniker);
756
757 res = CreateAntiMoniker(&antiMk);
758 res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk);
759 IMoniker_Release(antiMk);
760
761 res = IMoniker_GetTimeOfLastChange(mostRigthMk, pbc, tempMk, pCompositeTime);
762
763 IMoniker_Release(tempMk);
764 IMoniker_Release(mostRigthMk);
765
766 if (pmkToLeft)
767 IMoniker_Release(leftMk);
768
769 return res;
770 }
771
772 /******************************************************************************
773 * CompositeMoniker_Inverse
774 ******************************************************************************/
775 static HRESULT WINAPI
776 CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
777 {
778 HRESULT res;
779 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
780 IEnumMoniker *enumMoniker;
781
782 TRACE("(%p,%p)\n",iface,ppmk);
783
784 if (ppmk==NULL)
785 return E_POINTER;
786
787 /* This method returns a composite moniker that consists of the inverses of each of the components */
788 /* of the original composite, stored in reverse order */
789
790 res=CreateAntiMoniker(&antiMk);
791 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
792 IMoniker_Release(antiMk);
793
794 if (tempMk==NULL)
795
796 return IMoniker_Inverse(iface,ppmk);
797
798 else{
799
800 IMoniker_Enum(iface,FALSE,&enumMoniker);
801 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
802 IEnumMoniker_Release(enumMoniker);
803
804 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
805 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
806
807 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
808
809 IMoniker_Release(tempMk);
810 IMoniker_Release(mostRigthMk);
811 IMoniker_Release(tempInvMk);
812 IMoniker_Release(mostRigthInvMk);
813
814 return res;
815 }
816 }
817
818 /******************************************************************************
819 * CompositeMoniker_CommonPrefixWith
820 ******************************************************************************/
821 static HRESULT WINAPI
822 CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface, IMoniker* pmkOther,
823 IMoniker** ppmkPrefix)
824 {
825 DWORD mkSys;
826 HRESULT res1,res2;
827 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
828 IEnumMoniker *enumMoniker1,*enumMoniker2;
829 ULONG i,nbCommonMk=0;
830
831 /* If the other moniker is a composite, this method compares the components of each composite from left */
832 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
833 /* of the leftmost components were common to both monikers. */
834
835 if (ppmkPrefix==NULL)
836 return E_POINTER;
837
838 *ppmkPrefix=0;
839
840 if (pmkOther==NULL)
841 return MK_E_NOPREFIX;
842
843 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
844
845 if((mkSys==MKSYS_GENERICCOMPOSITE)){
846
847 IMoniker_Enum(iface,TRUE,&enumMoniker1);
848 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
849
850 while(1){
851
852 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
853 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
854
855 if ((res1==S_FALSE) && (res2==S_FALSE)){
856
857 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
858 *ppmkPrefix=iface;
859 IMoniker_AddRef(iface);
860 return MK_S_US;
861 }
862 else if ((res1==S_OK) && (res2==S_OK)){
863
864 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
865
866 nbCommonMk++;
867
868 else
869 break;
870
871 }
872 else if (res1==S_OK){
873
874 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
875 /* ppmkPrefix to the other moniker. */
876 *ppmkPrefix=pmkOther;
877 return MK_S_HIM;
878 }
879 else{
880 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
881 /* to this moniker. */
882 *ppmkPrefix=iface;
883 return MK_S_ME;
884 }
885 }
886
887 IEnumMoniker_Release(enumMoniker1);
888 IEnumMoniker_Release(enumMoniker2);
889
890 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
891 if (nbCommonMk==0)
892 return MK_E_NOPREFIX;
893
894 IEnumMoniker_Reset(enumMoniker1);
895
896 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
897
898 /* if we have more than one common moniker the result will be a composite moniker */
899 if (nbCommonMk>1){
900
901 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
902 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
903 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
904 IMoniker_Release(tempMk1);
905 IMoniker_Release(tempMk2);
906
907 /* compose all common monikers in a composite moniker */
908 for(i=0;i<nbCommonMk;i++){
909
910 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
911
912 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
913
914 IMoniker_Release(*ppmkPrefix);
915
916 IMoniker_Release(tempMk1);
917
918 *ppmkPrefix=tempMk2;
919 }
920 return S_OK;
921 }
922 else{
923 /* if we have only one common moniker the result will be a simple moniker which is the most-left one*/
924 *ppmkPrefix=tempMk1;
925
926 return S_OK;
927 }
928 }
929 else{
930 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
931 of this moniker.*/
932
933 IMoniker_Enum(iface,TRUE,&enumMoniker1);
934
935 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
936
937 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
938
939 *ppmkPrefix=pmkOther;
940
941 return MK_S_HIM;
942 }
943 else
944 return MK_E_NOPREFIX;
945 }
946 }
947
948 /***************************************************************************************************
949 * GetAfterCommonPrefix (local function)
950 * This function returns a moniker that consist of the remainder when the common prefix is removed
951 ***************************************************************************************************/
952 static VOID GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
953 {
954 IMoniker *tempMk,*tempMk1,*tempMk2;
955 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
956 ULONG nbRestMk=0;
957 DWORD mkSys;
958 HRESULT res1,res2;
959
960 *restMk=0;
961
962 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
963 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
964 /* on the first difference. */
965 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
966
967 IMoniker_IsSystemMoniker(commonMk,&mkSys);
968
969 if (mkSys==MKSYS_GENERICCOMPOSITE){
970
971 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
972 while(1){
973
974 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
975 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
976
977 if ((res1==S_FALSE)||(res2==S_FALSE)){
978
979 if (res1==S_OK)
980
981 nbRestMk++;
982
983 IMoniker_Release(tempMk1);
984 IMoniker_Release(tempMk2);
985
986 break;
987 }
988 IMoniker_Release(tempMk1);
989 IMoniker_Release(tempMk2);
990 }
991 }
992 else{
993 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
994 IMoniker_Release(tempMk1);
995 }
996
997 /* count the number of elements in the enumerator after the common prefix */
998 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
999
1000 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1001
1002 IMoniker_Release(tempMk);
1003
1004 if (nbRestMk==0)
1005 return;
1006
1007 /* create a generic composite moniker with monikers located after the common prefix */
1008 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1009
1010 if (nbRestMk==1){
1011
1012 *restMk= tempMk1;
1013 return;
1014 }
1015 else {
1016
1017 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1018
1019 CreateGenericComposite(tempMk1,tempMk2,restMk);
1020
1021 IMoniker_Release(tempMk1);
1022
1023 IMoniker_Release(tempMk2);
1024
1025 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1026
1027 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1028
1029 IMoniker_Release(tempMk1);
1030
1031 IMoniker_Release(*restMk);
1032
1033 *restMk=tempMk2;
1034 }
1035 }
1036 }
1037
1038 /******************************************************************************
1039 * CompositeMoniker_RelativePathTo
1040 ******************************************************************************/
1041 static HRESULT WINAPI
1042 CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther,
1043 IMoniker** ppmkRelPath)
1044 {
1045 HRESULT res;
1046 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1047
1048 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1049
1050 if (ppmkRelPath==NULL)
1051 return E_POINTER;
1052
1053 *ppmkRelPath=0;
1054
1055 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1056 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1057 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1058
1059 /* finds the common prefix of the two monikers */
1060 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1061
1062 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1063 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1064
1065 *ppmkRelPath=pmkOther;
1066 IMoniker_AddRef(pmkOther);
1067 return MK_S_HIM;
1068 }
1069
1070 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1071 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1072
1073 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1074 /* moniker when the common prefix is removed */
1075 if (res==MK_S_HIM){
1076
1077 IMoniker_Inverse(restThisMk,ppmkRelPath);
1078 IMoniker_Release(restThisMk);
1079 }
1080 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1081 /* when the common prefix is removed */
1082 else if (res==MK_S_ME){
1083
1084 *ppmkRelPath=restOtherMk;
1085 IMoniker_AddRef(restOtherMk);
1086 }
1087 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1088 /* moniker on the right of it. */
1089 else if (res==S_OK){
1090
1091 IMoniker_Inverse(restThisMk,&invRestThisMk);
1092 IMoniker_Release(restThisMk);
1093 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1094 IMoniker_Release(invRestThisMk);
1095 IMoniker_Release(restOtherMk);
1096 }
1097 return S_OK;
1098 }
1099
1100 /******************************************************************************
1101 * CompositeMoniker_GetDisplayName
1102 ******************************************************************************/
1103 static HRESULT WINAPI
1104 CompositeMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
1105 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
1106 {
1107 ULONG lengthStr=1;
1108 IEnumMoniker *enumMoniker;
1109 IMoniker* tempMk;
1110 LPOLESTR tempStr;
1111
1112 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1113
1114 if (ppszDisplayName==NULL)
1115 return E_POINTER;
1116
1117 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1118
1119 if (*ppszDisplayName==NULL)
1120 return E_OUTOFMEMORY;
1121
1122 /* This method returns the concatenation of the display names returned by each component moniker of */
1123 /* the composite */
1124
1125 **ppszDisplayName=0;
1126
1127 IMoniker_Enum(iface,TRUE,&enumMoniker);
1128
1129 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1130
1131 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1132
1133 lengthStr+=lstrlenW(tempStr);
1134
1135 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1136
1137 if (*ppszDisplayName==NULL)
1138 return E_OUTOFMEMORY;
1139
1140 strcatW(*ppszDisplayName,tempStr);
1141
1142 CoTaskMemFree(tempStr);
1143 IMoniker_Release(tempMk);
1144 }
1145
1146 IEnumMoniker_Release(enumMoniker);
1147
1148 return S_OK;
1149 }
1150
1151 /******************************************************************************
1152 * CompositeMoniker_ParseDisplayName
1153 ******************************************************************************/
1154 static HRESULT WINAPI
1155 CompositeMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
1156 IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten,
1157 IMoniker** ppmkOut)
1158 {
1159 IEnumMoniker *enumMoniker;
1160 IMoniker *tempMk,*mostRigthMk,*antiMk;
1161 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1162 /* passing everything else as the pmkToLeft parameter for that call. */
1163
1164 /* get the most right moniker */
1165 IMoniker_Enum(iface,FALSE,&enumMoniker);
1166 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1167 IEnumMoniker_Release(enumMoniker);
1168
1169 /* get the left moniker */
1170 CreateAntiMoniker(&antiMk);
1171 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1172 IMoniker_Release(antiMk);
1173
1174 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1175 }
1176
1177 /******************************************************************************
1178 * CompositeMoniker_IsSystemMoniker
1179 ******************************************************************************/
1180 static HRESULT WINAPI
1181 CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1182 {
1183 TRACE("(%p,%p)\n",iface,pwdMksys);
1184
1185 if (!pwdMksys)
1186 return E_POINTER;
1187
1188 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1189
1190 return S_OK;
1191 }
1192
1193 /*******************************************************************************
1194 * CompositeMonikerIROTData_QueryInterface
1195 *******************************************************************************/
1196 static HRESULT WINAPI
1197 CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
1198 VOID** ppvObject)
1199 {
1200
1201 IMoniker *This = impl_from_IROTData(iface);
1202
1203 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1204
1205 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1206 }
1207
1208 /***********************************************************************
1209 * CompositeMonikerIROTData_AddRef
1210 */
1211 static ULONG WINAPI
1212 CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1213 {
1214 IMoniker *This = impl_from_IROTData(iface);
1215
1216 TRACE("(%p)\n",iface);
1217
1218 return IMoniker_AddRef(This);
1219 }
1220
1221 /***********************************************************************
1222 * CompositeMonikerIROTData_Release
1223 */
1224 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1225 {
1226 IMoniker *This = impl_from_IROTData(iface);
1227
1228 TRACE("(%p)\n",iface);
1229
1230 return IMoniker_Release(This);
1231 }
1232
1233 /******************************************************************************
1234 * CompositeMonikerIROTData_GetComparisonData
1235 ******************************************************************************/
1236 static HRESULT WINAPI
1237 CompositeMonikerROTDataImpl_GetComparisonData(IROTData* iface,
1238 BYTE* pbData, ULONG cbMax, ULONG* pcbData)
1239 {
1240 IMoniker *This = impl_from_IROTData(iface);
1241 IEnumMoniker *pEnumMk;
1242 IMoniker *pmk;
1243 HRESULT hr;
1244
1245 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
1246
1247 *pcbData = sizeof(CLSID);
1248
1249 hr = IMoniker_Enum(This, TRUE, &pEnumMk);
1250 if (FAILED(hr)) return hr;
1251
1252 while(IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1253 {
1254 IROTData *pROTData;
1255 hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData);
1256 if (FAILED(hr))
1257 ERR("moniker doesn't support IROTData interface\n");
1258
1259 if (SUCCEEDED(hr))
1260 {
1261 ULONG cbData;
1262 hr = IROTData_GetComparisonData(pROTData, NULL, 0, &cbData);
1263 IROTData_Release(pROTData);
1264 if (SUCCEEDED(hr) || (hr == E_OUTOFMEMORY))
1265 {
1266 *pcbData += cbData;
1267 hr = S_OK;
1268 }
1269 else
1270 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr);
1271 }
1272
1273 IMoniker_Release(pmk);
1274
1275 if (FAILED(hr))
1276 {
1277 IEnumMoniker_Release(pEnumMk);
1278 return hr;
1279 }
1280 }
1281 if (cbMax < *pcbData)
1282 return E_OUTOFMEMORY;
1283
1284 IEnumMoniker_Reset(pEnumMk);
1285
1286 memcpy(pbData, &CLSID_CompositeMoniker, sizeof(CLSID));
1287 pbData += sizeof(CLSID);
1288 cbMax -= sizeof(CLSID);
1289
1290 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1291 {
1292 IROTData *pROTData;
1293 hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData);
1294 if (FAILED(hr))
1295 ERR("moniker doesn't support IROTData interface\n");
1296
1297 if (SUCCEEDED(hr))
1298 {
1299 ULONG cbData;
1300 hr = IROTData_GetComparisonData(pROTData, pbData, cbMax, &cbData);
1301 IROTData_Release(pROTData);
1302 if (SUCCEEDED(hr))
1303 {
1304 pbData += cbData;
1305 cbMax -= cbData;
1306 }
1307 else
1308 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr);
1309 }
1310
1311 IMoniker_Release(pmk);
1312
1313 if (FAILED(hr))
1314 {
1315 IEnumMoniker_Release(pEnumMk);
1316 return hr;
1317 }
1318 }
1319
1320 IEnumMoniker_Release(pEnumMk);
1321
1322 return S_OK;
1323 }
1324
1325 static HRESULT WINAPI CompositeMonikerMarshalImpl_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
1326 {
1327 IMoniker *This = impl_from_IMarshal(iface);
1328
1329 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppv);
1330
1331 return CompositeMonikerImpl_QueryInterface(This, riid, ppv);
1332 }
1333
1334 static ULONG WINAPI CompositeMonikerMarshalImpl_AddRef(IMarshal *iface)
1335 {
1336 IMoniker *This = impl_from_IMarshal(iface);
1337
1338 TRACE("(%p)\n",iface);
1339
1340 return CompositeMonikerImpl_AddRef(This);
1341 }
1342
1343 static ULONG WINAPI CompositeMonikerMarshalImpl_Release(IMarshal *iface)
1344 {
1345 IMoniker *This = impl_from_IMarshal(iface);
1346
1347 TRACE("(%p)\n",iface);
1348
1349 return CompositeMonikerImpl_Release(This);
1350 }
1351
1352 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetUnmarshalClass(
1353 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1354 void* pvDestContext, DWORD mshlflags, CLSID* pCid)
1355 {
1356 IMoniker *This = impl_from_IMarshal(iface);
1357
1358 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
1359 dwDestContext, pvDestContext, mshlflags, pCid);
1360
1361 return IMoniker_GetClassID(This, pCid);
1362 }
1363
1364 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetMarshalSizeMax(
1365 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1366 void* pvDestContext, DWORD mshlflags, DWORD* pSize)
1367 {
1368 IMoniker *This = impl_from_IMarshal(iface);
1369 IEnumMoniker *pEnumMk;
1370 IMoniker *pmk;
1371 HRESULT hr;
1372 ULARGE_INTEGER size;
1373
1374 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
1375 dwDestContext, pvDestContext, mshlflags, pSize);
1376
1377 *pSize = 0x10; /* to match native */
1378
1379 hr = IMoniker_Enum(This, TRUE, &pEnumMk);
1380 if (FAILED(hr)) return hr;
1381
1382 hr = IMoniker_GetSizeMax(This, &size);
1383
1384 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1385 {
1386 ULONG size;
1387
1388 hr = CoGetMarshalSizeMax(&size, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags);
1389 if (SUCCEEDED(hr))
1390 *pSize += size;
1391
1392 IMoniker_Release(pmk);
1393
1394 if (FAILED(hr))
1395 {
1396 IEnumMoniker_Release(pEnumMk);
1397 return hr;
1398 }
1399 }
1400
1401 IEnumMoniker_Release(pEnumMk);
1402
1403 return S_OK;
1404 }
1405
1406 static HRESULT WINAPI CompositeMonikerMarshalImpl_MarshalInterface(LPMARSHAL iface, IStream *pStm,
1407 REFIID riid, void* pv, DWORD dwDestContext,
1408 void* pvDestContext, DWORD mshlflags)
1409 {
1410 IMoniker *This = impl_from_IMarshal(iface);
1411 IEnumMoniker *pEnumMk;
1412 IMoniker *pmk;
1413 HRESULT hr;
1414 ULONG i = 0;
1415
1416 TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv,
1417 dwDestContext, pvDestContext, mshlflags);
1418
1419 hr = IMoniker_Enum(This, TRUE, &pEnumMk);
1420 if (FAILED(hr)) return hr;
1421
1422 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1423 {
1424 hr = CoMarshalInterface(pStm, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags);
1425
1426 IMoniker_Release(pmk);
1427
1428 if (FAILED(hr))
1429 {
1430 IEnumMoniker_Release(pEnumMk);
1431 return hr;
1432 }
1433 i++;
1434 }
1435
1436 if (i != 2)
1437 FIXME("moniker count of %d not supported\n", i);
1438
1439 IEnumMoniker_Release(pEnumMk);
1440
1441 return S_OK;
1442 }
1443
1444 static HRESULT WINAPI CompositeMonikerMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
1445 {
1446 CompositeMonikerImpl *This = (CompositeMonikerImpl *)impl_from_IMarshal(iface);
1447 HRESULT hr;
1448
1449 TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
1450
1451 CompositeMonikerImpl_ReleaseMonikersInTable(This);
1452
1453 /* resize the table if needed */
1454 if (This->tabLastIndex + 2 > This->tabSize)
1455 {
1456 This->tabSize += max(BLOCK_TAB_SIZE, 2);
1457 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1458
1459 if (This->tabMoniker==NULL)
1460 return E_OUTOFMEMORY;
1461 }
1462
1463 hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]);
1464 if (FAILED(hr))
1465 {
1466 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr);
1467 return hr;
1468 }
1469 This->tabLastIndex++;
1470 hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]);
1471 if (FAILED(hr))
1472 {
1473 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr);
1474 return hr;
1475 }
1476 This->tabLastIndex++;
1477
1478 return IMoniker_QueryInterface((IMoniker *)&This->lpvtbl1, riid, ppv);
1479 }
1480
1481 static HRESULT WINAPI CompositeMonikerMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
1482 {
1483 TRACE("(%p)\n", pStm);
1484 /* can't release a state-based marshal as nothing on server side to
1485 * release */
1486 return S_OK;
1487 }
1488
1489 static HRESULT WINAPI CompositeMonikerMarshalImpl_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)
1490 {
1491 TRACE("(0x%x)\n", dwReserved);
1492 /* can't disconnect a state-based marshal as nothing on server side to
1493 * disconnect from */
1494 return S_OK;
1495 }
1496
1497 /******************************************************************************
1498 * EnumMonikerImpl_QueryInterface
1499 ******************************************************************************/
1500 static HRESULT WINAPI
1501 EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1502 {
1503 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1504
1505 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1506
1507 /* Perform a sanity check on the parameters.*/
1508 if ( (This==0) || (ppvObject==0) )
1509 return E_INVALIDARG;
1510
1511 /* Initialize the return parameter */
1512 *ppvObject = 0;
1513
1514 /* Compare the riid with the interface IDs implemented by this object.*/
1515 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1516 *ppvObject = iface;
1517
1518 /* Check that we obtained an interface.*/
1519 if ((*ppvObject)==0)
1520 return E_NOINTERFACE;
1521
1522 /* Query Interface always increases the reference count by one when it is successful */
1523 IEnumMoniker_AddRef(iface);
1524
1525 return S_OK;
1526 }
1527
1528 /******************************************************************************
1529 * EnumMonikerImpl_AddRef
1530 ******************************************************************************/
1531 static ULONG WINAPI
1532 EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1533 {
1534 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1535
1536 TRACE("(%p)\n",This);
1537
1538 return InterlockedIncrement(&This->ref);
1539
1540 }
1541
1542 /******************************************************************************
1543 * EnumMonikerImpl_Release
1544 ******************************************************************************/
1545 static ULONG WINAPI
1546 EnumMonikerImpl_Release(IEnumMoniker* iface)
1547 {
1548 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1549 ULONG i;
1550 ULONG ref;
1551 TRACE("(%p)\n",This);
1552
1553 ref = InterlockedDecrement(&This->ref);
1554
1555 /* destroy the object if there's no more reference on it */
1556 if (ref == 0) {
1557
1558 for(i=0;i<This->tabSize;i++)
1559 IMoniker_Release(This->tabMoniker[i]);
1560
1561 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1562 HeapFree(GetProcessHeap(),0,This);
1563 }
1564 return ref;
1565 }
1566
1567 /******************************************************************************
1568 * EnumMonikerImpl_Next
1569 ******************************************************************************/
1570 static HRESULT WINAPI
1571 EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt,
1572 ULONG* pceltFethed)
1573 {
1574 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1575 ULONG i;
1576
1577 /* retrieve the requested number of moniker from the current position */
1578 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1579 {
1580 rgelt[i]=This->tabMoniker[This->currentPos++];
1581 IMoniker_AddRef(rgelt[i]);
1582 }
1583
1584 if (pceltFethed!=NULL)
1585 *pceltFethed= i;
1586
1587 if (i==celt)
1588 return S_OK;
1589 else
1590 return S_FALSE;
1591 }
1592
1593 /******************************************************************************
1594 * EnumMonikerImpl_Skip
1595 ******************************************************************************/
1596 static HRESULT WINAPI
1597 EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt)
1598 {
1599 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1600
1601 if ((This->currentPos+celt) >= This->tabSize)
1602 return S_FALSE;
1603
1604 This->currentPos+=celt;
1605
1606 return S_OK;
1607 }
1608
1609 /******************************************************************************
1610 * EnumMonikerImpl_Reset
1611 ******************************************************************************/
1612 static HRESULT WINAPI
1613 EnumMonikerImpl_Reset(IEnumMoniker* iface)
1614 {
1615
1616 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1617
1618 This->currentPos=0;
1619
1620 return S_OK;
1621 }
1622
1623 /******************************************************************************
1624 * EnumMonikerImpl_Clone
1625 ******************************************************************************/
1626 static HRESULT WINAPI
1627 EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum)
1628 {
1629 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1630
1631 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1632 }
1633
1634 /********************************************************************************/
1635 /* Virtual function table for the IROTData class */
1636 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
1637 {
1638 EnumMonikerImpl_QueryInterface,
1639 EnumMonikerImpl_AddRef,
1640 EnumMonikerImpl_Release,
1641 EnumMonikerImpl_Next,
1642 EnumMonikerImpl_Skip,
1643 EnumMonikerImpl_Reset,
1644 EnumMonikerImpl_Clone
1645 };
1646
1647 /******************************************************************************
1648 * EnumMonikerImpl_CreateEnumMoniker
1649 ******************************************************************************/
1650 static HRESULT
1651 EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, ULONG tabSize,
1652 ULONG currentPos, BOOL leftToRigth, IEnumMoniker ** ppmk)
1653 {
1654 EnumMonikerImpl* newEnumMoniker;
1655 int i;
1656
1657 if (currentPos > tabSize)
1658 return E_INVALIDARG;
1659
1660 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1661
1662 if (newEnumMoniker == 0)
1663 return STG_E_INSUFFICIENTMEMORY;
1664
1665 /* Initialize the virtual function table. */
1666 newEnumMoniker->lpVtbl = &VT_EnumMonikerImpl;
1667 newEnumMoniker->ref = 1;
1668
1669 newEnumMoniker->tabSize=tabSize;
1670 newEnumMoniker->currentPos=currentPos;
1671
1672 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1673
1674 if (newEnumMoniker->tabMoniker==NULL) {
1675 HeapFree(GetProcessHeap(), 0, newEnumMoniker);
1676 return E_OUTOFMEMORY;
1677 }
1678
1679 if (leftToRigth)
1680 for (i=0;i<tabSize;i++){
1681
1682 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1683 IMoniker_AddRef(tabMoniker[i]);
1684 }
1685 else
1686 for (i=tabSize-1;i>=0;i--){
1687
1688 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1689 IMoniker_AddRef(tabMoniker[i]);
1690 }
1691
1692 *ppmk=(IEnumMoniker*)newEnumMoniker;
1693
1694 return S_OK;
1695 }
1696
1697 /********************************************************************************/
1698 /* Virtual function table for the CompositeMonikerImpl class which includes */
1699 /* IPersist, IPersistStream and IMoniker functions. */
1700
1701 static const IMonikerVtbl VT_CompositeMonikerImpl =
1702 {
1703 CompositeMonikerImpl_QueryInterface,
1704 CompositeMonikerImpl_AddRef,
1705 CompositeMonikerImpl_Release,
1706 CompositeMonikerImpl_GetClassID,
1707 CompositeMonikerImpl_IsDirty,
1708 CompositeMonikerImpl_Load,
1709 CompositeMonikerImpl_Save,
1710 CompositeMonikerImpl_GetSizeMax,
1711 CompositeMonikerImpl_BindToObject,
1712 CompositeMonikerImpl_BindToStorage,
1713 CompositeMonikerImpl_Reduce,
1714 CompositeMonikerImpl_ComposeWith,
1715 CompositeMonikerImpl_Enum,
1716 CompositeMonikerImpl_IsEqual,
1717 CompositeMonikerImpl_Hash,
1718 CompositeMonikerImpl_IsRunning,
1719 CompositeMonikerImpl_GetTimeOfLastChange,
1720 CompositeMonikerImpl_Inverse,
1721 CompositeMonikerImpl_CommonPrefixWith,
1722 CompositeMonikerImpl_RelativePathTo,
1723 CompositeMonikerImpl_GetDisplayName,
1724 CompositeMonikerImpl_ParseDisplayName,
1725 CompositeMonikerImpl_IsSystemMoniker
1726 };
1727
1728 /********************************************************************************/
1729 /* Virtual function table for the IROTData class. */
1730 static const IROTDataVtbl VT_ROTDataImpl =
1731 {
1732 CompositeMonikerROTDataImpl_QueryInterface,
1733 CompositeMonikerROTDataImpl_AddRef,
1734 CompositeMonikerROTDataImpl_Release,
1735 CompositeMonikerROTDataImpl_GetComparisonData
1736 };
1737
1738 static const IMarshalVtbl VT_MarshalImpl =
1739 {
1740 CompositeMonikerMarshalImpl_QueryInterface,
1741 CompositeMonikerMarshalImpl_AddRef,
1742 CompositeMonikerMarshalImpl_Release,
1743 CompositeMonikerMarshalImpl_GetUnmarshalClass,
1744 CompositeMonikerMarshalImpl_GetMarshalSizeMax,
1745 CompositeMonikerMarshalImpl_MarshalInterface,
1746 CompositeMonikerMarshalImpl_UnmarshalInterface,
1747 CompositeMonikerMarshalImpl_ReleaseMarshalData,
1748 CompositeMonikerMarshalImpl_DisconnectObject
1749 };
1750
1751 /******************************************************************************
1752 * Composite-Moniker_Construct (local function)
1753 *******************************************************************************/
1754 static HRESULT
1755 CompositeMonikerImpl_Construct(IMoniker** ppMoniker,
1756 LPMONIKER pmkFirst, LPMONIKER pmkRest)
1757 {
1758 DWORD mkSys;
1759 IEnumMoniker *enumMoniker;
1760 IMoniker *tempMk;
1761 HRESULT res;
1762 CompositeMonikerImpl *This;
1763
1764 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1765
1766 if (!This)
1767 return E_OUTOFMEMORY;
1768
1769 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
1770
1771 /* Initialize the virtual function table. */
1772 This->lpvtbl1 = &VT_CompositeMonikerImpl;
1773 This->lpvtbl2 = &VT_ROTDataImpl;
1774 This->lpvtblMarshal= &VT_MarshalImpl;
1775 This->ref = 1;
1776
1777 This->tabSize=BLOCK_TAB_SIZE;
1778 This->tabLastIndex=0;
1779
1780 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
1781 if (This->tabMoniker==NULL) {
1782 HeapFree(GetProcessHeap(), 0, This);
1783 return E_OUTOFMEMORY;
1784 }
1785
1786 if (!pmkFirst && !pmkRest)
1787 {
1788 *ppMoniker = (IMoniker *)This;
1789 return S_OK;
1790 }
1791
1792 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
1793
1794 /* put the first moniker contents in the beginning of the table */
1795 if (mkSys!=MKSYS_GENERICCOMPOSITE){
1796
1797 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
1798 IMoniker_AddRef(pmkFirst);
1799 }
1800 else{
1801
1802 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
1803
1804 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
1805
1806
1807 if (++This->tabLastIndex==This->tabSize){
1808 LPVOID tab_moniker = This->tabMoniker;
1809
1810 This->tabSize+=BLOCK_TAB_SIZE;
1811 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1812
1813 if (This->tabMoniker==NULL){
1814 HeapFree(GetProcessHeap(), 0, tab_moniker);
1815 HeapFree(GetProcessHeap(), 0, This);
1816 return E_OUTOFMEMORY;
1817 }
1818 }
1819 }
1820
1821 IEnumMoniker_Release(enumMoniker);
1822 }
1823
1824 /* put the rest moniker contents after the first one and make simplification if needed */
1825
1826 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
1827
1828 if (mkSys!=MKSYS_GENERICCOMPOSITE){
1829
1830 /* add a simple moniker to the moniker table */
1831
1832 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
1833
1834 if (res==MK_E_NEEDGENERIC){
1835
1836 /* there's no simplification in this case */
1837 This->tabMoniker[This->tabLastIndex]=pmkRest;
1838
1839 This->tabLastIndex++;
1840
1841 IMoniker_AddRef(pmkRest);
1842 }
1843 else if (tempMk==NULL){
1844
1845 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1846 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1847
1848 This->tabLastIndex--;
1849 }
1850 else if (SUCCEEDED(res)){
1851
1852 /* the non-generic composition was successful so we can make a simplification in this case */
1853 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1854
1855 This->tabMoniker[This->tabLastIndex-1]=tempMk;
1856 } else
1857 return res;
1858
1859 /* resize tabMoniker if needed */
1860 if (This->tabLastIndex==This->tabSize){
1861 LPVOID tab_moniker = This->tabMoniker;
1862
1863 This->tabSize+=BLOCK_TAB_SIZE;
1864
1865 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1866
1867 if (This->tabMoniker==NULL){
1868 HeapFree(GetProcessHeap(), 0, tab_moniker);
1869 HeapFree(GetProcessHeap(), 0, This);
1870 return E_OUTOFMEMORY;
1871 }
1872 }
1873 }
1874 else{
1875
1876 /* add a composite moniker to the moniker table (do the same thing
1877 * for each moniker within the composite moniker as a simple moniker
1878 * (see above for how to add a simple moniker case) )
1879 */
1880 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
1881
1882 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
1883
1884 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
1885
1886 if (res==MK_E_NEEDGENERIC){
1887
1888 This->tabLastIndex++;
1889 }
1890 else if (tempMk==NULL){
1891
1892 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1893 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
1894 This->tabLastIndex--;
1895 }
1896 else{
1897
1898 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1899
1900 This->tabMoniker[This->tabLastIndex-1]=tempMk;
1901 }
1902
1903 if (This->tabLastIndex==This->tabSize){
1904 LPVOID tab_moniker = This->tabMoniker;
1905
1906 This->tabSize+=BLOCK_TAB_SIZE;
1907
1908 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1909
1910 if (This->tabMoniker==NULL){
1911 HeapFree(GetProcessHeap(), 0, tab_moniker);
1912 HeapFree(GetProcessHeap(), 0, This);
1913 return E_OUTOFMEMORY;
1914 }
1915 }
1916 }
1917
1918 IEnumMoniker_Release(enumMoniker);
1919 }
1920
1921 /* only one moniker, then just return it */
1922 if (This->tabLastIndex == 1)
1923 {
1924 *ppMoniker = This->tabMoniker[0];
1925 IMoniker_AddRef(*ppMoniker);
1926 IMoniker_Release((IMoniker *)This);
1927 }
1928 else
1929 *ppMoniker = (IMoniker *)This;
1930
1931 return S_OK;
1932 }
1933
1934 /******************************************************************************
1935 * CreateGenericComposite [OLE32.@]
1936 ******************************************************************************/
1937 HRESULT WINAPI
1938 CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest,
1939 LPMONIKER* ppmkComposite)
1940 {
1941 IMoniker* moniker = 0;
1942 HRESULT hr = S_OK;
1943
1944 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1945
1946 if (ppmkComposite==NULL)
1947 return E_POINTER;
1948
1949 *ppmkComposite=0;
1950
1951 if (pmkFirst==NULL && pmkRest!=NULL){
1952
1953 *ppmkComposite=pmkRest;
1954 return S_OK;
1955 }
1956 else if (pmkFirst!=NULL && pmkRest==NULL){
1957 *ppmkComposite=pmkFirst;
1958 return S_OK;
1959 }
1960 else if (pmkFirst==NULL && pmkRest==NULL)
1961 return S_OK;
1962
1963 hr = CompositeMonikerImpl_Construct(&moniker,pmkFirst,pmkRest);
1964
1965 if (FAILED(hr))
1966 return hr;
1967
1968 hr = IMoniker_QueryInterface(moniker,&IID_IMoniker,(void**)ppmkComposite);
1969 IMoniker_Release(moniker);
1970
1971 return hr;
1972 }
1973
1974 /******************************************************************************
1975 * MonikerCommonPrefixWith [OLE32.@]
1976 ******************************************************************************/
1977 HRESULT WINAPI
1978 MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1979 {
1980 FIXME("(),stub!\n");
1981 return E_NOTIMPL;
1982 }
1983
1984 static HRESULT WINAPI CompositeMonikerCF_QueryInterface(LPCLASSFACTORY iface,
1985 REFIID riid, LPVOID *ppv)
1986 {
1987 *ppv = NULL;
1988 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
1989 {
1990 *ppv = iface;
1991 IUnknown_AddRef(iface);
1992 return S_OK;
1993 }
1994 return E_NOINTERFACE;
1995 }
1996
1997 static ULONG WINAPI CompositeMonikerCF_AddRef(LPCLASSFACTORY iface)
1998 {
1999 return 2; /* non-heap based object */
2000 }
2001
2002 static ULONG WINAPI CompositeMonikerCF_Release(LPCLASSFACTORY iface)
2003 {
2004 return 1; /* non-heap based object */
2005 }
2006
2007 static HRESULT WINAPI CompositeMonikerCF_CreateInstance(LPCLASSFACTORY iface,
2008 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
2009 {
2010 IMoniker* pMoniker;
2011 HRESULT hr;
2012
2013 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
2014
2015 *ppv = NULL;
2016
2017 if (pUnk)
2018 return CLASS_E_NOAGGREGATION;
2019
2020 hr = CompositeMonikerImpl_Construct(&pMoniker, NULL, NULL);
2021
2022 if (SUCCEEDED(hr))
2023 {
2024 hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
2025 IMoniker_Release(pMoniker);
2026 }
2027
2028 return hr;
2029 }
2030
2031 static HRESULT WINAPI CompositeMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
2032 {
2033 FIXME("(%d), stub!\n",fLock);
2034 return S_OK;
2035 }
2036
2037 static const IClassFactoryVtbl CompositeMonikerCFVtbl =
2038 {
2039 CompositeMonikerCF_QueryInterface,
2040 CompositeMonikerCF_AddRef,
2041 CompositeMonikerCF_Release,
2042 CompositeMonikerCF_CreateInstance,
2043 CompositeMonikerCF_LockServer
2044 };
2045 static const IClassFactoryVtbl *CompositeMonikerCF = &CompositeMonikerCFVtbl;
2046
2047 HRESULT CompositeMonikerCF_Create(REFIID riid, LPVOID *ppv)
2048 {
2049 return IClassFactory_QueryInterface((IClassFactory *)&CompositeMonikerCF, riid, ppv);
2050 }
2051
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.