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 = (IROTData*)&(This->lpvtbl2);
119 else if (IsEqualIID(&IID_IMarshal, riid))
120 *ppvObject = (IROTData*)&(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
556 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
557
558 if (pmkOtherMoniker==NULL)
559 return S_FALSE;
560
561 /* This method returns S_OK if the components of both monikers are equal when compared in the */
562 /* left-to-right order.*/
563 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
564
565 if (enumMoniker1==NULL)
566 return S_FALSE;
567
568 IMoniker_Enum(iface,TRUE,&enumMoniker2);
569
570 while(1){
571
572 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
573 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
574
575 if((res1==S_OK)&&(res2==S_OK)){
576
577 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
578 res= S_FALSE;
579 break;
580 }
581 else
582 continue;
583 }
584 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
585 res = S_OK;
586 break;
587 }
588 else{
589 res = S_FALSE;
590 break;
591 }
592
593 if (res1==S_OK)
594 IMoniker_Release(tempMk1);
595
596 if (res2==S_OK)
597 IMoniker_Release(tempMk2);
598 }
599
600 IEnumMoniker_Release(enumMoniker1);
601 IEnumMoniker_Release(enumMoniker2);
602
603 return res;
604 }
605 /******************************************************************************
606 * CompositeMoniker_Hash
607 ******************************************************************************/
608 static HRESULT WINAPI
609 CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
610 {
611 IEnumMoniker *enumMoniker;
612 IMoniker *tempMk;
613 HRESULT res;
614 DWORD tempHash;
615
616 TRACE("(%p,%p)\n",iface,pdwHash);
617
618 if (pdwHash==NULL)
619 return E_POINTER;
620
621 res = IMoniker_Enum(iface,TRUE,&enumMoniker);
622 if(FAILED(res))
623 return res;
624
625 *pdwHash = 0;
626
627 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
628 res = IMoniker_Hash(tempMk, &tempHash);
629 if(FAILED(res))
630 break;
631 *pdwHash = *pdwHash ^ tempHash;
632
633 IMoniker_Release(tempMk);
634 }
635
636 IEnumMoniker_Release(enumMoniker);
637
638 return res;
639 }
640
641 /******************************************************************************
642 * CompositeMoniker_IsRunning
643 ******************************************************************************/
644 static HRESULT WINAPI
645 CompositeMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc,
646 IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning)
647 {
648 IRunningObjectTable* rot;
649 HRESULT res;
650 IMoniker *tempMk,*antiMk,*mostRigthMk;
651 IEnumMoniker *enumMoniker;
652
653 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
654
655 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
656 if (pmkToLeft!=NULL){
657
658 CreateGenericComposite(pmkToLeft,iface,&tempMk);
659
660 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
661
662 IMoniker_Release(tempMk);
663
664 return res;
665 }
666 else
667 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
668 /* to this moniker */
669
670 if (pmkNewlyRunning!=NULL)
671
672 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
673 return S_OK;
674
675 else
676 return S_FALSE;
677
678 else{
679
680 if (pbc==NULL)
681 return E_POINTER;
682
683 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
684 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
685 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
686 /* the composite as the pmkToLeft parameter for that call. */
687
688 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
689
690 if (FAILED(res))
691 return res;
692
693 res = IRunningObjectTable_IsRunning(rot,iface);
694 IRunningObjectTable_Release(rot);
695
696 if(res==S_OK)
697 return S_OK;
698
699 else{
700
701 IMoniker_Enum(iface,FALSE,&enumMoniker);
702 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
703 IEnumMoniker_Release(enumMoniker);
704
705 res=CreateAntiMoniker(&antiMk);
706 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
707 IMoniker_Release(antiMk);
708
709 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
710
711 IMoniker_Release(tempMk);
712 IMoniker_Release(mostRigthMk);
713
714 return res;
715 }
716 }
717 }
718
719 /******************************************************************************
720 * CompositeMoniker_GetTimeOfLastChange
721 ******************************************************************************/
722 static HRESULT WINAPI
723 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
724 IMoniker* pmkToLeft, FILETIME* pCompositeTime)
725 {
726 HRESULT res;
727 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftMk;
728 IEnumMoniker *enumMoniker;
729
730 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
731
732 if (pCompositeTime==NULL)
733 return E_INVALIDARG;
734
735 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
736 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
737 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
738 /* of the composite as the pmkToLeft parameter for that call. */
739 if (pmkToLeft)
740 {
741 IRunningObjectTable* rot;
742
743 res = IMoniker_ComposeWith(pmkToLeft, iface, FALSE, &leftMk);
744
745 res = IBindCtx_GetRunningObjectTable(pbc,&rot);
746 if (FAILED(res))
747 {
748 IMoniker_Release(leftMk);
749 return res;
750 }
751
752 if (IRunningObjectTable_GetTimeOfLastChange(rot,leftMk,pCompositeTime)==S_OK)
753 {
754 IMoniker_Release(leftMk);
755 return res;
756 }
757 }
758 else
759 leftMk = iface;
760
761 IMoniker_Enum(iface, FALSE, &enumMoniker);
762 IEnumMoniker_Next(enumMoniker, 1, &mostRigthMk, NULL);
763 IEnumMoniker_Release(enumMoniker);
764
765 res = CreateAntiMoniker(&antiMk);
766 res = IMoniker_ComposeWith(leftMk, antiMk, 0, &tempMk);
767 IMoniker_Release(antiMk);
768
769 res = IMoniker_GetTimeOfLastChange(mostRigthMk, pbc, tempMk, pCompositeTime);
770
771 IMoniker_Release(tempMk);
772 IMoniker_Release(mostRigthMk);
773
774 if (pmkToLeft)
775 IMoniker_Release(leftMk);
776
777 return res;
778 }
779
780 /******************************************************************************
781 * CompositeMoniker_Inverse
782 ******************************************************************************/
783 static HRESULT WINAPI
784 CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
785 {
786 HRESULT res;
787 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
788 IEnumMoniker *enumMoniker;
789
790 TRACE("(%p,%p)\n",iface,ppmk);
791
792 if (ppmk==NULL)
793 return E_POINTER;
794
795 /* This method returns a composite moniker that consists of the inverses of each of the components */
796 /* of the original composite, stored in reverse order */
797
798 res=CreateAntiMoniker(&antiMk);
799 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
800 IMoniker_Release(antiMk);
801
802 if (tempMk==NULL)
803
804 return IMoniker_Inverse(iface,ppmk);
805
806 else{
807
808 IMoniker_Enum(iface,FALSE,&enumMoniker);
809 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
810 IEnumMoniker_Release(enumMoniker);
811
812 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
813 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
814
815 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
816
817 IMoniker_Release(tempMk);
818 IMoniker_Release(mostRigthMk);
819 IMoniker_Release(tempInvMk);
820 IMoniker_Release(mostRigthInvMk);
821
822 return res;
823 }
824 }
825
826 /******************************************************************************
827 * CompositeMoniker_CommonPrefixWith
828 ******************************************************************************/
829 static HRESULT WINAPI
830 CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface, IMoniker* pmkOther,
831 IMoniker** ppmkPrefix)
832 {
833 DWORD mkSys;
834 HRESULT res1,res2;
835 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
836 IEnumMoniker *enumMoniker1,*enumMoniker2;
837 ULONG i,nbCommonMk=0;
838
839 /* If the other moniker is a composite, this method compares the components of each composite from left */
840 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
841 /* of the leftmost components were common to both monikers. */
842
843 if (ppmkPrefix==NULL)
844 return E_POINTER;
845
846 *ppmkPrefix=0;
847
848 if (pmkOther==NULL)
849 return MK_E_NOPREFIX;
850
851 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
852
853 if((mkSys==MKSYS_GENERICCOMPOSITE)){
854
855 IMoniker_Enum(iface,TRUE,&enumMoniker1);
856 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
857
858 while(1){
859
860 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
861 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
862
863 if ((res1==S_FALSE) && (res2==S_FALSE)){
864
865 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
866 *ppmkPrefix=iface;
867 IMoniker_AddRef(iface);
868 return MK_S_US;
869 }
870 else if ((res1==S_OK) && (res2==S_OK)){
871
872 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
873
874 nbCommonMk++;
875
876 else
877 break;
878
879 }
880 else if (res1==S_OK){
881
882 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
883 /* ppmkPrefix to the other moniker. */
884 *ppmkPrefix=pmkOther;
885 return MK_S_HIM;
886 }
887 else{
888 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
889 /* to this moniker. */
890 *ppmkPrefix=iface;
891 return MK_S_ME;
892 }
893 }
894
895 IEnumMoniker_Release(enumMoniker1);
896 IEnumMoniker_Release(enumMoniker2);
897
898 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
899 if (nbCommonMk==0)
900 return MK_E_NOPREFIX;
901
902 IEnumMoniker_Reset(enumMoniker1);
903
904 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
905
906 /* if we have more than one common moniker the result will be a composite moniker */
907 if (nbCommonMk>1){
908
909 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
910 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
911 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
912 IMoniker_Release(tempMk1);
913 IMoniker_Release(tempMk2);
914
915 /* compose all common monikers in a composite moniker */
916 for(i=0;i<nbCommonMk;i++){
917
918 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
919
920 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
921
922 IMoniker_Release(*ppmkPrefix);
923
924 IMoniker_Release(tempMk1);
925
926 *ppmkPrefix=tempMk2;
927 }
928 return S_OK;
929 }
930 else{
931 /* if we have only one common moniker the result will be a simple moniker which is the most-left one*/
932 *ppmkPrefix=tempMk1;
933
934 return S_OK;
935 }
936 }
937 else{
938 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
939 of this moniker.*/
940
941 IMoniker_Enum(iface,TRUE,&enumMoniker1);
942
943 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
944
945 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
946
947 *ppmkPrefix=pmkOther;
948
949 return MK_S_HIM;
950 }
951 else
952 return MK_E_NOPREFIX;
953 }
954 }
955
956 /***************************************************************************************************
957 * GetAfterCommonPrefix (local function)
958 * This function returns a moniker that consist of the remainder when the common prefix is removed
959 ***************************************************************************************************/
960 static VOID GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
961 {
962 IMoniker *tempMk,*tempMk1,*tempMk2;
963 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
964 ULONG nbRestMk=0;
965 DWORD mkSys;
966 HRESULT res1,res2;
967
968 *restMk=0;
969
970 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
971 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
972 /* on the first difference. */
973 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
974
975 IMoniker_IsSystemMoniker(commonMk,&mkSys);
976
977 if (mkSys==MKSYS_GENERICCOMPOSITE){
978
979 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
980 while(1){
981
982 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
983 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
984
985 if ((res1==S_FALSE)||(res2==S_FALSE)){
986
987 if (res1==S_OK)
988
989 nbRestMk++;
990
991 IMoniker_Release(tempMk1);
992 IMoniker_Release(tempMk1);
993
994 break;
995 }
996 IMoniker_Release(tempMk1);
997 IMoniker_Release(tempMk1);
998 }
999 }
1000 else{
1001 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1002 IMoniker_Release(tempMk1);
1003 }
1004
1005 /* count the number of elements in the enumerator after the common prefix */
1006 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1007
1008 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1009
1010 IMoniker_Release(tempMk);
1011
1012 if (nbRestMk==0)
1013 return;
1014
1015 /* create a generic composite moniker with monikers located after the common prefix */
1016 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1017
1018 if (nbRestMk==1){
1019
1020 *restMk= tempMk1;
1021 return;
1022 }
1023 else {
1024
1025 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1026
1027 CreateGenericComposite(tempMk1,tempMk2,restMk);
1028
1029 IMoniker_Release(tempMk1);
1030
1031 IMoniker_Release(tempMk2);
1032
1033 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1034
1035 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1036
1037 IMoniker_Release(tempMk1);
1038
1039 IMoniker_Release(*restMk);
1040
1041 *restMk=tempMk2;
1042 }
1043 }
1044 }
1045
1046 /******************************************************************************
1047 * CompositeMoniker_RelativePathTo
1048 ******************************************************************************/
1049 static HRESULT WINAPI
1050 CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther,
1051 IMoniker** ppmkRelPath)
1052 {
1053 HRESULT res;
1054 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1055
1056 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1057
1058 if (ppmkRelPath==NULL)
1059 return E_POINTER;
1060
1061 *ppmkRelPath=0;
1062
1063 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1064 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1065 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1066
1067 /* finds the common prefix of the two monikers */
1068 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1069
1070 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1071 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1072
1073 *ppmkRelPath=pmkOther;
1074 IMoniker_AddRef(pmkOther);
1075 return MK_S_HIM;
1076 }
1077
1078 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1079 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1080
1081 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1082 /* moniker when the common prefix is removed */
1083 if (res==MK_S_HIM){
1084
1085 IMoniker_Inverse(restThisMk,ppmkRelPath);
1086 IMoniker_Release(restThisMk);
1087 }
1088 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1089 /* when the common prefix is removed */
1090 else if (res==MK_S_ME){
1091
1092 *ppmkRelPath=restOtherMk;
1093 IMoniker_AddRef(restOtherMk);
1094 }
1095 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1096 /* moniker on the right of it. */
1097 else if (res==S_OK){
1098
1099 IMoniker_Inverse(restThisMk,&invRestThisMk);
1100 IMoniker_Release(restThisMk);
1101 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1102 IMoniker_Release(invRestThisMk);
1103 IMoniker_Release(restOtherMk);
1104 }
1105 return S_OK;
1106 }
1107
1108 /******************************************************************************
1109 * CompositeMoniker_GetDisplayName
1110 ******************************************************************************/
1111 static HRESULT WINAPI
1112 CompositeMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
1113 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
1114 {
1115 ULONG lengthStr=1;
1116 IEnumMoniker *enumMoniker;
1117 IMoniker* tempMk;
1118 LPOLESTR tempStr;
1119
1120 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1121
1122 if (ppszDisplayName==NULL)
1123 return E_POINTER;
1124
1125 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1126
1127 if (*ppszDisplayName==NULL)
1128 return E_OUTOFMEMORY;
1129
1130 /* This method returns the concatenation of the display names returned by each component moniker of */
1131 /* the composite */
1132
1133 **ppszDisplayName=0;
1134
1135 IMoniker_Enum(iface,TRUE,&enumMoniker);
1136
1137 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1138
1139 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1140
1141 lengthStr+=lstrlenW(tempStr);
1142
1143 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1144
1145 if (*ppszDisplayName==NULL)
1146 return E_OUTOFMEMORY;
1147
1148 strcatW(*ppszDisplayName,tempStr);
1149
1150 CoTaskMemFree(tempStr);
1151 IMoniker_Release(tempMk);
1152 }
1153
1154 IEnumMoniker_Release(enumMoniker);
1155
1156 return S_OK;
1157 }
1158
1159 /******************************************************************************
1160 * CompositeMoniker_ParseDisplayName
1161 ******************************************************************************/
1162 static HRESULT WINAPI
1163 CompositeMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
1164 IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten,
1165 IMoniker** ppmkOut)
1166 {
1167 IEnumMoniker *enumMoniker;
1168 IMoniker *tempMk,*mostRigthMk,*antiMk;
1169 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1170 /* passing everything else as the pmkToLeft parameter for that call. */
1171
1172 /* get the most right moniker */
1173 IMoniker_Enum(iface,FALSE,&enumMoniker);
1174 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1175 IEnumMoniker_Release(enumMoniker);
1176
1177 /* get the left moniker */
1178 CreateAntiMoniker(&antiMk);
1179 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1180 IMoniker_Release(antiMk);
1181
1182 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1183 }
1184
1185 /******************************************************************************
1186 * CompositeMoniker_IsSystemMoniker
1187 ******************************************************************************/
1188 static HRESULT WINAPI
1189 CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1190 {
1191 TRACE("(%p,%p)\n",iface,pwdMksys);
1192
1193 if (!pwdMksys)
1194 return E_POINTER;
1195
1196 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1197
1198 return S_OK;
1199 }
1200
1201 /*******************************************************************************
1202 * CompositeMonikerIROTData_QueryInterface
1203 *******************************************************************************/
1204 static HRESULT WINAPI
1205 CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
1206 VOID** ppvObject)
1207 {
1208
1209 IMoniker *This = impl_from_IROTData(iface);
1210
1211 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1212
1213 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1214 }
1215
1216 /***********************************************************************
1217 * CompositeMonikerIROTData_AddRef
1218 */
1219 static ULONG WINAPI
1220 CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1221 {
1222 IMoniker *This = impl_from_IROTData(iface);
1223
1224 TRACE("(%p)\n",iface);
1225
1226 return IMoniker_AddRef(This);
1227 }
1228
1229 /***********************************************************************
1230 * CompositeMonikerIROTData_Release
1231 */
1232 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1233 {
1234 IMoniker *This = impl_from_IROTData(iface);
1235
1236 TRACE("(%p)\n",iface);
1237
1238 return IMoniker_Release(This);
1239 }
1240
1241 /******************************************************************************
1242 * CompositeMonikerIROTData_GetComparisonData
1243 ******************************************************************************/
1244 static HRESULT WINAPI
1245 CompositeMonikerROTDataImpl_GetComparisonData(IROTData* iface,
1246 BYTE* pbData, ULONG cbMax, ULONG* pcbData)
1247 {
1248 IMoniker *This = impl_from_IROTData(iface);
1249 IEnumMoniker *pEnumMk;
1250 IMoniker *pmk;
1251 HRESULT hr;
1252
1253 TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
1254
1255 *pcbData = sizeof(CLSID);
1256
1257 hr = IMoniker_Enum(This, TRUE, &pEnumMk);
1258 if (FAILED(hr)) return hr;
1259
1260 while(IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1261 {
1262 IROTData *pROTData;
1263 hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData);
1264 if (FAILED(hr))
1265 ERR("moniker doesn't support IROTData interface\n");
1266
1267 if (SUCCEEDED(hr))
1268 {
1269 ULONG cbData;
1270 hr = IROTData_GetComparisonData(pROTData, NULL, 0, &cbData);
1271 IROTData_Release(pROTData);
1272 if (SUCCEEDED(hr) || (hr == E_OUTOFMEMORY))
1273 {
1274 *pcbData += cbData;
1275 hr = S_OK;
1276 }
1277 else
1278 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr);
1279 }
1280
1281 IMoniker_Release(pmk);
1282
1283 if (FAILED(hr))
1284 {
1285 IEnumMoniker_Release(pEnumMk);
1286 return hr;
1287 }
1288 }
1289 if (cbMax < *pcbData)
1290 return E_OUTOFMEMORY;
1291
1292 IEnumMoniker_Reset(pEnumMk);
1293
1294 memcpy(pbData, &CLSID_CompositeMoniker, sizeof(CLSID));
1295 pbData += sizeof(CLSID);
1296 cbMax -= sizeof(CLSID);
1297
1298 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1299 {
1300 IROTData *pROTData;
1301 hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData);
1302 if (FAILED(hr))
1303 ERR("moniker doesn't support IROTData interface\n");
1304
1305 if (SUCCEEDED(hr))
1306 {
1307 ULONG cbData;
1308 hr = IROTData_GetComparisonData(pROTData, pbData, cbMax, &cbData);
1309 IROTData_Release(pROTData);
1310 if (SUCCEEDED(hr))
1311 {
1312 pbData += cbData;
1313 cbMax -= cbData;
1314 }
1315 else
1316 ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr);
1317 }
1318
1319 IMoniker_Release(pmk);
1320
1321 if (FAILED(hr))
1322 {
1323 IEnumMoniker_Release(pEnumMk);
1324 return hr;
1325 }
1326 }
1327
1328 IEnumMoniker_Release(pEnumMk);
1329
1330 return S_OK;
1331 }
1332
1333 static HRESULT WINAPI CompositeMonikerMarshalImpl_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv)
1334 {
1335 IMoniker *This = impl_from_IMarshal(iface);
1336
1337 TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppv);
1338
1339 return CompositeMonikerImpl_QueryInterface(This, riid, ppv);
1340 }
1341
1342 static ULONG WINAPI CompositeMonikerMarshalImpl_AddRef(IMarshal *iface)
1343 {
1344 IMoniker *This = impl_from_IMarshal(iface);
1345
1346 TRACE("(%p)\n",iface);
1347
1348 return CompositeMonikerImpl_AddRef(This);
1349 }
1350
1351 static ULONG WINAPI CompositeMonikerMarshalImpl_Release(IMarshal *iface)
1352 {
1353 IMoniker *This = impl_from_IMarshal(iface);
1354
1355 TRACE("(%p)\n",iface);
1356
1357 return CompositeMonikerImpl_Release(This);
1358 }
1359
1360 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetUnmarshalClass(
1361 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1362 void* pvDestContext, DWORD mshlflags, CLSID* pCid)
1363 {
1364 IMoniker *This = impl_from_IMarshal(iface);
1365
1366 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
1367 dwDestContext, pvDestContext, mshlflags, pCid);
1368
1369 return IMoniker_GetClassID(This, pCid);
1370 }
1371
1372 static HRESULT WINAPI CompositeMonikerMarshalImpl_GetMarshalSizeMax(
1373 LPMARSHAL iface, REFIID riid, void* pv, DWORD dwDestContext,
1374 void* pvDestContext, DWORD mshlflags, DWORD* pSize)
1375 {
1376 IMoniker *This = impl_from_IMarshal(iface);
1377 IEnumMoniker *pEnumMk;
1378 IMoniker *pmk;
1379 HRESULT hr;
1380 ULARGE_INTEGER size;
1381
1382 TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
1383 dwDestContext, pvDestContext, mshlflags, pSize);
1384
1385 *pSize = 0x10; /* to match native */
1386
1387 hr = IMoniker_Enum(This, TRUE, &pEnumMk);
1388 if (FAILED(hr)) return hr;
1389
1390 hr = IMoniker_GetSizeMax(This, &size);
1391
1392 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1393 {
1394 ULONG size;
1395
1396 hr = CoGetMarshalSizeMax(&size, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags);
1397 if (SUCCEEDED(hr))
1398 *pSize += size;
1399
1400 IMoniker_Release(pmk);
1401
1402 if (FAILED(hr))
1403 {
1404 IEnumMoniker_Release(pEnumMk);
1405 return hr;
1406 }
1407 }
1408
1409 IEnumMoniker_Release(pEnumMk);
1410
1411 return S_OK;
1412 }
1413
1414 static HRESULT WINAPI CompositeMonikerMarshalImpl_MarshalInterface(LPMARSHAL iface, IStream *pStm,
1415 REFIID riid, void* pv, DWORD dwDestContext,
1416 void* pvDestContext, DWORD mshlflags)
1417 {
1418 IMoniker *This = impl_from_IMarshal(iface);
1419 IEnumMoniker *pEnumMk;
1420 IMoniker *pmk;
1421 HRESULT hr;
1422 ULONG i = 0;
1423
1424 TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv,
1425 dwDestContext, pvDestContext, mshlflags);
1426
1427 hr = IMoniker_Enum(This, TRUE, &pEnumMk);
1428 if (FAILED(hr)) return hr;
1429
1430 while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
1431 {
1432 hr = CoMarshalInterface(pStm, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags);
1433
1434 IMoniker_Release(pmk);
1435
1436 if (FAILED(hr))
1437 {
1438 IEnumMoniker_Release(pEnumMk);
1439 return hr;
1440 }
1441 i++;
1442 }
1443
1444 if (i != 2)
1445 FIXME("moniker count of %d not supported\n", i);
1446
1447 IEnumMoniker_Release(pEnumMk);
1448
1449 return S_OK;
1450 }
1451
1452 static HRESULT WINAPI CompositeMonikerMarshalImpl_UnmarshalInterface(LPMARSHAL iface, IStream *pStm, REFIID riid, void **ppv)
1453 {
1454 CompositeMonikerImpl *This = (CompositeMonikerImpl *)impl_from_IMarshal(iface);
1455 HRESULT hr;
1456
1457 TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
1458
1459 CompositeMonikerImpl_ReleaseMonikersInTable(This);
1460
1461 /* resize the table if needed */
1462 if (This->tabLastIndex + 2 > This->tabSize)
1463 {
1464 This->tabSize += max(BLOCK_TAB_SIZE, 2);
1465 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1466
1467 if (This->tabMoniker==NULL)
1468 return E_OUTOFMEMORY;
1469 }
1470
1471 hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]);
1472 if (FAILED(hr))
1473 {
1474 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr);
1475 return hr;
1476 }
1477 This->tabLastIndex++;
1478 hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]);
1479 if (FAILED(hr))
1480 {
1481 ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr);
1482 return hr;
1483 }
1484 This->tabLastIndex++;
1485
1486 return IMoniker_QueryInterface((IMoniker *)&This->lpvtbl1, riid, ppv);
1487 }
1488
1489 static HRESULT WINAPI CompositeMonikerMarshalImpl_ReleaseMarshalData(LPMARSHAL iface, IStream *pStm)
1490 {
1491 TRACE("(%p)\n", pStm);
1492 /* can't release a state-based marshal as nothing on server side to
1493 * release */
1494 return S_OK;
1495 }
1496
1497 static HRESULT WINAPI CompositeMonikerMarshalImpl_DisconnectObject(LPMARSHAL iface, DWORD dwReserved)
1498 {
1499 TRACE("(0x%x)\n", dwReserved);
1500 /* can't disconnect a state-based marshal as nothing on server side to
1501 * disconnect from */
1502 return S_OK;
1503 }
1504
1505 /******************************************************************************
1506 * EnumMonikerImpl_QueryInterface
1507 ******************************************************************************/
1508 static HRESULT WINAPI
1509 EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1510 {
1511 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1512
1513 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1514
1515 /* Perform a sanity check on the parameters.*/
1516 if ( (This==0) || (ppvObject==0) )
1517 return E_INVALIDARG;
1518
1519 /* Initialize the return parameter */
1520 *ppvObject = 0;
1521
1522 /* Compare the riid with the interface IDs implemented by this object.*/
1523 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1524 *ppvObject = iface;
1525
1526 /* Check that we obtained an interface.*/
1527 if ((*ppvObject)==0)
1528 return E_NOINTERFACE;
1529
1530 /* Query Interface always increases the reference count by one when it is successful */
1531 IEnumMoniker_AddRef(iface);
1532
1533 return S_OK;
1534 }
1535
1536 /******************************************************************************
1537 * EnumMonikerImpl_AddRef
1538 ******************************************************************************/
1539 static ULONG WINAPI
1540 EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1541 {
1542 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1543
1544 TRACE("(%p)\n",This);
1545
1546 return InterlockedIncrement(&This->ref);
1547
1548 }
1549
1550 /******************************************************************************
1551 * EnumMonikerImpl_Release
1552 ******************************************************************************/
1553 static ULONG WINAPI
1554 EnumMonikerImpl_Release(IEnumMoniker* iface)
1555 {
1556 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1557 ULONG i;
1558 ULONG ref;
1559 TRACE("(%p)\n",This);
1560
1561 ref = InterlockedDecrement(&This->ref);
1562
1563 /* destroy the object if there's no more reference on it */
1564 if (ref == 0) {
1565
1566 for(i=0;i<This->tabSize;i++)
1567 IMoniker_Release(This->tabMoniker[i]);
1568
1569 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1570 HeapFree(GetProcessHeap(),0,This);
1571 }
1572 return ref;
1573 }
1574
1575 /******************************************************************************
1576 * EnumMonikerImpl_Next
1577 ******************************************************************************/
1578 static HRESULT WINAPI
1579 EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt,
1580 ULONG* pceltFethed)
1581 {
1582 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1583 ULONG i;
1584
1585 /* retrieve the requested number of moniker from the current position */
1586 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1587 {
1588 rgelt[i]=This->tabMoniker[This->currentPos++];
1589 IMoniker_AddRef(rgelt[i]);
1590 }
1591
1592 if (pceltFethed!=NULL)
1593 *pceltFethed= i;
1594
1595 if (i==celt)
1596 return S_OK;
1597 else
1598 return S_FALSE;
1599 }
1600
1601 /******************************************************************************
1602 * EnumMonikerImpl_Skip
1603 ******************************************************************************/
1604 static HRESULT WINAPI
1605 EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt)
1606 {
1607 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1608
1609 if ((This->currentPos+celt) >= This->tabSize)
1610 return S_FALSE;
1611
1612 This->currentPos+=celt;
1613
1614 return S_OK;
1615 }
1616
1617 /******************************************************************************
1618 * EnumMonikerImpl_Reset
1619 ******************************************************************************/
1620 static HRESULT WINAPI
1621 EnumMonikerImpl_Reset(IEnumMoniker* iface)
1622 {
1623
1624 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1625
1626 This->currentPos=0;
1627
1628 return S_OK;
1629 }
1630
1631 /******************************************************************************
1632 * EnumMonikerImpl_Clone
1633 ******************************************************************************/
1634 static HRESULT WINAPI
1635 EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum)
1636 {
1637 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1638
1639 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1640 }
1641
1642 /********************************************************************************/
1643 /* Virtual function table for the IROTData class */
1644 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
1645 {
1646 EnumMonikerImpl_QueryInterface,
1647 EnumMonikerImpl_AddRef,
1648 EnumMonikerImpl_Release,
1649 EnumMonikerImpl_Next,
1650 EnumMonikerImpl_Skip,
1651 EnumMonikerImpl_Reset,
1652 EnumMonikerImpl_Clone
1653 };
1654
1655 /******************************************************************************
1656 * EnumMonikerImpl_CreateEnumMoniker
1657 ******************************************************************************/
1658 static HRESULT
1659 EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, ULONG tabSize,
1660 ULONG currentPos, BOOL leftToRigth, IEnumMoniker ** ppmk)
1661 {
1662 EnumMonikerImpl* newEnumMoniker;
1663 int i;
1664
1665 if (currentPos > tabSize)
1666 return E_INVALIDARG;
1667
1668 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1669
1670 if (newEnumMoniker == 0)
1671 return STG_E_INSUFFICIENTMEMORY;
1672
1673 /* Initialize the virtual function table. */
1674 newEnumMoniker->lpVtbl = &VT_EnumMonikerImpl;
1675 newEnumMoniker->ref = 1;
1676
1677 newEnumMoniker->tabSize=tabSize;
1678 newEnumMoniker->currentPos=currentPos;
1679
1680 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1681
1682 if (newEnumMoniker->tabMoniker==NULL) {
1683 HeapFree(GetProcessHeap(), 0, newEnumMoniker);
1684 return E_OUTOFMEMORY;
1685 }
1686
1687 if (leftToRigth)
1688 for (i=0;i<tabSize;i++){
1689
1690 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1691 IMoniker_AddRef(tabMoniker[i]);
1692 }
1693 else
1694 for (i=tabSize-1;i>=0;i--){
1695
1696 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1697 IMoniker_AddRef(tabMoniker[i]);
1698 }
1699
1700 *ppmk=(IEnumMoniker*)newEnumMoniker;
1701
1702 return S_OK;
1703 }
1704
1705 /********************************************************************************/
1706 /* Virtual function table for the CompositeMonikerImpl class which includes */
1707 /* IPersist, IPersistStream and IMoniker functions. */
1708
1709 static const IMonikerVtbl VT_CompositeMonikerImpl =
1710 {
1711 CompositeMonikerImpl_QueryInterface,
1712 CompositeMonikerImpl_AddRef,
1713 CompositeMonikerImpl_Release,
1714 CompositeMonikerImpl_GetClassID,
1715 CompositeMonikerImpl_IsDirty,
1716 CompositeMonikerImpl_Load,
1717 CompositeMonikerImpl_Save,
1718 CompositeMonikerImpl_GetSizeMax,
1719 CompositeMonikerImpl_BindToObject,
1720 CompositeMonikerImpl_BindToStorage,
1721 CompositeMonikerImpl_Reduce,
1722 CompositeMonikerImpl_ComposeWith,
1723 CompositeMonikerImpl_Enum,
1724 CompositeMonikerImpl_IsEqual,
1725 CompositeMonikerImpl_Hash,
1726 CompositeMonikerImpl_IsRunning,
1727 CompositeMonikerImpl_GetTimeOfLastChange,
1728 CompositeMonikerImpl_Inverse,
1729 CompositeMonikerImpl_CommonPrefixWith,
1730 CompositeMonikerImpl_RelativePathTo,
1731 CompositeMonikerImpl_GetDisplayName,
1732 CompositeMonikerImpl_ParseDisplayName,
1733 CompositeMonikerImpl_IsSystemMoniker
1734 };
1735
1736 /********************************************************************************/
1737 /* Virtual function table for the IROTData class. */
1738 static const IROTDataVtbl VT_ROTDataImpl =
1739 {
1740 CompositeMonikerROTDataImpl_QueryInterface,
1741 CompositeMonikerROTDataImpl_AddRef,
1742 CompositeMonikerROTDataImpl_Release,
1743 CompositeMonikerROTDataImpl_GetComparisonData
1744 };
1745
1746 static const IMarshalVtbl VT_MarshalImpl =
1747 {
1748 CompositeMonikerMarshalImpl_QueryInterface,
1749 CompositeMonikerMarshalImpl_AddRef,
1750 CompositeMonikerMarshalImpl_Release,
1751 CompositeMonikerMarshalImpl_GetUnmarshalClass,
1752 CompositeMonikerMarshalImpl_GetMarshalSizeMax,
1753 CompositeMonikerMarshalImpl_MarshalInterface,
1754 CompositeMonikerMarshalImpl_UnmarshalInterface,
1755 CompositeMonikerMarshalImpl_ReleaseMarshalData,
1756 CompositeMonikerMarshalImpl_DisconnectObject
1757 };
1758
1759 /******************************************************************************
1760 * Composite-Moniker_Construct (local function)
1761 *******************************************************************************/
1762 static HRESULT
1763 CompositeMonikerImpl_Construct(IMoniker** ppMoniker,
1764 LPMONIKER pmkFirst, LPMONIKER pmkRest)
1765 {
1766 DWORD mkSys;
1767 IEnumMoniker *enumMoniker;
1768 IMoniker *tempMk;
1769 HRESULT res;
1770 CompositeMonikerImpl *This;
1771
1772 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1773
1774 if (!This)
1775 return E_OUTOFMEMORY;
1776
1777 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
1778
1779 /* Initialize the virtual function table. */
1780 This->lpvtbl1 = &VT_CompositeMonikerImpl;
1781 This->lpvtbl2 = &VT_ROTDataImpl;
1782 This->lpvtblMarshal= &VT_MarshalImpl;
1783 This->ref = 1;
1784
1785 This->tabSize=BLOCK_TAB_SIZE;
1786 This->tabLastIndex=0;
1787
1788 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
1789 if (This->tabMoniker==NULL) {
1790 HeapFree(GetProcessHeap(), 0, This);
1791 return E_OUTOFMEMORY;
1792 }
1793
1794 if (!pmkFirst && !pmkRest)
1795 {
1796 *ppMoniker = (IMoniker *)This;
1797 return S_OK;
1798 }
1799
1800 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
1801
1802 /* put the first moniker contents in the beginning of the table */
1803 if (mkSys!=MKSYS_GENERICCOMPOSITE){
1804
1805 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
1806 IMoniker_AddRef(pmkFirst);
1807 }
1808 else{
1809
1810 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
1811
1812 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
1813
1814
1815 if (++This->tabLastIndex==This->tabSize){
1816 LPVOID tab_moniker = This->tabMoniker;
1817
1818 This->tabSize+=BLOCK_TAB_SIZE;
1819 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1820
1821 if (This->tabMoniker==NULL){
1822 HeapFree(GetProcessHeap(), 0, tab_moniker);
1823 HeapFree(GetProcessHeap(), 0, This);
1824 return E_OUTOFMEMORY;
1825 }
1826 }
1827 }
1828
1829 IEnumMoniker_Release(enumMoniker);
1830 }
1831
1832 /* put the rest moniker contents after the first one and make simplification if needed */
1833
1834 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
1835
1836 if (mkSys!=MKSYS_GENERICCOMPOSITE){
1837
1838 /* add a simple moniker to the moniker table */
1839
1840 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
1841
1842 if (res==MK_E_NEEDGENERIC){
1843
1844 /* there's no simplification in this case */
1845 This->tabMoniker[This->tabLastIndex]=pmkRest;
1846
1847 This->tabLastIndex++;
1848
1849 IMoniker_AddRef(pmkRest);
1850 }
1851 else if (tempMk==NULL){
1852
1853 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1854 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1855
1856 This->tabLastIndex--;
1857 }
1858 else if (SUCCEEDED(res)){
1859
1860 /* the non-generic composition was successful so we can make a simplification in this case */
1861 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1862
1863 This->tabMoniker[This->tabLastIndex-1]=tempMk;
1864 } else
1865 return res;
1866
1867 /* resize tabMoniker if needed */
1868 if (This->tabLastIndex==This->tabSize){
1869 LPVOID tab_moniker = This->tabMoniker;
1870
1871 This->tabSize+=BLOCK_TAB_SIZE;
1872
1873 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1874
1875 if (This->tabMoniker==NULL){
1876 HeapFree(GetProcessHeap(), 0, tab_moniker);
1877 HeapFree(GetProcessHeap(), 0, This);
1878 return E_OUTOFMEMORY;
1879 }
1880 }
1881 }
1882 else{
1883
1884 /* add a composite moniker to the moniker table (do the same thing
1885 * for each moniker within the composite moniker as a simple moniker
1886 * (see above for how to add a simple moniker case) )
1887 */
1888 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
1889
1890 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
1891
1892 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
1893
1894 if (res==MK_E_NEEDGENERIC){
1895
1896 This->tabLastIndex++;
1897 }
1898 else if (tempMk==NULL){
1899
1900 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1901 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
1902 This->tabLastIndex--;
1903 }
1904 else{
1905
1906 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1907
1908 This->tabMoniker[This->tabLastIndex-1]=tempMk;
1909 }
1910
1911 if (This->tabLastIndex==This->tabSize){
1912 LPVOID tab_moniker = This->tabMoniker;
1913
1914 This->tabSize+=BLOCK_TAB_SIZE;
1915
1916 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1917
1918 if (This->tabMoniker==NULL){
1919 HeapFree(GetProcessHeap(), 0, tab_moniker);
1920 HeapFree(GetProcessHeap(), 0, This);
1921 return E_OUTOFMEMORY;
1922 }
1923 }
1924 }
1925
1926 IEnumMoniker_Release(enumMoniker);
1927 }
1928
1929 /* only one moniker, then just return it */
1930 if (This->tabLastIndex == 1)
1931 {
1932 *ppMoniker = This->tabMoniker[0];
1933 IMoniker_AddRef(*ppMoniker);
1934 IMoniker_Release((IMoniker *)This);
1935 }
1936 else
1937 *ppMoniker = (IMoniker *)This;
1938
1939 return S_OK;
1940 }
1941
1942 /******************************************************************************
1943 * CreateGenericComposite [OLE32.@]
1944 ******************************************************************************/
1945 HRESULT WINAPI
1946 CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest,
1947 LPMONIKER* ppmkComposite)
1948 {
1949 IMoniker* moniker = 0;
1950 HRESULT hr = S_OK;
1951
1952 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1953
1954 if (ppmkComposite==NULL)
1955 return E_POINTER;
1956
1957 *ppmkComposite=0;
1958
1959 if (pmkFirst==NULL && pmkRest!=NULL){
1960
1961 *ppmkComposite=pmkRest;
1962 return S_OK;
1963 }
1964 else if (pmkFirst!=NULL && pmkRest==NULL){
1965 *ppmkComposite=pmkFirst;
1966 return S_OK;
1967 }
1968 else if (pmkFirst==NULL && pmkRest==NULL)
1969 return S_OK;
1970
1971 hr = CompositeMonikerImpl_Construct(&moniker,pmkFirst,pmkRest);
1972
1973 if (FAILED(hr))
1974 return hr;
1975
1976 hr = IMoniker_QueryInterface(moniker,&IID_IMoniker,(void**)ppmkComposite);
1977 IMoniker_Release(moniker);
1978
1979 return hr;
1980 }
1981
1982 /******************************************************************************
1983 * MonikerCommonPrefixWith [OLE32.@]
1984 ******************************************************************************/
1985 HRESULT WINAPI
1986 MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1987 {
1988 FIXME("(),stub!\n");
1989 return E_NOTIMPL;
1990 }
1991
1992 static HRESULT WINAPI CompositeMonikerCF_QueryInterface(LPCLASSFACTORY iface,
1993 REFIID riid, LPVOID *ppv)
1994 {
1995 *ppv = NULL;
1996 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
1997 {
1998 *ppv = iface;
1999 IUnknown_AddRef(iface);
2000 return S_OK;
2001 }
2002 return E_NOINTERFACE;
2003 }
2004
2005 static ULONG WINAPI CompositeMonikerCF_AddRef(LPCLASSFACTORY iface)
2006 {
2007 return 2; /* non-heap based object */
2008 }
2009
2010 static ULONG WINAPI CompositeMonikerCF_Release(LPCLASSFACTORY iface)
2011 {
2012 return 1; /* non-heap based object */
2013 }
2014
2015 static HRESULT WINAPI CompositeMonikerCF_CreateInstance(LPCLASSFACTORY iface,
2016 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
2017 {
2018 IMoniker* pMoniker;
2019 HRESULT hr;
2020
2021 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
2022
2023 *ppv = NULL;
2024
2025 if (pUnk)
2026 return CLASS_E_NOAGGREGATION;
2027
2028 hr = CompositeMonikerImpl_Construct(&pMoniker, NULL, NULL);
2029
2030 if (SUCCEEDED(hr))
2031 {
2032 hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
2033 IMoniker_Release(pMoniker);
2034 }
2035
2036 return hr;
2037 }
2038
2039 static HRESULT WINAPI CompositeMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
2040 {
2041 FIXME("(%d), stub!\n",fLock);
2042 return S_OK;
2043 }
2044
2045 static const IClassFactoryVtbl CompositeMonikerCFVtbl =
2046 {
2047 CompositeMonikerCF_QueryInterface,
2048 CompositeMonikerCF_AddRef,
2049 CompositeMonikerCF_Release,
2050 CompositeMonikerCF_CreateInstance,
2051 CompositeMonikerCF_LockServer
2052 };
2053 static const IClassFactoryVtbl *CompositeMonikerCF = &CompositeMonikerCFVtbl;
2054
2055 HRESULT CompositeMonikerCF_Create(REFIID riid, LPVOID *ppv)
2056 {
2057 return IClassFactory_QueryInterface((IClassFactory *)&CompositeMonikerCF, riid, ppv);
2058 }
2059
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.