Move the hwnd self into the listbox LB_DESCR struct.
[wine/wine-kai.git] / dlls / ole32 / compositemoniker.c
blob9d7fa0c08b072c77ca512435d64958874d9c7709
1 /*
2 * CompositeMonikers implementation
4 * Copyright 1999 Noomen Hamza
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <assert.h>
22 #include <stdarg.h>
23 #include <string.h>
25 #define COBJMACROS
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "winerror.h"
33 #include "wine/debug.h"
34 #include "wine/unicode.h"
35 #include "ole2.h"
36 #include "moniker.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40 const CLSID CLSID_CompositeMoniker = {
41 0x309, 0, 0, {0xC0, 0, 0, 0, 0, 0, 0, 0x46}
44 #define BLOCK_TAB_SIZE 5 /* represent the first size table and it's increment block size */
46 /* CompositeMoniker data structure */
47 typedef struct CompositeMonikerImpl{
49 IMonikerVtbl* lpvtbl1; /* VTable relative to the IMoniker interface.*/
51 /* The ROT (RunningObjectTable implementation) uses the IROTData
52 * interface to test whether two monikers are equal. That's why IROTData
53 * interface is implemented by monikers.
55 IROTDataVtbl* lpvtbl2; /* VTable relative to the IROTData interface.*/
57 ULONG ref; /* reference counter for this object */
59 IMoniker** tabMoniker; /* dynamaic table containing all components (monikers) of this composite moniker */
61 ULONG tabSize; /* size of tabMoniker */
63 ULONG tabLastIndex; /* first free index in tabMoniker */
65 } CompositeMonikerImpl;
68 /* EnumMoniker data structure */
69 typedef struct EnumMonikerImpl{
71 IEnumMonikerVtbl *lpVtbl; /* VTable relative to the IEnumMoniker interface.*/
73 ULONG ref; /* reference counter for this object */
75 IMoniker** tabMoniker; /* dynamic table containing the enumerated monikers */
77 ULONG tabSize; /* size of tabMoniker */
79 ULONG currentPos; /* index pointer on the current moniker */
81 } EnumMonikerImpl;
84 /********************************************************************************/
85 /* CompositeMoniker prototype functions : */
87 /* IUnknown prototype functions */
88 static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
89 static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);
90 static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);
92 /* IPersist prototype functions */
93 static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
95 /* IPersistStream prototype functions */
96 static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);
97 static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);
98 static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
99 static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
101 /* IMoniker prototype functions */
102 static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
103 static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
104 static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
105 static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
106 static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
107 static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
108 static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
109 static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
110 static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);
111 static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
112 static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
113 static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
114 static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
115 static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
116 static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
118 /********************************************************************************/
119 /* IROTData prototype functions */
121 /* IUnknown prototype functions */
122 static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
123 static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);
124 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);
126 /* IROTData prototype function */
127 static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
129 /* Local function used by CompositeMoniker implementation */
130 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);
131 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);
133 /********************************************************************************/
134 /* IEnumMoniker prototype functions */
136 /* IUnknown prototype functions */
137 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);
138 static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);
139 static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);
141 /* IEnumMoniker prototype functions */
142 static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);
143 static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);
144 static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);
145 static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);
147 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
149 /********************************************************************************/
150 /* Virtual function table for the CompositeMonikerImpl class which includes */
151 /* IPersist, IPersistStream and IMoniker functions. */
153 static IMonikerVtbl VT_CompositeMonikerImpl =
155 CompositeMonikerImpl_QueryInterface,
156 CompositeMonikerImpl_AddRef,
157 CompositeMonikerImpl_Release,
158 CompositeMonikerImpl_GetClassID,
159 CompositeMonikerImpl_IsDirty,
160 CompositeMonikerImpl_Load,
161 CompositeMonikerImpl_Save,
162 CompositeMonikerImpl_GetSizeMax,
163 CompositeMonikerImpl_BindToObject,
164 CompositeMonikerImpl_BindToStorage,
165 CompositeMonikerImpl_Reduce,
166 CompositeMonikerImpl_ComposeWith,
167 CompositeMonikerImpl_Enum,
168 CompositeMonikerImpl_IsEqual,
169 CompositeMonikerImpl_Hash,
170 CompositeMonikerImpl_IsRunning,
171 CompositeMonikerImpl_GetTimeOfLastChange,
172 CompositeMonikerImpl_Inverse,
173 CompositeMonikerImpl_CommonPrefixWith,
174 CompositeMonikerImpl_RelativePathTo,
175 CompositeMonikerImpl_GetDisplayName,
176 CompositeMonikerImpl_ParseDisplayName,
177 CompositeMonikerImpl_IsSystemMoniker
180 /********************************************************************************/
181 /* Virtual function table for the IROTData class. */
182 static IROTDataVtbl VT_ROTDataImpl =
184 CompositeMonikerROTDataImpl_QueryInterface,
185 CompositeMonikerROTDataImpl_AddRef,
186 CompositeMonikerROTDataImpl_Release,
187 CompositeMonikerROTDataImpl_GetComparaisonData
190 /********************************************************************************/
191 /* Virtual function table for the IROTData class */
192 static IEnumMonikerVtbl VT_EnumMonikerImpl =
194 EnumMonikerImpl_QueryInterface,
195 EnumMonikerImpl_AddRef,
196 EnumMonikerImpl_Release,
197 EnumMonikerImpl_Next,
198 EnumMonikerImpl_Skip,
199 EnumMonikerImpl_Reset,
200 EnumMonikerImpl_Clone
203 /*******************************************************************************
204 * CompositeMoniker_QueryInterface
205 *******************************************************************************/
206 HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
208 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
210 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
212 /* Perform a sanity check on the parameters.*/
213 if ( (This==0) || (ppvObject==0) )
214 return E_INVALIDARG;
216 /* Initialize the return parameter */
217 *ppvObject = 0;
219 /* Compare the riid with the interface IDs implemented by this object.*/
220 if (IsEqualIID(&IID_IUnknown, riid) ||
221 IsEqualIID(&IID_IPersist, riid) ||
222 IsEqualIID(&IID_IPersistStream, riid) ||
223 IsEqualIID(&IID_IMoniker, riid)
225 *ppvObject = iface;
226 else if (IsEqualIID(&IID_IROTData, riid))
227 *ppvObject = (IROTData*)&(This->lpvtbl2);
229 /* Check that we obtained an interface.*/
230 if ((*ppvObject)==0)
231 return E_NOINTERFACE;
233 /* Query Interface always increases the reference count by one when it is successful */
234 CompositeMonikerImpl_AddRef(iface);
236 return S_OK;
239 /******************************************************************************
240 * CompositeMoniker_AddRef
241 ******************************************************************************/
242 ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)
244 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
246 TRACE("(%p)\n",This);
248 return InterlockedIncrement(&This->ref);
251 /******************************************************************************
252 * CompositeMoniker_Release
253 ******************************************************************************/
254 ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
256 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
257 ULONG i;
258 ULONG ref;
260 TRACE("(%p)\n",This);
262 ref = InterlockedDecrement(&This->ref);
264 /* destroy the object if there's no more reference on it */
265 if (ref == 0){
267 /* release all the components before destroying this object */
268 for (i=0;i<This->tabLastIndex;i++)
269 IMoniker_Release(This->tabMoniker[i]);
271 CompositeMonikerImpl_Destroy(This);
273 return ref;
276 /******************************************************************************
277 * CompositeMoniker_GetClassID
278 ******************************************************************************/
279 HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
281 TRACE("(%p,%p),stub!\n",iface,pClassID);
283 if (pClassID==NULL)
284 return E_POINTER;
286 *pClassID = CLSID_CompositeMoniker;
288 return S_OK;
291 /******************************************************************************
292 * CompositeMoniker_IsDirty
293 ******************************************************************************/
294 HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)
296 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
297 method in the OLE-provided moniker interfaces always return S_FALSE because
298 their internal state never changes. */
300 TRACE("(%p)\n",iface);
302 return S_FALSE;
305 /******************************************************************************
306 * CompositeMoniker_Load
307 ******************************************************************************/
308 HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
310 HRESULT res;
311 DWORD constant;
312 CLSID clsid;
313 WCHAR string[1]={0};
315 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
317 TRACE("(%p,%p)\n",iface,pStm);
319 /* this function call OleLoadFromStream function for each moniker within this object */
321 /* read the a constant written by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
322 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
324 if (SUCCEEDED(res)&& constant!=3)
325 return E_FAIL;
327 while(1){
328 #if 0
329 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
330 #endif
331 res=ReadClassStm(pStm,&clsid);
332 DPRINTF("res=%ld",res);
333 if (FAILED(res))
334 break;
336 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
337 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
338 if (FAILED(res))
339 break;
340 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
341 if (FAILED(res))
342 break;
344 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
345 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
346 if (res!=S_OK)
347 break;
348 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
349 if (FAILED(res))
350 break;
352 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
353 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
354 if (FAILED(res))
355 break;
356 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
357 if (FAILED(res))
358 break;
360 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
361 return E_FAIL;
363 else
365 FIXME("()\n");
366 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
367 break;
368 return E_NOTIMPL;
371 /* resize the table if needed */
372 if (++This->tabLastIndex==This->tabSize){
374 This->tabSize+=BLOCK_TAB_SIZE;
375 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
377 if (This->tabMoniker==NULL)
378 return E_OUTOFMEMORY;
382 return res;
385 /******************************************************************************
386 * CompositeMoniker_Save
387 ******************************************************************************/
388 HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
390 HRESULT res;
391 IEnumMoniker *enumMk;
392 IMoniker *pmk;
393 DWORD constant=3;
395 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
397 /* This function calls OleSaveToStream function for each moniker within
398 * this object.
399 * When I tested this function in windows, I usually found this constant
400 * at the beginning of the stream. I don't known why (there's no
401 * indication in the specification) !
403 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
405 IMoniker_Enum(iface,TRUE,&enumMk);
407 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
409 res=OleSaveToStream((IPersistStream*)pmk,pStm);
411 IMoniker_Release(pmk);
413 if (FAILED(res)){
415 IEnumMoniker_Release(pmk);
416 return res;
420 IEnumMoniker_Release(enumMk);
422 return S_OK;
425 /******************************************************************************
426 * CompositeMoniker_GetSizeMax
427 ******************************************************************************/
428 HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
430 IEnumMoniker *enumMk;
431 IMoniker *pmk;
432 ULARGE_INTEGER ptmpSize;
434 /* The sizeMax of this object is calculated by calling GetSizeMax on
435 * each moniker within this object then summing all returned values
438 TRACE("(%p,%p)\n",iface,pcbSize);
440 if (pcbSize!=NULL)
441 return E_POINTER;
443 pcbSize->u.LowPart =0;
444 pcbSize->u.HighPart=0;
446 IMoniker_Enum(iface,TRUE,&enumMk);
448 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==TRUE){
450 IMoniker_GetSizeMax(pmk,&ptmpSize);
452 IMoniker_Release(pmk);
454 pcbSize->u.LowPart +=ptmpSize.u.LowPart;
455 pcbSize->u.HighPart+=ptmpSize.u.HighPart;
458 IEnumMoniker_Release(enumMk);
460 return S_OK;
463 /******************************************************************************
464 * Composite-Moniker_Construct (local function)
465 *******************************************************************************/
466 HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)
468 DWORD mkSys;
469 IEnumMoniker *enumMoniker;
470 IMoniker *tempMk;
471 HRESULT res;
473 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
475 /* Initialize the virtual function table. */
476 This->lpvtbl1 = &VT_CompositeMonikerImpl;
477 This->lpvtbl2 = &VT_ROTDataImpl;
478 This->ref = 0;
480 This->tabSize=BLOCK_TAB_SIZE;
481 This->tabLastIndex=0;
483 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
484 if (This->tabMoniker==NULL)
485 return E_OUTOFMEMORY;
487 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
489 /* put the first moniker contents in the beginning of the table */
490 if (mkSys!=MKSYS_GENERICCOMPOSITE){
492 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
493 IMoniker_AddRef(pmkFirst);
495 else{
497 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
499 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
502 if (++This->tabLastIndex==This->tabSize){
504 This->tabSize+=BLOCK_TAB_SIZE;
505 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
507 if (This->tabMoniker==NULL)
508 return E_OUTOFMEMORY;
512 IEnumMoniker_Release(enumMoniker);
515 /* put the rest moniker contents after the first one and make simplification if needed */
517 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
519 if (mkSys!=MKSYS_GENERICCOMPOSITE){
521 /* add a simple moniker to the moniker table */
523 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
525 if (res==MK_E_NEEDGENERIC){
527 /* there's no simplification in this case */
528 This->tabMoniker[This->tabLastIndex]=pmkRest;
530 This->tabLastIndex++;
532 IMoniker_AddRef(pmkRest);
534 else if (tempMk==NULL){
536 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
537 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
539 This->tabLastIndex--;
541 else if (SUCCEEDED(res)){
543 /* the non-generic composition was successful so we can make a simplification in this case */
544 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
546 This->tabMoniker[This->tabLastIndex-1]=tempMk;
547 } else
548 return res;
550 /* resize tabMoniker if needed */
551 if (This->tabLastIndex==This->tabSize){
553 This->tabSize+=BLOCK_TAB_SIZE;
555 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
557 if (This->tabMoniker==NULL)
558 return E_OUTOFMEMORY;
561 else{
563 /* add a composite moniker to the moniker table (do the same thing
564 * for each moniker within the composite moniker as a simple moniker
565 * (see above for how to add a simple moniker case) )
567 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
569 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
571 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
573 if (res==MK_E_NEEDGENERIC){
575 This->tabLastIndex++;
577 else if (tempMk==NULL){
579 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
580 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
581 This->tabLastIndex--;
583 else{
585 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
587 This->tabMoniker[This->tabLastIndex-1]=tempMk;
590 if (This->tabLastIndex==This->tabSize){
592 This->tabSize+=BLOCK_TAB_SIZE;
594 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
596 if (This->tabMoniker==NULL)
597 return E_OUTOFMEMORY;
601 IEnumMoniker_Release(enumMoniker);
604 return S_OK;
607 /******************************************************************************
608 * CompositeMoniker_Destroy (local function)
609 *******************************************************************************/
610 HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)
612 TRACE("(%p)\n",This);
614 HeapFree(GetProcessHeap(),0,This->tabMoniker);
616 HeapFree(GetProcessHeap(),0,This);
618 return S_OK;
621 /******************************************************************************
622 * CompositeMoniker_BindToObject
623 ******************************************************************************/
624 HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,
625 IBindCtx* pbc,
626 IMoniker* pmkToLeft,
627 REFIID riid,
628 VOID** ppvResult)
630 HRESULT res;
631 IRunningObjectTable *prot;
632 IMoniker *tempMk,*antiMk,*mostRigthMk;
633 IEnumMoniker *enumMoniker;
635 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
637 if (ppvResult==NULL)
638 return E_POINTER;
640 *ppvResult=0;
641 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
642 /* object for the requested interface pointer. */
643 if(pmkToLeft==NULL){
645 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
647 if (SUCCEEDED(res)){
649 /* if the requested class was loaded before ! we don't need to reload it */
650 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
652 if (res==S_OK)
653 return res;
656 else{
657 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
658 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
660 IMoniker_Enum(iface,FALSE,&enumMoniker);
661 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
662 IEnumMoniker_Release(enumMoniker);
664 res=CreateAntiMoniker(&antiMk);
665 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
666 IMoniker_Release(antiMk);
668 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
670 IMoniker_Release(tempMk);
671 IMoniker_Release(mostRigthMk);
674 return res;
677 /******************************************************************************
678 * CompositeMoniker_BindToStorage
679 ******************************************************************************/
680 HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,
681 IBindCtx* pbc,
682 IMoniker* pmkToLeft,
683 REFIID riid,
684 VOID** ppvResult)
686 HRESULT res;
687 IMoniker *tempMk,*antiMk,*mostRigthMk;
688 IEnumMoniker *enumMoniker;
690 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
692 *ppvResult=0;
694 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
695 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
697 if (pmkToLeft!=NULL){
699 IMoniker_Enum(iface,FALSE,&enumMoniker);
700 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
701 IEnumMoniker_Release(enumMoniker);
703 res=CreateAntiMoniker(&antiMk);
704 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
705 IMoniker_Release(antiMk);
707 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
709 IMoniker_Release(tempMk);
711 IMoniker_Release(mostRigthMk);
713 return res;
715 else
716 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
719 /******************************************************************************
720 * CompositeMoniker_Reduce
721 ******************************************************************************/
722 HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,
723 IBindCtx* pbc,
724 DWORD dwReduceHowFar,
725 IMoniker** ppmkToLeft,
726 IMoniker** ppmkReduced)
728 HRESULT res;
729 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
730 IEnumMoniker *enumMoniker;
732 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
734 if (ppmkReduced==NULL)
735 return E_POINTER;
737 /* This method recursively calls Reduce for each of its component monikers. */
739 if (ppmkToLeft==NULL){
741 IMoniker_Enum(iface,FALSE,&enumMoniker);
742 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
743 IEnumMoniker_Release(enumMoniker);
745 res=CreateAntiMoniker(&antiMk);
746 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
747 IMoniker_Release(antiMk);
749 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
751 else if (*ppmkToLeft==NULL)
753 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
755 else{
757 /* separate the composite moniker in to left and right moniker */
758 IMoniker_Enum(iface,FALSE,&enumMoniker);
759 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
760 IEnumMoniker_Release(enumMoniker);
762 res=CreateAntiMoniker(&antiMk);
763 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
764 IMoniker_Release(antiMk);
766 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
767 /* of the reduced components */
768 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
769 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
772 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
774 else{
775 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
777 IMoniker_AddRef(iface);
779 *ppmkReduced=iface;
781 return MK_S_REDUCED_TO_SELF;
786 /******************************************************************************
787 * CompositeMoniker_ComposeWith
788 ******************************************************************************/
789 HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,
790 IMoniker* pmkRight,
791 BOOL fOnlyIfNotGeneric,
792 IMoniker** ppmkComposite)
794 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
796 if ((ppmkComposite==NULL)||(pmkRight==NULL))
797 return E_POINTER;
799 *ppmkComposite=0;
801 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
802 /* otherwise, the method returns the result of combining the two monikers by calling the */
803 /* CreateGenericComposite function */
805 if (fOnlyIfNotGeneric)
806 return MK_E_NEEDGENERIC;
808 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
811 /******************************************************************************
812 * CompositeMoniker_Enum
813 ******************************************************************************/
814 HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
816 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
818 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
820 if (ppenumMoniker == NULL)
821 return E_POINTER;
823 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
826 /******************************************************************************
827 * CompositeMoniker_IsEqual
828 ******************************************************************************/
829 HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
831 IEnumMoniker *enumMoniker1,*enumMoniker2;
832 IMoniker *tempMk1,*tempMk2;
833 HRESULT res1,res2,res;
835 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
837 if (pmkOtherMoniker==NULL)
838 return S_FALSE;
840 /* This method returns S_OK if the components of both monikers are equal when compared in the */
841 /* left-to-right order.*/
842 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
844 if (enumMoniker1==NULL)
845 return S_FALSE;
847 IMoniker_Enum(iface,TRUE,&enumMoniker2);
849 while(1){
851 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
852 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
854 if((res1==S_OK)&&(res2==S_OK)){
856 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
857 res= S_FALSE;
858 break;
860 else
861 continue;
863 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
864 res = S_OK;
865 break;
867 else{
868 res = S_FALSE;
869 break;
872 if (res1==S_OK)
873 IMoniker_Release(tempMk1);
875 if (res2==S_OK)
876 IMoniker_Release(tempMk2);
879 IEnumMoniker_Release(enumMoniker1);
880 IEnumMoniker_Release(enumMoniker2);
882 return res;
884 /******************************************************************************
885 * CompositeMoniker_Hash
886 ******************************************************************************/
887 HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
889 FIXME("(),stub!\n");
891 return E_NOTIMPL;
894 /******************************************************************************
895 * CompositeMoniker_IsRunning
896 ******************************************************************************/
897 HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,
898 IBindCtx* pbc,
899 IMoniker* pmkToLeft,
900 IMoniker* pmkNewlyRunning)
902 IRunningObjectTable* rot;
903 HRESULT res;
904 IMoniker *tempMk,*antiMk,*mostRigthMk;
905 IEnumMoniker *enumMoniker;
907 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
909 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
910 if (pmkToLeft!=NULL){
912 CreateGenericComposite(pmkToLeft,iface,&tempMk);
914 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
916 IMoniker_Release(tempMk);
918 return res;
920 else
921 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
922 /* to this moniker */
924 if (pmkNewlyRunning!=NULL)
926 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
927 return S_OK;
929 else
930 return S_FALSE;
932 else{
934 if (pbc==NULL)
935 return E_POINTER;
937 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
938 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
939 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
940 /* the composite as the pmkToLeft parameter for that call. */
942 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
944 if (FAILED(res))
945 return res;
947 res = IRunningObjectTable_IsRunning(rot,iface);
948 IRunningObjectTable_Release(rot);
950 if(res==S_OK)
951 return S_OK;
953 else{
955 IMoniker_Enum(iface,FALSE,&enumMoniker);
956 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
957 IEnumMoniker_Release(enumMoniker);
959 res=CreateAntiMoniker(&antiMk);
960 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
961 IMoniker_Release(antiMk);
963 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
965 IMoniker_Release(tempMk);
966 IMoniker_Release(mostRigthMk);
968 return res;
973 /******************************************************************************
974 * CompositeMoniker_GetTimeOfLastChange
975 ******************************************************************************/
976 HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
977 IBindCtx* pbc,
978 IMoniker* pmkToLeft,
979 FILETIME* pCompositeTime)
981 IRunningObjectTable* rot;
982 HRESULT res;
983 IMoniker *tempMk,*antiMk,*mostRigthMk;
984 IEnumMoniker *enumMoniker;
986 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
988 if (pCompositeTime==NULL)
989 return E_INVALIDARG;
991 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
992 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
993 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
994 /* of the composite as the pmkToLeft parameter for that call. */
995 if (pmkToLeft!=NULL){
997 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
999 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
1001 if (FAILED(res))
1002 return res;
1004 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
1005 return res;
1006 else
1008 IMoniker_Enum(iface,FALSE,&enumMoniker);
1009 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1010 IEnumMoniker_Release(enumMoniker);
1012 res=CreateAntiMoniker(&antiMk);
1013 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1014 IMoniker_Release(antiMk);
1016 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
1018 IMoniker_Release(tempMk);
1019 IMoniker_Release(mostRigthMk);
1021 return res;
1023 else
1024 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
1027 /******************************************************************************
1028 * CompositeMoniker_Inverse
1029 ******************************************************************************/
1030 HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
1032 HRESULT res;
1033 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
1034 IEnumMoniker *enumMoniker;
1036 TRACE("(%p,%p)\n",iface,ppmk);
1038 if (ppmk==NULL)
1039 return E_POINTER;
1041 /* This method returns a composite moniker that consists of the inverses of each of the components */
1042 /* of the original composite, stored in reverse order */
1044 res=CreateAntiMoniker(&antiMk);
1045 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1046 IMoniker_Release(antiMk);
1048 if (tempMk==NULL)
1050 return IMoniker_Inverse(iface,ppmk);
1052 else{
1054 IMoniker_Enum(iface,FALSE,&enumMoniker);
1055 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1056 IEnumMoniker_Release(enumMoniker);
1058 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
1059 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
1061 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
1063 IMoniker_Release(tempMk);
1064 IMoniker_Release(mostRigthMk);
1065 IMoniker_Release(tempInvMk);
1066 IMoniker_Release(mostRigthInvMk);
1068 return res;
1072 /******************************************************************************
1073 * CompositeMoniker_CommonPrefixWith
1074 ******************************************************************************/
1075 HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
1077 DWORD mkSys;
1078 HRESULT res1,res2;
1079 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
1080 IEnumMoniker *enumMoniker1,*enumMoniker2;
1081 ULONG i,nbCommonMk=0;
1083 /* If the other moniker is a composite, this method compares the components of each composite from left */
1084 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
1085 /* of the leftmost components were common to both monikers. */
1087 if (ppmkPrefix==NULL)
1088 return E_POINTER;
1090 *ppmkPrefix=0;
1092 if (pmkOther==NULL)
1093 return MK_E_NOPREFIX;
1095 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
1097 if((mkSys==MKSYS_GENERICCOMPOSITE)){
1099 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1100 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
1102 while(1){
1104 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1105 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
1107 if ((res1==S_FALSE) && (res2==S_FALSE)){
1109 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
1110 *ppmkPrefix=iface;
1111 IMoniker_AddRef(iface);
1112 return MK_S_US;
1114 else if ((res1==S_OK) && (res2==S_OK)){
1116 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
1118 nbCommonMk++;
1120 else
1121 break;
1124 else if (res1==S_OK){
1126 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
1127 /* ppmkPrefix to the other moniker. */
1128 *ppmkPrefix=pmkOther;
1129 return MK_S_HIM;
1131 else{
1132 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
1133 /* to this moniker. */
1134 *ppmkPrefix=iface;
1135 return MK_S_ME;
1139 IEnumMoniker_Release(enumMoniker1);
1140 IEnumMoniker_Release(enumMoniker2);
1142 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
1143 if (nbCommonMk==0)
1144 return MK_E_NOPREFIX;
1146 IEnumMoniker_Reset(enumMoniker1);
1148 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1150 /* if we have more than one commun moniker the result will be a composite moniker */
1151 if (nbCommonMk>1){
1153 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
1154 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1155 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
1156 IMoniker_Release(tempMk1);
1157 IMoniker_Release(tempMk2);
1159 /* compose all common monikers in a composite moniker */
1160 for(i=0;i<nbCommonMk;i++){
1162 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1164 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
1166 IMoniker_Release(*ppmkPrefix);
1168 IMoniker_Release(tempMk1);
1170 *ppmkPrefix=tempMk2;
1172 return S_OK;
1174 else{
1175 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
1176 *ppmkPrefix=tempMk1;
1178 return S_OK;
1181 else{
1182 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
1183 of this moniker.*/
1185 IMoniker_Enum(iface,TRUE,&enumMoniker1);
1187 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
1189 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
1191 *ppmkPrefix=pmkOther;
1193 return MK_S_HIM;
1195 else
1196 return MK_E_NOPREFIX;
1199 /***************************************************************************************************
1200 * GetAfterCommonPrefix (local function)
1201 * This function returns a moniker that consist of the remainder when the common prefix is removed
1202 ***************************************************************************************************/
1203 VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
1205 IMoniker *tempMk,*tempMk1,*tempMk2;
1206 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
1207 ULONG nbRestMk=0;
1208 DWORD mkSys;
1209 HRESULT res1,res2;
1211 *restMk=0;
1213 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
1214 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
1215 /* on the first difference. */
1216 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
1218 IMoniker_IsSystemMoniker(commonMk,&mkSys);
1220 if (mkSys==MKSYS_GENERICCOMPOSITE){
1222 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
1223 while(1){
1225 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1226 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
1228 if ((res1==S_FALSE)||(res2==S_FALSE)){
1230 if (res1==S_OK)
1232 nbRestMk++;
1234 IMoniker_Release(tempMk1);
1235 IMoniker_Release(tempMk1);
1237 break;
1239 IMoniker_Release(tempMk1);
1240 IMoniker_Release(tempMk1);
1243 else{
1244 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1245 IMoniker_Release(tempMk1);
1248 /* count the number of elements in the enumerator after the common prefix */
1249 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1251 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1253 IMoniker_Release(tempMk);
1255 if (nbRestMk==0)
1256 return;
1258 /* create a generic composite moniker with monikers located after the common prefix */
1259 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1261 if (nbRestMk==1){
1263 *restMk= tempMk1;
1264 return;
1266 else {
1268 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1270 CreateGenericComposite(tempMk1,tempMk2,restMk);
1272 IMoniker_Release(tempMk1);
1274 IMoniker_Release(tempMk2);
1276 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1278 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1280 IMoniker_Release(tempMk1);
1282 IMoniker_Release(*restMk);
1284 *restMk=tempMk2;
1288 /******************************************************************************
1289 * CompositeMoniker_RelativePathTo
1290 ******************************************************************************/
1291 HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)
1293 HRESULT res;
1294 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1296 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1298 if (ppmkRelPath==NULL)
1299 return E_POINTER;
1301 *ppmkRelPath=0;
1303 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1304 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1305 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1307 /* finds the common prefix of the two monikers */
1308 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1310 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1311 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1313 *ppmkRelPath=pmkOther;
1314 IMoniker_AddRef(pmkOther);
1315 return MK_S_HIM;
1318 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1319 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1321 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1322 /* moniker when the common prefix is removed */
1323 if (res==MK_S_HIM){
1325 IMoniker_Inverse(restThisMk,ppmkRelPath);
1326 IMoniker_Release(restThisMk);
1328 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1329 /* when the common prefix is removed */
1330 else if (res==MK_S_ME){
1332 *ppmkRelPath=restOtherMk;
1333 IMoniker_AddRef(restOtherMk);
1335 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1336 /* moniker on the right of it. */
1337 else if (res==S_OK){
1339 IMoniker_Inverse(restThisMk,&invRestThisMk);
1340 IMoniker_Release(restThisMk);
1341 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1342 IMoniker_Release(invRestThisMk);
1343 IMoniker_Release(restOtherMk);
1345 return S_OK;
1348 /******************************************************************************
1349 * CompositeMoniker_GetDisplayName
1350 ******************************************************************************/
1351 HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,
1352 IBindCtx* pbc,
1353 IMoniker* pmkToLeft,
1354 LPOLESTR *ppszDisplayName)
1356 ULONG lengthStr=1;
1357 IEnumMoniker *enumMoniker;
1358 IMoniker* tempMk;
1359 LPOLESTR tempStr;
1361 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1363 if (ppszDisplayName==NULL)
1364 return E_POINTER;
1366 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1368 if (*ppszDisplayName==NULL)
1369 return E_OUTOFMEMORY;
1371 /* This method returns the concatenation of the display names returned by each component moniker of */
1372 /* the composite */
1374 **ppszDisplayName=0;
1376 IMoniker_Enum(iface,TRUE,&enumMoniker);
1378 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1380 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1382 lengthStr+=lstrlenW(tempStr);
1384 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1386 if (*ppszDisplayName==NULL)
1387 return E_OUTOFMEMORY;
1389 strcatW(*ppszDisplayName,tempStr);
1391 CoTaskMemFree(tempStr);
1392 IMoniker_Release(tempMk);
1395 IEnumMoniker_Release(enumMoniker);
1397 return S_OK;
1400 /******************************************************************************
1401 * CompositeMoniker_ParseDisplayName
1402 ******************************************************************************/
1403 HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,
1404 IBindCtx* pbc,
1405 IMoniker* pmkToLeft,
1406 LPOLESTR pszDisplayName,
1407 ULONG* pchEaten,
1408 IMoniker** ppmkOut)
1410 IEnumMoniker *enumMoniker;
1411 IMoniker *tempMk,*mostRigthMk,*antiMk;
1412 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1413 /* passing everything else as the pmkToLeft parameter for that call. */
1415 /* get the most right moniker */
1416 IMoniker_Enum(iface,FALSE,&enumMoniker);
1417 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1418 IEnumMoniker_Release(enumMoniker);
1420 /* get the left moniker */
1421 CreateAntiMoniker(&antiMk);
1422 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1423 IMoniker_Release(antiMk);
1425 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1428 /******************************************************************************
1429 * CompositeMoniker_IsSystemMoniker
1430 ******************************************************************************/
1431 HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1433 TRACE("(%p,%p)\n",iface,pwdMksys);
1435 if (!pwdMksys)
1436 return E_POINTER;
1438 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1440 return S_OK;
1443 /*******************************************************************************
1444 * CompositeMonikerIROTData_QueryInterface
1445 *******************************************************************************/
1446 HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
1449 ICOM_THIS_From_IROTData(IMoniker, iface);
1451 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1453 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1456 /***********************************************************************
1457 * CompositeMonikerIROTData_AddRef
1459 ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1461 ICOM_THIS_From_IROTData(IMoniker, iface);
1463 TRACE("(%p)\n",iface);
1465 return CompositeMonikerImpl_AddRef(This);
1468 /***********************************************************************
1469 * CompositeMonikerIROTData_Release
1471 ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1473 ICOM_THIS_From_IROTData(IMoniker, iface);
1475 TRACE("(%p)\n",iface);
1477 return CompositeMonikerImpl_Release(This);
1480 /******************************************************************************
1481 * CompositeMonikerIROTData_GetComparaisonData
1482 ******************************************************************************/
1483 HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1484 BYTE* pbData,
1485 ULONG cbMax,
1486 ULONG* pcbData)
1488 FIXME("(),stub!\n");
1489 return E_NOTIMPL;
1492 /******************************************************************************
1493 * EnumMonikerImpl_QueryInterface
1494 ******************************************************************************/
1495 HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1497 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1499 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1501 /* Perform a sanity check on the parameters.*/
1502 if ( (This==0) || (ppvObject==0) )
1503 return E_INVALIDARG;
1505 /* Initialize the return parameter */
1506 *ppvObject = 0;
1508 /* Compare the riid with the interface IDs implemented by this object.*/
1509 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1510 *ppvObject = iface;
1512 /* Check that we obtained an interface.*/
1513 if ((*ppvObject)==0)
1514 return E_NOINTERFACE;
1516 /* Query Interface always increases the reference count by one when it is successful */
1517 EnumMonikerImpl_AddRef(iface);
1519 return S_OK;
1522 /******************************************************************************
1523 * EnumMonikerImpl_AddRef
1524 ******************************************************************************/
1525 ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1527 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1529 TRACE("(%p)\n",This);
1531 return InterlockedIncrement(&This->ref);
1535 /******************************************************************************
1536 * EnumMonikerImpl_Release
1537 ******************************************************************************/
1538 ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)
1540 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1541 ULONG i;
1542 ULONG ref;
1543 TRACE("(%p)\n",This);
1545 ref = InterlockedDecrement(&This->ref);
1547 /* destroy the object if there's no more reference on it */
1548 if (ref == 0) {
1550 for(i=0;i<This->tabSize;i++)
1551 IMoniker_Release(This->tabMoniker[i]);
1553 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1554 HeapFree(GetProcessHeap(),0,This);
1556 return ref;
1559 /******************************************************************************
1560 * EnumMonikerImpl_Next
1561 ******************************************************************************/
1562 HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){
1564 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1565 ULONG i;
1567 /* retrieve the requested number of moniker from the current position */
1568 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1570 rgelt[i]=This->tabMoniker[This->currentPos++];
1572 if (pceltFethed!=NULL)
1573 *pceltFethed= i;
1575 if (i==celt)
1576 return S_OK;
1577 else
1578 return S_FALSE;
1581 /******************************************************************************
1582 * EnumMonikerImpl_Skip
1583 ******************************************************************************/
1584 HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){
1586 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1588 if ((This->currentPos+celt) >= This->tabSize)
1589 return S_FALSE;
1591 This->currentPos+=celt;
1593 return S_OK;
1596 /******************************************************************************
1597 * EnumMonikerImpl_Reset
1598 ******************************************************************************/
1599 HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){
1601 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1603 This->currentPos=0;
1605 return S_OK;
1608 /******************************************************************************
1609 * EnumMonikerImpl_Clone
1610 ******************************************************************************/
1611 HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){
1613 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1615 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1618 /******************************************************************************
1619 * EnumMonikerImpl_CreateEnumMoniker
1620 ******************************************************************************/
1621 HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,
1622 ULONG tabSize,
1623 ULONG currentPos,
1624 BOOL leftToRigth,
1625 IEnumMoniker ** ppmk)
1627 EnumMonikerImpl* newEnumMoniker;
1628 int i;
1631 if (currentPos > tabSize)
1632 return E_INVALIDARG;
1634 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1636 if (newEnumMoniker == 0)
1637 return STG_E_INSUFFICIENTMEMORY;
1639 /* Initialize the virtual function table. */
1640 newEnumMoniker->lpVtbl = &VT_EnumMonikerImpl;
1641 newEnumMoniker->ref = 0;
1643 newEnumMoniker->tabSize=tabSize;
1644 newEnumMoniker->currentPos=currentPos;
1646 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1648 if (newEnumMoniker->tabMoniker==NULL) {
1649 HeapFree(GetProcessHeap(), 0, newEnumMoniker);
1650 return E_OUTOFMEMORY;
1653 if (leftToRigth)
1654 for (i=0;i<tabSize;i++){
1656 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1657 IMoniker_AddRef(tabMoniker[i]);
1659 else
1660 for (i=tabSize-1;i>=0;i--){
1662 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1663 IMoniker_AddRef(tabMoniker[i]);
1666 *ppmk=(IEnumMoniker*)newEnumMoniker;
1668 return S_OK;
1671 /******************************************************************************
1672 * CreateGenericComposite [OLE32.@]
1673 ******************************************************************************/
1674 HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)
1676 CompositeMonikerImpl* newCompositeMoniker = 0;
1677 HRESULT hr = S_OK;
1679 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1681 if (ppmkComposite==NULL)
1682 return E_POINTER;
1684 *ppmkComposite=0;
1686 if (pmkFirst==NULL && pmkRest!=NULL){
1688 *ppmkComposite=pmkRest;
1689 return S_OK;
1691 else if (pmkFirst!=NULL && pmkRest==NULL){
1692 *ppmkComposite=pmkFirst;
1693 return S_OK;
1695 else if (pmkFirst==NULL && pmkRest==NULL)
1696 return S_OK;
1698 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1700 if (newCompositeMoniker == 0)
1701 return STG_E_INSUFFICIENTMEMORY;
1703 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1705 if (FAILED(hr)){
1707 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1708 return hr;
1710 if (newCompositeMoniker->tabLastIndex==1)
1712 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1713 else
1715 hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1717 return hr;
1720 /******************************************************************************
1721 * MonikerCommonPrefixWith [OLE32.@]
1722 ******************************************************************************/
1723 HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1725 FIXME("(),stub!\n");
1726 return E_NOTIMPL;