source: trunk/src/ole32/compositemoniker.c@ 6823

Last change on this file since 6823 was 6711, checked in by sandervl, 24 years ago

restored old version + wine update

File size: 58.2 KB
Line 
1/***************************************************************************************
2 * CompositeMonikers implementation
3 *
4 * Copyright 1999 Noomen Hamza
5 ***************************************************************************************/
6#include <assert.h>
7#include <string.h>
8#include "winbase.h"
9#include "winerror.h"
10#include "debugtools.h"
11#include "wine/obj_base.h"
12#include "wine/obj_misc.h"
13#include "wine/obj_storage.h"
14#include "wine/obj_moniker.h"
15#include "wine/obj_inplace.h"
16#include "wine/unicode.h"
17#include "ole2.h"
18
19#ifdef __WIN32OS2__
20#undef FIXME
21#undef TRACE
22#ifdef DEBUG
23#define TRACE WriteLog("OLE32: %s", __FUNCTION__); WriteLog
24#define FIXME WriteLog("FIXME OLE32: %s", __FUNCTION__); WriteLog
25#else
26#define TRACE 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
27#define FIXME 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
28#endif
29#endif
30
31DEFAULT_DEBUG_CHANNEL(ole);
32
33#define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
34
35/* CompositeMoniker data structure */
36typedef struct CompositeMonikerImpl{
37
38 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
39
40 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
41 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
42 */
43 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
44
45 ULONG ref; /* reference counter for this object */
46
47 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
48
49 ULONG tabSize; /* size of tabMoniker */
50
51 ULONG tabLastIndex; /* first free index in tabMoniker */
52
53} CompositeMonikerImpl;
54
55
56/* EnumMoniker data structure */
57typedef struct EnumMonikerImpl{
58
59 ICOM_VFIELD(IEnumMoniker); /* VTable relative to the IEnumMoniker interface.*/
60
61 ULONG ref; /* reference counter for this object */
62
63 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
64
65 ULONG tabSize; /* size of tabMoniker */
66
67 ULONG currentPos; /* index pointer on the current moniker */
68
69} EnumMonikerImpl;
70
71
72/********************************************************************************/
73/* CompositeMoniker prototype functions : */
74
75/* IUnknown prototype functions */
76static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
77static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
78static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
79
80/* IPersist prototype functions */
81static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
82
83/* IPersistStream prototype functions */
84static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
85static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
86static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
87static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
88
89/* IMoniker prototype functions */
90static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
91static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
92static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
93static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
94static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
95static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
96static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
97static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
98static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
99static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
100static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
101static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
102static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
103static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
104static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
105
106/********************************************************************************/
107/* IROTData prototype functions */
108
109/* IUnknown prototype functions */
110static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
111static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
112static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
113
114/* IROTData prototype function */
115static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
116
117/* Local function used by CompositeMoniker implementation */
118HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
119HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
120
121/********************************************************************************/
122/* IEnumMoniker prototype functions */
123
124/* IUnknown prototype functions */
125static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
126static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
127static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
128
129/* IEnumMoniker prototype functions */
130static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
131static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
132static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
133static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
134
135HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
136
137/********************************************************************************/
138/* Virtual function table for the CompositeMonikerImpl class which includes */
139/* IPersist, IPersistStream and IMoniker functions. */
140
141static ICOM_VTABLE(IMoniker) VT_CompositeMonikerImpl =
142{
143 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
144 CompositeMonikerImpl_QueryInterface,
145 CompositeMonikerImpl_AddRef,
146 CompositeMonikerImpl_Release,
147 CompositeMonikerImpl_GetClassID,
148 CompositeMonikerImpl_IsDirty,
149 CompositeMonikerImpl_Load,
150 CompositeMonikerImpl_Save,
151 CompositeMonikerImpl_GetSizeMax,
152 CompositeMonikerImpl_BindToObject,
153 CompositeMonikerImpl_BindToStorage,
154 CompositeMonikerImpl_Reduce,
155 CompositeMonikerImpl_ComposeWith,
156 CompositeMonikerImpl_Enum,
157 CompositeMonikerImpl_IsEqual,
158 CompositeMonikerImpl_Hash,
159 CompositeMonikerImpl_IsRunning,
160 CompositeMonikerImpl_GetTimeOfLastChange,
161 CompositeMonikerImpl_Inverse,
162 CompositeMonikerImpl_CommonPrefixWith,
163 CompositeMonikerImpl_RelativePathTo,
164 CompositeMonikerImpl_GetDisplayName,
165 CompositeMonikerImpl_ParseDisplayName,
166 CompositeMonikerImpl_IsSystemMoniker
167};
168
169/********************************************************************************/
170/* Virtual function table for the IROTData class. */
171static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
172{
173 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
174 CompositeMonikerROTDataImpl_QueryInterface,
175 CompositeMonikerROTDataImpl_AddRef,
176 CompositeMonikerROTDataImpl_Release,
177 CompositeMonikerROTDataImpl_GetComparaisonData
178};
179
180/********************************************************************************/
181/* Virtual function table for the IROTData class */
182static ICOM_VTABLE(IEnumMoniker) VT_EnumMonikerImpl =
183{
184 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
185 EnumMonikerImpl_QueryInterface,
186 EnumMonikerImpl_AddRef,
187 EnumMonikerImpl_Release,
188 EnumMonikerImpl_Next,
189 EnumMonikerImpl_Skip,
190 EnumMonikerImpl_Reset,
191 EnumMonikerImpl_Clone
192};
193
194/*******************************************************************************
195 * CompositeMoniker_QueryInterface
196 *******************************************************************************/
197HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
198{
199 ICOM_THIS(CompositeMonikerImpl,iface);
200
201 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
202
203 /* Perform a sanity check on the parameters.*/
204 if ( (This==0) || (ppvObject==0) )
205 return E_INVALIDARG;
206
207 /* Initialize the return parameter */
208 *ppvObject = 0;
209
210 /* Compare the riid with the interface IDs implemented by this object.*/
211 if (IsEqualIID(&IID_IUnknown, riid) ||
212 IsEqualIID(&IID_IPersist, riid) ||
213 IsEqualIID(&IID_IPersistStream, riid) ||
214 IsEqualIID(&IID_IMoniker, riid)
215 )
216 *ppvObject = iface;
217 else if (IsEqualIID(&IID_IROTData, riid))
218 *ppvObject = (IROTData*)&(This->lpvtbl2);
219
220 /* Check that we obtained an interface.*/
221 if ((*ppvObject)==0)
222 return E_NOINTERFACE;
223
224 /* Query Interface always increases the reference count by one when it is successful */
225 CompositeMonikerImpl_AddRef(iface);
226
227 return S_OK;
228}
229
230/******************************************************************************
231 * CompositeMoniker_AddRef
232 ******************************************************************************/
233ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
234{
235 ICOM_THIS(CompositeMonikerImpl,iface);
236
237 TRACE("(%p)\n",This);
238
239 return ++(This->ref);
240}
241
242/******************************************************************************
243 * CompositeMoniker_Release
244 ******************************************************************************/
245ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
246{
247 ICOM_THIS(CompositeMonikerImpl,iface);
248 ULONG i;
249
250 TRACE("(%p)\n",This);
251
252 This->ref--;
253
254 /* destroy the object if there's no more reference on it */
255 if (This->ref==0){
256
257 /* release all the components before destroying this object */
258 for (i=0;i<This->tabLastIndex;i++)
259 IMoniker_Release(This->tabMoniker[i]);
260
261 CompositeMonikerImpl_Destroy(This);
262
263 return 0;
264 }
265 return This->ref;;
266}
267
268/******************************************************************************
269 * CompositeMoniker_GetClassID
270 ******************************************************************************/
271HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
272{
273 TRACE("(%p,%p),stub!\n",iface,pClassID);
274
275 if (pClassID==NULL)
276 return E_POINTER;
277
278 *pClassID = CLSID_CompositeMoniker;
279
280 return S_OK;
281}
282
283/******************************************************************************
284 * CompositeMoniker_IsDirty
285 ******************************************************************************/
286HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
287{
288 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
289 method in the OLE-provided moniker interfaces always return S_FALSE because
290 their internal state never changes. */
291
292 TRACE("(%p)\n",iface);
293
294 return S_FALSE;
295}
296
297/******************************************************************************
298 * CompositeMoniker_Load
299 ******************************************************************************/
300HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
301{
302 HRESULT res;
303 DWORD constant;
304 CLSID clsid;
305 WCHAR string[1]={0};
306
307 ICOM_THIS(CompositeMonikerImpl,iface);
308
309 TRACE("(%p,%p)\n",iface,pStm);
310
311 /* this function call OleLoadFromStream function for each moniker within this object */
312
313 /* read the a constant writen by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
314 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
315
316 if (SUCCEEDED(res)&& constant!=3)
317 return E_FAIL;
318
319 while(1){
320#if 0
321 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
322#endif
323 res=ReadClassStm(pStm,&clsid);
324 DPRINTF("res=%ld",res);
325 if (FAILED(res))
326 break;
327
328 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
329 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
330 if (FAILED(res))
331 break;
332 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
333 if (FAILED(res))
334 break;
335 }
336 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
337 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
338 if (res!=S_OK)
339 break;
340 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
341 if (FAILED(res))
342 break;
343 }
344 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
345 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
346 if (FAILED(res))
347 break;
348 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
349 if (FAILED(res))
350 break;
351 }
352 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
353 return E_FAIL;
354
355 else{
356 FIXME("()");
357 break;
358 return E_NOTIMPL;
359 }
360
361 /* resize the table if needed */
362 if (++This->tabLastIndex==This->tabSize){
363
364 This->tabSize+=BLOCK_TAB_SIZE;
365 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
366
367 if (This->tabMoniker==NULL)
368 return E_OUTOFMEMORY;
369 }
370 }
371
372 return res;
373}
374
375/******************************************************************************
376 * CompositeMoniker_Save
377 ******************************************************************************/
378HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
379{
380 HRESULT res;
381 IEnumMoniker *enumMk;
382 IMoniker *pmk;
383 DWORD constant=3;
384
385 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
386
387 /* this function call OleSaveToStream function for each moniker within this object */
388
389 /* when I tested this function in windows system ! I usually found this constant in the begining of */
390 /* the stream I dont known why (there's no indication in specification) ! */
391 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
392
393 IMoniker_Enum(iface,TRUE,&enumMk);
394
395 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
396
397 res=OleSaveToStream((IPersistStream*)pmk,pStm);
398
399 IMoniker_Release(pmk);
400
401 if (FAILED(res)){
402
403 IEnumMoniker_Release(pmk);
404 return res;
405 }
406 }
407
408 IEnumMoniker_Release(enumMk);
409
410 return S_OK;
411}
412
413/******************************************************************************
414 * CompositeMoniker_GetSizeMax
415 ******************************************************************************/
416HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
417{
418 IEnumMoniker *enumMk;
419 IMoniker *pmk;
420 ULARGE_INTEGER ptmpSize;
421
422 /* the sizeMax of this object is calculated by calling GetSizeMax on each moniker within this object then */
423 /* suming all returned sizemax */
424
425 TRACE("(%p,%p)\n",iface,pcbSize);
426
427 if (pcbSize!=NULL)
428 return E_POINTER;
429
430 pcbSize->s.LowPart =0;
431 pcbSize->s.HighPart=0;
432
433 IMoniker_Enum(iface,TRUE,&enumMk);
434
435 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
436
437 IMoniker_GetSizeMax(pmk,&ptmpSize);
438
439 IMoniker_Release(pmk);
440
441 pcbSize->s.LowPart +=ptmpSize.s.LowPart;
442 pcbSize->s.HighPart+=ptmpSize.s.HighPart;
443 }
444
445 IEnumMoniker_Release(enumMk);
446
447 return S_OK;
448}
449
450/******************************************************************************
451 * Composite-Moniker_Construct (local function)
452 *******************************************************************************/
453HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
454{
455 DWORD mkSys;
456 IEnumMoniker *enumMoniker;
457 IMoniker *tempMk;
458 HRESULT res;
459
460 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
461
462 /* Initialize the virtual fgunction table. */
463 This->lpvtbl1 = &VT_CompositeMonikerImpl;
464 This->lpvtbl2 = &VT_ROTDataImpl;
465 This->ref = 0;
466
467 This->tabSize=BLOCK_TAB_SIZE;
468 This->tabLastIndex=0;
469
470 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
471 if (This->tabMoniker==NULL)
472 return E_OUTOFMEMORY;
473
474 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
475
476 /* put the first moniker contents in the begining of the table */
477 if (mkSys!=MKSYS_GENERICCOMPOSITE){
478
479 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
480 IMoniker_AddRef(pmkFirst);
481 }
482 else{
483
484 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
485
486 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
487
488
489 if (++This->tabLastIndex==This->tabSize){
490
491 This->tabSize+=BLOCK_TAB_SIZE;
492 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
493
494 if (This->tabMoniker==NULL)
495 return E_OUTOFMEMORY;
496 }
497 }
498
499 IEnumMoniker_Release(enumMoniker);
500 }
501
502 /* put the rest moniker contents after the first one and make simplification if needed */
503
504 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
505
506 if (mkSys!=MKSYS_GENERICCOMPOSITE){
507
508 /* add a simple moniker to the moniker table */
509
510 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
511
512 if (res==MK_E_NEEDGENERIC){
513
514 /* there's no simplification in this case */
515 This->tabMoniker[This->tabLastIndex]=pmkRest;
516
517 This->tabLastIndex++;
518
519 IMoniker_AddRef(pmkRest);
520 }
521 else if (tempMk==NULL){
522
523 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
524 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
525
526 This->tabLastIndex--;
527 }
528 else if (SUCCEEDED(res)){
529
530 /* the non-generic composition was successful so we can make a simplification in this case */
531 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
532
533 This->tabMoniker[This->tabLastIndex-1]=tempMk;
534 } else
535 return res;
536
537 /* resize tabMoniker if needed */
538 if (This->tabLastIndex==This->tabSize){
539
540 This->tabSize+=BLOCK_TAB_SIZE;
541
542 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
543
544 if (This->tabMoniker==NULL)
545 return E_OUTOFMEMORY;
546 }
547 }
548 else{
549
550 /* add a composite moniker to the moniker table (do the same thing for each moniker within the */
551 /* composite moniker as a simple moniker (see above how to add a simple moniker case) ) */
552 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
553
554 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
555
556 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
557
558 if (res==MK_E_NEEDGENERIC){
559
560 This->tabLastIndex++;
561 }
562 else if (tempMk==NULL){
563
564 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
565 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
566 This->tabLastIndex--;
567 }
568 else{
569
570 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
571
572 This->tabMoniker[This->tabLastIndex-1]=tempMk;
573 }
574
575 if (This->tabLastIndex==This->tabSize){
576
577 This->tabSize+=BLOCK_TAB_SIZE;
578
579 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
580
581 if (This->tabMoniker==NULL)
582 return E_OUTOFMEMORY;
583 }
584 }
585
586 IEnumMoniker_Release(enumMoniker);
587 }
588
589 return S_OK;
590}
591
592/******************************************************************************
593 * CompositeMoniker_Destroy (local function)
594 *******************************************************************************/
595HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
596{
597 TRACE("(%p)\n",This);
598
599 HeapFree(GetProcessHeap(),0,This->tabMoniker);
600
601 HeapFree(GetProcessHeap(),0,This);
602
603 return S_OK;
604}
605
606/******************************************************************************
607 * CompositeMoniker_BindToObject
608 ******************************************************************************/
609HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
610 IBindCtx* pbc,
611 IMoniker* pmkToLeft,
612 REFIID riid,
613 VOID** ppvResult)
614{
615 HRESULT res;
616 IRunningObjectTable *prot;
617 IMoniker *tempMk,*antiMk,*mostRigthMk;
618 IEnumMoniker *enumMoniker;
619
620 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
621
622 if (ppvResult==NULL)
623 return E_POINTER;
624
625 *ppvResult=0;
626 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
627 /* object for the requested interface pointer. */
628 if(pmkToLeft==NULL){
629
630 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
631
632 if (SUCCEEDED(res)){
633
634 /* if the requested class was loaded befor ! we dont need to reload it */
635 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
636
637 if (res==S_OK)
638 return res;
639 }
640 }
641 else{
642 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
643 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
644
645 IMoniker_Enum(iface,FALSE,&enumMoniker);
646 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
647 IEnumMoniker_Release(enumMoniker);
648
649 res=CreateAntiMoniker(&antiMk);
650 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
651 IMoniker_Release(antiMk);
652
653 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
654
655 IMoniker_Release(tempMk);
656 IMoniker_Release(mostRigthMk);
657 }
658
659 return res;
660}
661
662/******************************************************************************
663 * CompositeMoniker_BindToStorage
664 ******************************************************************************/
665HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
666 IBindCtx* pbc,
667 IMoniker* pmkToLeft,
668 REFIID riid,
669 VOID** ppvResult)
670{
671 HRESULT res;
672 IMoniker *tempMk,*antiMk,*mostRigthMk;
673 IEnumMoniker *enumMoniker;
674
675 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
676
677 *ppvResult=0;
678
679 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
680 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
681
682 if (pmkToLeft!=NULL){
683
684 IMoniker_Enum(iface,FALSE,&enumMoniker);
685 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
686 IEnumMoniker_Release(enumMoniker);
687
688 res=CreateAntiMoniker(&antiMk);
689 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
690 IMoniker_Release(antiMk);
691
692 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
693
694 IMoniker_Release(tempMk);
695
696 IMoniker_Release(mostRigthMk);
697
698 return res;
699 }
700 else
701 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
702}
703
704/******************************************************************************
705 * CompositeMoniker_Reduce
706 ******************************************************************************/
707HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
708 IBindCtx* pbc,
709 DWORD dwReduceHowFar,
710 IMoniker** ppmkToLeft,
711 IMoniker** ppmkReduced)
712{
713 HRESULT res;
714 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
715 IEnumMoniker *enumMoniker;
716
717 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
718
719 if (ppmkReduced==NULL)
720 return E_POINTER;
721
722 /* This method recursively calls Reduce for each of its component monikers. */
723
724 if (ppmkToLeft==NULL){
725
726 IMoniker_Enum(iface,FALSE,&enumMoniker);
727 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
728 IEnumMoniker_Release(enumMoniker);
729
730 res=CreateAntiMoniker(&antiMk);
731 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
732 IMoniker_Release(antiMk);
733
734 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
735 }
736 else if (*ppmkToLeft==NULL)
737
738 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
739
740 else{
741
742 /* separate the composite moniker in to left and right moniker */
743 IMoniker_Enum(iface,FALSE,&enumMoniker);
744 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
745 IEnumMoniker_Release(enumMoniker);
746
747 res=CreateAntiMoniker(&antiMk);
748 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
749 IMoniker_Release(antiMk);
750
751 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
752 /* of the reduced components */
753 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
754 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
755 )
756
757 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
758
759 else{
760 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
761
762 IMoniker_AddRef(iface);
763
764 *ppmkReduced=iface;
765
766 return MK_S_REDUCED_TO_SELF;
767 }
768 }
769}
770
771/******************************************************************************
772 * CompositeMoniker_ComposeWith
773 ******************************************************************************/
774HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
775 IMoniker* pmkRight,
776 BOOL fOnlyIfNotGeneric,
777 IMoniker** ppmkComposite)
778{
779 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
780
781 if ((ppmkComposite==NULL)||(pmkRight==NULL))
782 return E_POINTER;
783
784 *ppmkComposite=0;
785
786 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
787 /* otherwise, the method returns the result of combining the two monikers by calling the */
788 /* CreateGenericComposite function */
789
790 if (fOnlyIfNotGeneric)
791 return MK_E_NEEDGENERIC;
792
793 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
794}
795
796/******************************************************************************
797 * CompositeMoniker_Enum
798 ******************************************************************************/
799HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
800{
801 ICOM_THIS(CompositeMonikerImpl,iface);
802
803 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
804
805 if (ppenumMoniker == NULL)
806 return E_POINTER;
807
808 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
809}
810
811/******************************************************************************
812 * CompositeMoniker_IsEqual
813 ******************************************************************************/
814HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
815{
816 IEnumMoniker *enumMoniker1,*enumMoniker2;
817 IMoniker *tempMk1,*tempMk2;
818 HRESULT res1,res2,res;
819
820 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
821
822 if (pmkOtherMoniker==NULL)
823 return S_FALSE;
824
825 /* This method returns S_OK if the components of both monikers are equal when compared in the */
826 /* left-to-right order.*/
827 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
828
829 if (enumMoniker1==NULL)
830 return S_FALSE;
831
832 IMoniker_Enum(iface,TRUE,&enumMoniker2);
833
834 while(1){
835
836 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
837 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
838
839 if((res1==S_OK)&&(res2==S_OK)){
840
841 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
842 res= S_FALSE;
843 break;
844 }
845 else
846 continue;
847 }
848 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
849 res = S_OK;
850 break;
851 }
852 else{
853 res = S_FALSE;
854 break;
855 }
856
857 if (res1==S_OK)
858 IMoniker_Release(tempMk1);
859
860 if (res2==S_OK)
861 IMoniker_Release(tempMk2);
862 }
863
864 IEnumMoniker_Release(enumMoniker1);
865 IEnumMoniker_Release(enumMoniker2);
866
867 return res;
868}
869/******************************************************************************
870 * CompositeMoniker_Hash
871 ******************************************************************************/
872HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
873{
874 FIXME("(),stub!\n");
875
876 return E_NOTIMPL;
877}
878
879/******************************************************************************
880 * CompositeMoniker_IsRunning
881 ******************************************************************************/
882HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
883 IBindCtx* pbc,
884 IMoniker* pmkToLeft,
885 IMoniker* pmkNewlyRunning)
886{
887 IRunningObjectTable* rot;
888 HRESULT res;
889 IMoniker *tempMk,*antiMk,*mostRigthMk;
890 IEnumMoniker *enumMoniker;
891
892 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
893
894 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
895 if (pmkToLeft!=NULL){
896
897 CreateGenericComposite(pmkToLeft,iface,&tempMk);
898
899 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
900
901 IMoniker_Release(tempMk);
902
903 return res;
904 }
905 else
906 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
907 /* to this moniker */
908
909 if (pmkNewlyRunning!=NULL)
910
911 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
912 return S_OK;
913
914 else
915 return S_FALSE;
916
917 else{
918
919 if (pbc==NULL)
920 return E_POINTER;
921
922 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
923 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
924 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
925 /* the composite as the pmkToLeft parameter for that call. */
926
927 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
928
929 if (FAILED(res))
930 return res;
931
932 res = IRunningObjectTable_IsRunning(rot,iface);
933 IRunningObjectTable_Release(rot);
934
935 if(res==S_OK)
936 return S_OK;
937
938 else{
939
940 IMoniker_Enum(iface,FALSE,&enumMoniker);
941 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
942 IEnumMoniker_Release(enumMoniker);
943
944 res=CreateAntiMoniker(&antiMk);
945 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
946 IMoniker_Release(antiMk);
947
948 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
949
950 IMoniker_Release(tempMk);
951 IMoniker_Release(mostRigthMk);
952
953 return res;
954 }
955 }
956}
957
958/******************************************************************************
959 * CompositeMoniker_GetTimeOfLastChange
960 ******************************************************************************/
961HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
962 IBindCtx* pbc,
963 IMoniker* pmkToLeft,
964 FILETIME* pCompositeTime)
965{
966 IRunningObjectTable* rot;
967 HRESULT res;
968 IMoniker *tempMk,*antiMk,*mostRigthMk;
969 IEnumMoniker *enumMoniker;
970
971 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
972
973 if (pCompositeTime==NULL)
974 return E_INVALIDARG;
975
976 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
977 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
978 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
979 /* of the composite as the pmkToLeft parameter for that call. */
980 if (pmkToLeft!=NULL){
981
982 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
983
984 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
985
986 if (FAILED(res))
987 return res;
988
989 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
990 return res;
991 else
992
993 IMoniker_Enum(iface,FALSE,&enumMoniker);
994 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
995 IEnumMoniker_Release(enumMoniker);
996
997 res=CreateAntiMoniker(&antiMk);
998 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
999 IMoniker_Release(antiMk);
1000
1001 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
1002
1003 IMoniker_Release(tempMk);
1004 IMoniker_Release(mostRigthMk);
1005
1006 return res;
1007 }
1008 else
1009 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
1010}
1011
1012/******************************************************************************
1013 * CompositeMoniker_Inverse
1014 ******************************************************************************/
1015HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1016{
1017 HRESULT res;
1018 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1019 IEnumMoniker *enumMoniker;
1020
1021 TRACE("(%p,%p)\n",iface,ppmk);
1022
1023 if (ppmk==NULL)
1024 return E_POINTER;
1025
1026 /* This method returns a composite moniker that consists of the inverses of each of the components */
1027 /* of the original composite, stored in reverse order */
1028
1029 res=CreateAntiMoniker(&antiMk);
1030 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1031 IMoniker_Release(antiMk);
1032
1033 if (tempMk==NULL)
1034
1035 return IMoniker_Inverse(iface,ppmk);
1036
1037 else{
1038
1039 IMoniker_Enum(iface,FALSE,&enumMoniker);
1040 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1041 IEnumMoniker_Release(enumMoniker);
1042
1043 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1044 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1045
1046 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1047
1048 IMoniker_Release(tempMk);
1049 IMoniker_Release(mostRigthMk);
1050 IMoniker_Release(tempInvMk);
1051 IMoniker_Release(mostRigthInvMk);
1052
1053 return res;
1054 }
1055}
1056
1057/******************************************************************************
1058 * CompositeMoniker_CommonPrefixWith
1059 ******************************************************************************/
1060HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1061{
1062 DWORD mkSys;
1063 HRESULT res1,res2;
1064 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1065 IEnumMoniker *enumMoniker1,*enumMoniker2;
1066 ULONG i,nbCommonMk=0;
1067
1068 /* If the other moniker is a composite, this method compares the components of each composite from left */
1069 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1070 /* of the leftmost components were common to both monikers. */
1071
1072 if (ppmkPrefix==NULL)
1073 return E_POINTER;
1074
1075 *ppmkPrefix=0;
1076
1077 if (pmkOther==NULL)
1078 return MK_E_NOPREFIX;
1079
1080 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1081
1082 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1083
1084 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1085 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1086
1087 while(1){
1088
1089 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1090 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1091
1092 if ((res1==S_FALSE) && (res2==S_FALSE)){
1093
1094 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1095 *ppmkPrefix=iface;
1096 IMoniker_AddRef(iface);
1097 return MK_S_US;
1098 }
1099 else if ((res1==S_OK) && (res2==S_OK)){
1100
1101 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1102
1103 nbCommonMk++;
1104
1105 else
1106 break;
1107
1108 }
1109 else if (res1==S_OK){
1110
1111 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1112 /* ppmkPrefix to the other moniker. */
1113 *ppmkPrefix=pmkOther;
1114 return MK_S_HIM;
1115 }
1116 else{
1117 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1118 /* to this moniker. */
1119 *ppmkPrefix=iface;
1120 return MK_S_ME;
1121 }
1122 }
1123
1124 IEnumMoniker_Release(enumMoniker1);
1125 IEnumMoniker_Release(enumMoniker2);
1126
1127 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1128 if (nbCommonMk==0)
1129 return MK_E_NOPREFIX;
1130
1131 IEnumMoniker_Reset(enumMoniker1);
1132
1133 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1134
1135 /* if we have more than one commun moniker the result will be a composite moniker */
1136 if (nbCommonMk>1){
1137
1138 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1139 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1140 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1141 IMoniker_Release(tempMk1);
1142 IMoniker_Release(tempMk2);
1143
1144 /* compose all common monikers in a composite moniker */
1145 for(i=0;i<nbCommonMk;i++){
1146
1147 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1148
1149 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1150
1151 IMoniker_Release(*ppmkPrefix);
1152
1153 IMoniker_Release(tempMk1);
1154
1155 *ppmkPrefix=tempMk2;
1156 }
1157 return S_OK;
1158 }
1159 else{
1160 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1161 *ppmkPrefix=tempMk1;
1162
1163 return S_OK;
1164 }
1165 }
1166 else{
1167 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1168 of this moniker.*/
1169
1170 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1171
1172 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1173
1174 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1175
1176 *ppmkPrefix=pmkOther;
1177
1178 return MK_S_HIM;
1179 }
1180 else
1181 return MK_E_NOPREFIX;
1182 }
1183}
1184/***************************************************************************************************
1185 * GetAfterCommonPrefix (local function)
1186 * This function returns a moniker that consist of the remainder when the common prefix is removed
1187 ***************************************************************************************************/
1188VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1189{
1190 IMoniker *tempMk,*tempMk1,*tempMk2;
1191 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1192 ULONG nbRestMk=0;
1193 DWORD mkSys;
1194 HRESULT res1,res2;
1195
1196 *restMk=0;
1197
1198 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1199 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1200 /* on the first difference. */
1201 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1202
1203 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1204
1205 if (mkSys==MKSYS_GENERICCOMPOSITE){
1206
1207 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1208 while(1){
1209
1210 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1211 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1212
1213 if ((res1==S_FALSE)||(res2==S_FALSE)){
1214
1215 if (res1==S_OK)
1216
1217 nbRestMk++;
1218
1219 IMoniker_Release(tempMk1);
1220 IMoniker_Release(tempMk1);
1221
1222 break;
1223 }
1224 IMoniker_Release(tempMk1);
1225 IMoniker_Release(tempMk1);
1226 }
1227 }
1228 else{
1229 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1230 IMoniker_Release(tempMk1);
1231 }
1232
1233 /* count the number of elements in the enumerator after the common prefix */
1234 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1235
1236 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1237
1238 IMoniker_Release(tempMk);;
1239
1240 if (nbRestMk==0)
1241 return;
1242
1243 /* create a generic composite moniker with monikers located after the common prefix */
1244 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1245
1246 if (nbRestMk==1){
1247
1248 *restMk= tempMk1;
1249 return;
1250 }
1251 else {
1252
1253 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1254
1255 CreateGenericComposite(tempMk1,tempMk2,restMk);
1256
1257 IMoniker_Release(tempMk1);
1258
1259 IMoniker_Release(tempMk2);
1260
1261 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1262
1263 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1264
1265 IMoniker_Release(tempMk1);
1266
1267 IMoniker_Release(*restMk);
1268
1269 *restMk=tempMk2;
1270 }
1271 }
1272}
1273/******************************************************************************
1274 * CompositeMoniker_RelativePathTo
1275 ******************************************************************************/
1276HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1277{
1278 HRESULT res;
1279 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1280
1281 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1282
1283 if (ppmkRelPath==NULL)
1284 return E_POINTER;
1285
1286 *ppmkRelPath=0;
1287
1288 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1289 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1290 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1291
1292 /* finds the common prefix of the two monikers */
1293 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1294
1295 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1296 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1297
1298 *ppmkRelPath=pmkOther;
1299 IMoniker_AddRef(pmkOther);
1300 return MK_S_HIM;
1301 }
1302
1303 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1304 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1305
1306 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1307 /* moniker when the common prefix is removed */
1308 if (res==MK_S_HIM){
1309
1310 IMoniker_Inverse(restThisMk,ppmkRelPath);
1311 IMoniker_Release(restThisMk);
1312 }
1313 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1314 /* when the common prefix is removed */
1315 else if (res==MK_S_ME){
1316
1317 *ppmkRelPath=restOtherMk;
1318 IMoniker_AddRef(restOtherMk);
1319 }
1320 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1321 /* moniker on the right of it. */
1322 else if (res==S_OK){
1323
1324 IMoniker_Inverse(restThisMk,&invRestThisMk);
1325 IMoniker_Release(restThisMk);
1326 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1327 IMoniker_Release(invRestThisMk);
1328 IMoniker_Release(restOtherMk);
1329 }
1330 return S_OK;
1331}
1332
1333/******************************************************************************
1334 * CompositeMoniker_GetDisplayName
1335 ******************************************************************************/
1336HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1337 IBindCtx* pbc,
1338 IMoniker* pmkToLeft,
1339 LPOLESTR *ppszDisplayName)
1340{
1341 ULONG lengthStr=1;
1342 IEnumMoniker *enumMoniker;
1343 IMoniker* tempMk;
1344 LPOLESTR tempStr;
1345
1346 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1347
1348 if (ppszDisplayName==NULL)
1349 return E_POINTER;
1350
1351 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1352
1353 if (*ppszDisplayName==NULL)
1354 return E_OUTOFMEMORY;
1355
1356 /* This method returns the concatenation of the display names returned by each component moniker of */
1357 /* the composite */
1358
1359 **ppszDisplayName=0;
1360
1361 IMoniker_Enum(iface,TRUE,&enumMoniker);
1362
1363 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1364
1365 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1366
1367 lengthStr+=lstrlenW(tempStr);
1368
1369 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1370
1371 if (*ppszDisplayName==NULL)
1372 return E_OUTOFMEMORY;
1373
1374 strcatW(*ppszDisplayName,tempStr);
1375
1376 CoTaskMemFree(tempStr);
1377 IMoniker_Release(tempMk);
1378 }
1379
1380 IEnumMoniker_Release(enumMoniker);
1381
1382 return S_OK;
1383}
1384
1385/******************************************************************************
1386 * CompositeMoniker_ParseDisplayName
1387 ******************************************************************************/
1388HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1389 IBindCtx* pbc,
1390 IMoniker* pmkToLeft,
1391 LPOLESTR pszDisplayName,
1392 ULONG* pchEaten,
1393 IMoniker** ppmkOut)
1394{
1395 IEnumMoniker *enumMoniker;
1396 IMoniker *tempMk,*mostRigthMk,*antiMk;
1397 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1398 /* passing everything else as the pmkToLeft parameter for that call. */
1399
1400 /* get the most right moniker */
1401 IMoniker_Enum(iface,FALSE,&enumMoniker);
1402 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1403 IEnumMoniker_Release(enumMoniker);
1404
1405 /* get the left moniker */
1406 CreateAntiMoniker(&antiMk);
1407 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1408 IMoniker_Release(antiMk);
1409
1410 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1411}
1412
1413/******************************************************************************
1414 * CompositeMoniker_IsSystemMoniker
1415 ******************************************************************************/
1416HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1417{
1418 TRACE("(%p,%p)\n",iface,pwdMksys);
1419
1420 if (!pwdMksys)
1421 return E_POINTER;
1422
1423 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1424
1425 return S_OK;
1426}
1427
1428/*******************************************************************************
1429 * CompositeMonikerIROTData_QueryInterface
1430 *******************************************************************************/
1431HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1432{
1433
1434 ICOM_THIS_From_IROTData(IMoniker, iface);
1435
1436 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1437
1438 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1439}
1440
1441/***********************************************************************
1442 * CompositeMonikerIROTData_AddRef
1443 */
1444ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1445{
1446 ICOM_THIS_From_IROTData(IMoniker, iface);
1447
1448 TRACE("(%p)\n",iface);
1449
1450 return CompositeMonikerImpl_AddRef(This);
1451}
1452
1453/***********************************************************************
1454 * CompositeMonikerIROTData_Release
1455 */
1456ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1457{
1458 ICOM_THIS_From_IROTData(IMoniker, iface);
1459
1460 TRACE("(%p)\n",iface);
1461
1462 return CompositeMonikerImpl_Release(This);
1463}
1464
1465/******************************************************************************
1466 * CompositeMonikerIROTData_GetComparaisonData
1467 ******************************************************************************/
1468HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1469 BYTE* pbData,
1470 ULONG cbMax,
1471 ULONG* pcbData)
1472{
1473 FIXME("(),stub!\n");
1474 return E_NOTIMPL;
1475}
1476
1477/******************************************************************************
1478 * EnumMonikerImpl_QueryInterface
1479 ******************************************************************************/
1480HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1481{
1482 ICOM_THIS(EnumMonikerImpl,iface);
1483
1484 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1485
1486 /* Perform a sanity check on the parameters.*/
1487 if ( (This==0) || (ppvObject==0) )
1488 return E_INVALIDARG;
1489
1490 /* Initialize the return parameter */
1491 *ppvObject = 0;
1492
1493 /* Compare the riid with the interface IDs implemented by this object.*/
1494 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1495 *ppvObject = iface;
1496
1497 /* Check that we obtained an interface.*/
1498 if ((*ppvObject)==0)
1499 return E_NOINTERFACE;
1500
1501 /* Query Interface always increases the reference count by one when it is successful */
1502 EnumMonikerImpl_AddRef(iface);
1503
1504 return S_OK;
1505}
1506
1507/******************************************************************************
1508 * EnumMonikerImpl_AddRef
1509 ******************************************************************************/
1510ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1511{
1512 ICOM_THIS(EnumMonikerImpl,iface);
1513
1514 TRACE("(%p)\n",This);
1515
1516 return ++(This->ref);
1517
1518}
1519
1520/******************************************************************************
1521 * EnumMonikerImpl_Release
1522 ******************************************************************************/
1523ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1524{
1525 ICOM_THIS(EnumMonikerImpl,iface);
1526 ULONG i
1527 ;
1528 TRACE("(%p)\n",This);
1529
1530 This->ref--;
1531
1532 /* destroy the object if there's no more reference on it */
1533 if (This->ref==0){
1534
1535 for(i=0;i<This->tabSize;i++)
1536 IMoniker_Release(This->tabMoniker[i]);
1537
1538 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1539 HeapFree(GetProcessHeap(),0,This);
1540
1541 return 0;
1542 }
1543 return This->ref;;
1544}
1545
1546/******************************************************************************
1547 * EnumMonikerImpl_Next
1548 ******************************************************************************/
1549HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1550
1551 ICOM_THIS(EnumMonikerImpl,iface);
1552 ULONG i;
1553
1554 /* retrieve the requested number of moniker from the current position */
1555 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1556
1557 rgelt[i]=This->tabMoniker[This->currentPos++];
1558
1559 if (pceltFethed!=NULL)
1560 *pceltFethed= i;
1561
1562 if (i==celt)
1563 return S_OK;
1564 else
1565 return S_FALSE;
1566}
1567
1568/******************************************************************************
1569 * EnumMonikerImpl_Skip
1570 ******************************************************************************/
1571HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1572
1573 ICOM_THIS(EnumMonikerImpl,iface);
1574
1575 if ((This->currentPos+celt) >= This->tabSize)
1576 return S_FALSE;
1577
1578 This->currentPos+=celt;
1579
1580 return S_OK;
1581}
1582
1583/******************************************************************************
1584 * EnumMonikerImpl_Reset
1585 ******************************************************************************/
1586HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1587
1588 ICOM_THIS(EnumMonikerImpl,iface);
1589
1590 This->currentPos=0;
1591
1592 return S_OK;
1593}
1594
1595/******************************************************************************
1596 * EnumMonikerImpl_Clone
1597 ******************************************************************************/
1598HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1599
1600 ICOM_THIS(EnumMonikerImpl,iface);
1601
1602 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1603}
1604
1605/******************************************************************************
1606 * EnumMonikerImpl_CreateEnumMoniker
1607 ******************************************************************************/
1608HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1609 ULONG tabSize,
1610 ULONG currentPos,
1611 BOOL leftToRigth,
1612 IEnumMoniker ** ppmk)
1613{
1614 EnumMonikerImpl* newEnumMoniker;
1615 int i;
1616
1617
1618 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1619
1620 if (newEnumMoniker == 0)
1621 return STG_E_INSUFFICIENTMEMORY;
1622
1623 if (currentPos > tabSize)
1624 return E_INVALIDARG;
1625
1626 /* Initialize the virtual function table. */
1627 ICOM_VTBL(newEnumMoniker) = &VT_EnumMonikerImpl;
1628 newEnumMoniker->ref = 0;
1629
1630 newEnumMoniker->tabSize=tabSize;
1631 newEnumMoniker->currentPos=currentPos;
1632
1633 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1634
1635 if (newEnumMoniker->tabMoniker==NULL)
1636 return E_OUTOFMEMORY;
1637
1638 if (leftToRigth)
1639 for (i=0;i<tabSize;i++){
1640
1641 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1642 IMoniker_AddRef(tabMoniker[i]);
1643 }
1644 else
1645 for (i=tabSize-1;i>=0;i--){
1646
1647 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1648 IMoniker_AddRef(tabMoniker[i]);
1649 }
1650
1651 *ppmk=(IEnumMoniker*)newEnumMoniker;
1652
1653 return S_OK;
1654}
1655
1656/******************************************************************************
1657 * CreateGenericComposite [OLE.55]
1658 ******************************************************************************/
1659HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1660{
1661 CompositeMonikerImpl* newCompositeMoniker = 0;
1662 HRESULT hr = S_OK;
1663
1664 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1665
1666 if (ppmkComposite==NULL)
1667 return E_POINTER;
1668
1669 *ppmkComposite=0;
1670
1671 if (pmkFirst==NULL && pmkRest!=NULL){
1672
1673 *ppmkComposite=pmkRest;
1674 return S_OK;
1675 }
1676 else if (pmkFirst!=NULL && pmkRest==NULL){
1677 *ppmkComposite=pmkFirst;
1678 return S_OK;
1679 }
1680 else if (pmkFirst==NULL && pmkRest==NULL)
1681 return S_OK;
1682
1683 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1684
1685 if (newCompositeMoniker == 0)
1686 return STG_E_INSUFFICIENTMEMORY;
1687
1688 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1689
1690 if (FAILED(hr)){
1691
1692 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1693 return hr;
1694 }
1695 if (newCompositeMoniker->tabLastIndex==1)
1696
1697 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1698 else
1699
1700 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1701
1702 return hr;
1703}
1704
1705/******************************************************************************
1706 * MonikerCommonPrefixWith [OLE.55]
1707 ******************************************************************************/
1708HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1709{
1710 FIXME("(),stub!\n");
1711 return E_NOTIMPL;
1712}
1713
1714
Note: See TracBrowser for help on using the repository browser.