source: trunk/src/ole32/compositemoniker.cpp@ 1033

Last change on this file since 1033 was 1033, checked in by davidr, 26 years ago

Ported remaining files pertaining to OLE32 from WINE

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