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

Last change on this file since 6496 was 5602, checked in by sandervl, 24 years ago

resync with Wine 20010418

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