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

Last change on this file since 7502 was 7502, checked in by phaller, 24 years ago

Fixed out-of-scope FIXME,TRACE,WARN macros

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