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