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