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