advpack: Add initial implementation of SetPerUserSecValues.
[wine/dcerpc.git] / dlls / ole32 / compositemoniker.c
blob4e9d763e41f2eb5d45928a68f7bcaeb2c1f26937
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 static 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 const 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 const IROTDataVtbl* lpvtbl2; /* VTable relative to the IROTData interface.*/
57 LONG 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 const IEnumMonikerVtbl *lpVtbl; /* VTable relative to the IEnumMoniker interface.*/
73 LONG 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;
83 static inline IMoniker *impl_from_IROTData( IROTData *iface )
85 return (IMoniker *)((char*)iface - FIELD_OFFSET(CompositeMonikerImpl, lpvtbl2));
88 static HRESULT EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);
90 /*******************************************************************************
91 * CompositeMoniker_QueryInterface
92 *******************************************************************************/
93 static HRESULT WINAPI
94 CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
96 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
98 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
100 /* Perform a sanity check on the parameters.*/
101 if ( (This==0) || (ppvObject==0) )
102 return E_INVALIDARG;
104 /* Initialize the return parameter */
105 *ppvObject = 0;
107 /* Compare the riid with the interface IDs implemented by this object.*/
108 if (IsEqualIID(&IID_IUnknown, riid) ||
109 IsEqualIID(&IID_IPersist, riid) ||
110 IsEqualIID(&IID_IPersistStream, riid) ||
111 IsEqualIID(&IID_IMoniker, riid)
113 *ppvObject = iface;
114 else if (IsEqualIID(&IID_IROTData, riid))
115 *ppvObject = (IROTData*)&(This->lpvtbl2);
117 /* Check that we obtained an interface.*/
118 if ((*ppvObject)==0)
119 return E_NOINTERFACE;
121 /* Query Interface always increases the reference count by one when it is successful */
122 IMoniker_AddRef(iface);
124 return S_OK;
127 /******************************************************************************
128 * CompositeMoniker_AddRef
129 ******************************************************************************/
130 static ULONG WINAPI
131 CompositeMonikerImpl_AddRef(IMoniker* iface)
133 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
135 TRACE("(%p)\n",This);
137 return InterlockedIncrement(&This->ref);
140 /******************************************************************************
141 * CompositeMoniker_Release
142 ******************************************************************************/
143 static ULONG WINAPI
144 CompositeMonikerImpl_Release(IMoniker* iface)
146 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
147 ULONG i;
148 ULONG ref;
150 TRACE("(%p)\n",This);
152 ref = InterlockedDecrement(&This->ref);
154 /* destroy the object if there's no more reference on it */
155 if (ref == 0){
157 /* release all the components before destroying this object */
158 for (i=0;i<This->tabLastIndex;i++)
159 IMoniker_Release(This->tabMoniker[i]);
161 HeapFree(GetProcessHeap(),0,This->tabMoniker);
162 HeapFree(GetProcessHeap(),0,This);
164 return ref;
167 /******************************************************************************
168 * CompositeMoniker_GetClassID
169 ******************************************************************************/
170 static HRESULT WINAPI
171 CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
173 TRACE("(%p,%p)\n",iface,pClassID);
175 if (pClassID==NULL)
176 return E_POINTER;
178 *pClassID = CLSID_CompositeMoniker;
180 return S_OK;
183 /******************************************************************************
184 * CompositeMoniker_IsDirty
185 ******************************************************************************/
186 static HRESULT WINAPI
187 CompositeMonikerImpl_IsDirty(IMoniker* iface)
189 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
190 method in the OLE-provided moniker interfaces always return S_FALSE because
191 their internal state never changes. */
193 TRACE("(%p)\n",iface);
195 return S_FALSE;
198 /******************************************************************************
199 * CompositeMoniker_Load
200 ******************************************************************************/
201 static HRESULT WINAPI
202 CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
204 HRESULT res;
205 DWORD constant;
206 CLSID clsid;
207 WCHAR string[1]={0};
209 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
211 TRACE("(%p,%p)\n",iface,pStm);
213 /* this function call OleLoadFromStream function for each moniker within this object */
215 /* read the a constant written by CompositeMonikerImpl_Save (see CompositeMonikerImpl_Save for more details)*/
216 res=IStream_Read(pStm,&constant,sizeof(DWORD),NULL);
218 if (SUCCEEDED(res)&& constant!=3)
219 return E_FAIL;
221 while(1){
222 #if 0
223 res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
224 #endif
225 res=ReadClassStm(pStm,&clsid);
226 DPRINTF("res=%ld",res);
227 if (FAILED(res))
228 break;
230 if (IsEqualIID(&clsid,&CLSID_FileMoniker)){
231 res=CreateFileMoniker(string,&This->tabMoniker[This->tabLastIndex]);
232 if (FAILED(res))
233 break;
234 res=IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
235 if (FAILED(res))
236 break;
238 else if (IsEqualIID(&clsid,&CLSID_ItemMoniker)){
239 CreateItemMoniker(string,string,&This->tabMoniker[This->tabLastIndex]);
240 if (res!=S_OK)
241 break;
242 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
243 if (FAILED(res))
244 break;
246 else if (IsEqualIID(&clsid,&CLSID_AntiMoniker)){
247 CreateAntiMoniker(&This->tabMoniker[This->tabLastIndex]);
248 if (FAILED(res))
249 break;
250 IMoniker_Load(This->tabMoniker[This->tabLastIndex],pStm);
251 if (FAILED(res))
252 break;
254 else if (IsEqualIID(&clsid,&CLSID_CompositeMoniker))
255 return E_FAIL;
257 else
259 FIXME("()\n");
260 /* FIXME: To whoever wrote this code: It's either return or break. it cannot be both! */
261 break;
262 return E_NOTIMPL;
265 /* resize the table if needed */
266 if (++This->tabLastIndex==This->tabSize){
268 This->tabSize+=BLOCK_TAB_SIZE;
269 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
271 if (This->tabMoniker==NULL)
272 return E_OUTOFMEMORY;
276 return res;
279 /******************************************************************************
280 * CompositeMoniker_Save
281 ******************************************************************************/
282 static HRESULT WINAPI
283 CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
285 HRESULT res;
286 IEnumMoniker *enumMk;
287 IMoniker *pmk;
288 DWORD constant=3;
290 TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
292 /* This function calls OleSaveToStream function for each moniker within
293 * this object.
294 * When I tested this function in windows, I usually found this constant
295 * at the beginning of the stream. I don't known why (there's no
296 * indication in the specification) !
298 res=IStream_Write(pStm,&constant,sizeof(constant),NULL);
300 IMoniker_Enum(iface,TRUE,&enumMk);
302 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
304 res=OleSaveToStream((IPersistStream*)pmk,pStm);
306 IMoniker_Release(pmk);
308 if (FAILED(res)){
310 IEnumMoniker_Release(pmk);
311 return res;
315 IEnumMoniker_Release(enumMk);
317 return S_OK;
320 /******************************************************************************
321 * CompositeMoniker_GetSizeMax
322 ******************************************************************************/
323 static HRESULT WINAPI
324 CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)
326 IEnumMoniker *enumMk;
327 IMoniker *pmk;
328 ULARGE_INTEGER ptmpSize;
330 /* The sizeMax of this object is calculated by calling GetSizeMax on
331 * each moniker within this object then summing all returned values
334 TRACE("(%p,%p)\n",iface,pcbSize);
336 if (!pcbSize)
337 return E_POINTER;
339 pcbSize->u.LowPart =0;
340 pcbSize->u.HighPart=0;
342 IMoniker_Enum(iface,TRUE,&enumMk);
344 while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)){
346 IMoniker_GetSizeMax(pmk,&ptmpSize);
348 IMoniker_Release(pmk);
350 pcbSize->u.LowPart +=ptmpSize.u.LowPart;
351 pcbSize->u.HighPart+=ptmpSize.u.HighPart;
354 IEnumMoniker_Release(enumMk);
356 return S_OK;
359 /******************************************************************************
360 * CompositeMoniker_BindToObject
361 ******************************************************************************/
362 static HRESULT WINAPI
363 CompositeMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc,
364 IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
366 HRESULT res;
367 IRunningObjectTable *prot;
368 IMoniker *tempMk,*antiMk,*mostRigthMk;
369 IEnumMoniker *enumMoniker;
371 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
373 if (ppvResult==NULL)
374 return E_POINTER;
376 *ppvResult=0;
377 /* If pmkToLeft is NULL, this method looks for the moniker in the ROT, and if found, queries the retrieved */
378 /* object for the requested interface pointer. */
379 if(pmkToLeft==NULL){
381 res=IBindCtx_GetRunningObjectTable(pbc,&prot);
383 if (SUCCEEDED(res)){
385 /* if the requested class was loaded before ! we don't need to reload it */
386 res = IRunningObjectTable_GetObject(prot,iface,(IUnknown**)ppvResult);
388 if (res==S_OK)
389 return res;
392 else{
393 /* If pmkToLeft is not NULL, the method recursively calls IMoniker::BindToObject on the rightmost */
394 /* component of the composite, passing the rest of the composite as the pmkToLeft parameter for that call */
396 IMoniker_Enum(iface,FALSE,&enumMoniker);
397 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
398 IEnumMoniker_Release(enumMoniker);
400 res=CreateAntiMoniker(&antiMk);
401 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
402 IMoniker_Release(antiMk);
404 res=CompositeMonikerImpl_BindToObject(mostRigthMk,pbc,tempMk,riid,ppvResult);
406 IMoniker_Release(tempMk);
407 IMoniker_Release(mostRigthMk);
410 return res;
413 /******************************************************************************
414 * CompositeMoniker_BindToStorage
415 ******************************************************************************/
416 static HRESULT WINAPI
417 CompositeMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc,
418 IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)
420 HRESULT res;
421 IMoniker *tempMk,*antiMk,*mostRigthMk;
422 IEnumMoniker *enumMoniker;
424 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
426 *ppvResult=0;
428 /* This method recursively calls BindToStorage on the rightmost component of the composite, */
429 /* passing the rest of the composite as the pmkToLeft parameter for that call. */
431 if (pmkToLeft!=NULL){
433 IMoniker_Enum(iface,FALSE,&enumMoniker);
434 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
435 IEnumMoniker_Release(enumMoniker);
437 res=CreateAntiMoniker(&antiMk);
438 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
439 IMoniker_Release(antiMk);
441 res=CompositeMonikerImpl_BindToStorage(mostRigthMk,pbc,tempMk,riid,ppvResult);
443 IMoniker_Release(tempMk);
445 IMoniker_Release(mostRigthMk);
447 return res;
449 else
450 return IMoniker_BindToStorage(iface,pbc,NULL,riid,ppvResult);
453 /******************************************************************************
454 * CompositeMoniker_Reduce
455 ******************************************************************************/
456 static HRESULT WINAPI
457 CompositeMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
458 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
460 HRESULT res;
461 IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;
462 IEnumMoniker *enumMoniker;
464 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
466 if (ppmkReduced==NULL)
467 return E_POINTER;
469 /* This method recursively calls Reduce for each of its component monikers. */
471 if (ppmkToLeft==NULL){
473 IMoniker_Enum(iface,FALSE,&enumMoniker);
474 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
475 IEnumMoniker_Release(enumMoniker);
477 res=CreateAntiMoniker(&antiMk);
478 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
479 IMoniker_Release(antiMk);
481 return CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk, ppmkReduced);
483 else if (*ppmkToLeft==NULL)
485 return IMoniker_Reduce(iface,pbc,dwReduceHowFar,NULL,ppmkReduced);
487 else{
489 /* separate the composite moniker in to left and right moniker */
490 IMoniker_Enum(iface,FALSE,&enumMoniker);
491 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
492 IEnumMoniker_Release(enumMoniker);
494 res=CreateAntiMoniker(&antiMk);
495 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
496 IMoniker_Release(antiMk);
498 /* If any of the components reduces itself, the method returns S_OK and passes back a composite */
499 /* of the reduced components */
500 if (IMoniker_Reduce(mostRigthMk,pbc,dwReduceHowFar,NULL,&mostRigthReducedMk) &&
501 CompositeMonikerImpl_Reduce(mostRigthMk,pbc,dwReduceHowFar,&tempMk,&leftReducedComposedMk)
504 return CreateGenericComposite(leftReducedComposedMk,mostRigthReducedMk,ppmkReduced);
506 else{
507 /* If no reduction occurred, the method passes back the same moniker and returns MK_S_REDUCED_TO_SELF.*/
509 IMoniker_AddRef(iface);
511 *ppmkReduced=iface;
513 return MK_S_REDUCED_TO_SELF;
518 /******************************************************************************
519 * CompositeMoniker_ComposeWith
520 ******************************************************************************/
521 static HRESULT WINAPI
522 CompositeMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
523 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
525 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
527 if ((ppmkComposite==NULL)||(pmkRight==NULL))
528 return E_POINTER;
530 *ppmkComposite=0;
532 /* If fOnlyIfNotGeneric is TRUE, this method sets *pmkComposite to NULL and returns MK_E_NEEDGENERIC; */
533 /* otherwise, the method returns the result of combining the two monikers by calling the */
534 /* CreateGenericComposite function */
536 if (fOnlyIfNotGeneric)
537 return MK_E_NEEDGENERIC;
539 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
542 /******************************************************************************
543 * CompositeMoniker_Enum
544 ******************************************************************************/
545 static HRESULT WINAPI
546 CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
548 CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;
550 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
552 if (ppenumMoniker == NULL)
553 return E_POINTER;
555 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
558 /******************************************************************************
559 * CompositeMoniker_IsEqual
560 ******************************************************************************/
561 static HRESULT WINAPI
562 CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
564 IEnumMoniker *enumMoniker1,*enumMoniker2;
565 IMoniker *tempMk1,*tempMk2;
566 HRESULT res1,res2,res;
568 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
570 if (pmkOtherMoniker==NULL)
571 return S_FALSE;
573 /* This method returns S_OK if the components of both monikers are equal when compared in the */
574 /* left-to-right order.*/
575 IMoniker_Enum(pmkOtherMoniker,TRUE,&enumMoniker1);
577 if (enumMoniker1==NULL)
578 return S_FALSE;
580 IMoniker_Enum(iface,TRUE,&enumMoniker2);
582 while(1){
584 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
585 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
587 if((res1==S_OK)&&(res2==S_OK)){
589 if(IMoniker_IsEqual(tempMk1,tempMk2)==S_FALSE){
590 res= S_FALSE;
591 break;
593 else
594 continue;
596 else if ( (res1==S_FALSE) && (res2==S_FALSE) ){
597 res = S_OK;
598 break;
600 else{
601 res = S_FALSE;
602 break;
605 if (res1==S_OK)
606 IMoniker_Release(tempMk1);
608 if (res2==S_OK)
609 IMoniker_Release(tempMk2);
612 IEnumMoniker_Release(enumMoniker1);
613 IEnumMoniker_Release(enumMoniker2);
615 return res;
617 /******************************************************************************
618 * CompositeMoniker_Hash
619 ******************************************************************************/
620 static HRESULT WINAPI
621 CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
623 IEnumMoniker *enumMoniker;
624 IMoniker *tempMk;
625 HRESULT res;
626 DWORD tempHash;
628 TRACE("(%p,%p)\n",iface,pdwHash);
630 if (pdwHash==NULL)
631 return E_POINTER;
633 res = IMoniker_Enum(iface,TRUE,&enumMoniker);
634 if(FAILED(res))
635 return res;
637 while(1){
638 res=IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL);
639 if(FAILED(res))
640 break;
642 res = IMoniker_Hash(tempMk, &tempHash);
643 if(FAILED(res))
644 break;
645 *pdwHash = (*pdwHash * 37) + tempHash;
647 IMoniker_Release(tempMk);
650 IEnumMoniker_Release(enumMoniker);
652 return res;
655 /******************************************************************************
656 * CompositeMoniker_IsRunning
657 ******************************************************************************/
658 static HRESULT WINAPI
659 CompositeMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc,
660 IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning)
662 IRunningObjectTable* rot;
663 HRESULT res;
664 IMoniker *tempMk,*antiMk,*mostRigthMk;
665 IEnumMoniker *enumMoniker;
667 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
669 /* If pmkToLeft is non-NULL, this method composes pmkToLeft with this moniker and calls IsRunning on the result.*/
670 if (pmkToLeft!=NULL){
672 CreateGenericComposite(pmkToLeft,iface,&tempMk);
674 res = IMoniker_IsRunning(tempMk,pbc,NULL,pmkNewlyRunning);
676 IMoniker_Release(tempMk);
678 return res;
680 else
681 /* If pmkToLeft is NULL, this method returns S_OK if pmkNewlyRunning is non-NULL and is equal */
682 /* to this moniker */
684 if (pmkNewlyRunning!=NULL)
686 if (IMoniker_IsEqual(iface,pmkNewlyRunning)==S_OK)
687 return S_OK;
689 else
690 return S_FALSE;
692 else{
694 if (pbc==NULL)
695 return E_POINTER;
697 /* If pmkToLeft and pmkNewlyRunning are both NULL, this method checks the ROT to see whether */
698 /* the moniker is running. If so, the method returns S_OK; otherwise, it recursively calls */
699 /* IMoniker::IsRunning on the rightmost component of the composite, passing the remainder of */
700 /* the composite as the pmkToLeft parameter for that call. */
702 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
704 if (FAILED(res))
705 return res;
707 res = IRunningObjectTable_IsRunning(rot,iface);
708 IRunningObjectTable_Release(rot);
710 if(res==S_OK)
711 return S_OK;
713 else{
715 IMoniker_Enum(iface,FALSE,&enumMoniker);
716 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
717 IEnumMoniker_Release(enumMoniker);
719 res=CreateAntiMoniker(&antiMk);
720 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
721 IMoniker_Release(antiMk);
723 res=IMoniker_IsRunning(mostRigthMk,pbc,tempMk,pmkNewlyRunning);
725 IMoniker_Release(tempMk);
726 IMoniker_Release(mostRigthMk);
728 return res;
733 /******************************************************************************
734 * CompositeMoniker_GetTimeOfLastChange
735 ******************************************************************************/
736 static HRESULT WINAPI
737 CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
738 IMoniker* pmkToLeft, FILETIME* pCompositeTime)
740 IRunningObjectTable* rot;
741 HRESULT res;
742 IMoniker *tempMk,*antiMk,*mostRigthMk;
743 IEnumMoniker *enumMoniker;
745 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pCompositeTime);
747 if (pCompositeTime==NULL)
748 return E_INVALIDARG;
750 /* This method creates a composite of pmkToLeft (if non-NULL) and this moniker and uses the ROT to */
751 /* retrieve the time of last change. If the object is not in the ROT, the method recursively calls */
752 /* IMoniker::GetTimeOfLastChange on the rightmost component of the composite, passing the remainder */
753 /* of the composite as the pmkToLeft parameter for that call. */
754 if (pmkToLeft!=NULL){
756 res=CreateGenericComposite(pmkToLeft,iface,&tempMk);
758 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
760 if (FAILED(res))
761 return res;
763 if (IRunningObjectTable_GetTimeOfLastChange(rot,tempMk,pCompositeTime)==S_OK)
764 return res;
765 else
767 IMoniker_Enum(iface,FALSE,&enumMoniker);
768 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
769 IEnumMoniker_Release(enumMoniker);
771 res=CreateAntiMoniker(&antiMk);
772 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
773 IMoniker_Release(antiMk);
775 res=CompositeMonikerImpl_GetTimeOfLastChange(mostRigthMk,pbc,tempMk,pCompositeTime);
777 IMoniker_Release(tempMk);
778 IMoniker_Release(mostRigthMk);
780 return res;
782 else
783 return IMoniker_GetTimeOfLastChange(iface,pbc,NULL,pCompositeTime);
786 /******************************************************************************
787 * CompositeMoniker_Inverse
788 ******************************************************************************/
789 static HRESULT WINAPI
790 CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
792 HRESULT res;
793 IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;
794 IEnumMoniker *enumMoniker;
796 TRACE("(%p,%p)\n",iface,ppmk);
798 if (ppmk==NULL)
799 return E_POINTER;
801 /* This method returns a composite moniker that consists of the inverses of each of the components */
802 /* of the original composite, stored in reverse order */
804 res=CreateAntiMoniker(&antiMk);
805 res=IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
806 IMoniker_Release(antiMk);
808 if (tempMk==NULL)
810 return IMoniker_Inverse(iface,ppmk);
812 else{
814 IMoniker_Enum(iface,FALSE,&enumMoniker);
815 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
816 IEnumMoniker_Release(enumMoniker);
818 IMoniker_Inverse(mostRigthMk,&mostRigthInvMk);
819 CompositeMonikerImpl_Inverse(tempMk,&tempInvMk);
821 res=CreateGenericComposite(mostRigthInvMk,tempInvMk,ppmk);
823 IMoniker_Release(tempMk);
824 IMoniker_Release(mostRigthMk);
825 IMoniker_Release(tempInvMk);
826 IMoniker_Release(mostRigthInvMk);
828 return res;
832 /******************************************************************************
833 * CompositeMoniker_CommonPrefixWith
834 ******************************************************************************/
835 static HRESULT WINAPI
836 CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface, IMoniker* pmkOther,
837 IMoniker** ppmkPrefix)
839 DWORD mkSys;
840 HRESULT res1,res2;
841 IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
842 IEnumMoniker *enumMoniker1,*enumMoniker2;
843 ULONG i,nbCommonMk=0;
845 /* If the other moniker is a composite, this method compares the components of each composite from left */
846 /* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
847 /* of the leftmost components were common to both monikers. */
849 if (ppmkPrefix==NULL)
850 return E_POINTER;
852 *ppmkPrefix=0;
854 if (pmkOther==NULL)
855 return MK_E_NOPREFIX;
857 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
859 if((mkSys==MKSYS_GENERICCOMPOSITE)){
861 IMoniker_Enum(iface,TRUE,&enumMoniker1);
862 IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
864 while(1){
866 res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
867 res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
869 if ((res1==S_FALSE) && (res2==S_FALSE)){
871 /* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
872 *ppmkPrefix=iface;
873 IMoniker_AddRef(iface);
874 return MK_S_US;
876 else if ((res1==S_OK) && (res2==S_OK)){
878 if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
880 nbCommonMk++;
882 else
883 break;
886 else if (res1==S_OK){
888 /* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
889 /* ppmkPrefix to the other moniker. */
890 *ppmkPrefix=pmkOther;
891 return MK_S_HIM;
893 else{
894 /* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
895 /* to this moniker. */
896 *ppmkPrefix=iface;
897 return MK_S_ME;
901 IEnumMoniker_Release(enumMoniker1);
902 IEnumMoniker_Release(enumMoniker2);
904 /* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
905 if (nbCommonMk==0)
906 return MK_E_NOPREFIX;
908 IEnumMoniker_Reset(enumMoniker1);
910 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
912 /* if we have more than one commun moniker the result will be a composite moniker */
913 if (nbCommonMk>1){
915 /* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
916 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
917 CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
918 IMoniker_Release(tempMk1);
919 IMoniker_Release(tempMk2);
921 /* compose all common monikers in a composite moniker */
922 for(i=0;i<nbCommonMk;i++){
924 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
926 CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
928 IMoniker_Release(*ppmkPrefix);
930 IMoniker_Release(tempMk1);
932 *ppmkPrefix=tempMk2;
934 return S_OK;
936 else{
937 /* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
938 *ppmkPrefix=tempMk1;
940 return S_OK;
943 else{
944 /* If the other moniker is not a composite, the method simply compares it to the leftmost component
945 of this moniker.*/
947 IMoniker_Enum(iface,TRUE,&enumMoniker1);
949 IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
951 if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
953 *ppmkPrefix=pmkOther;
955 return MK_S_HIM;
957 else
958 return MK_E_NOPREFIX;
962 /***************************************************************************************************
963 * GetAfterCommonPrefix (local function)
964 * This function returns a moniker that consist of the remainder when the common prefix is removed
965 ***************************************************************************************************/
966 static VOID GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
968 IMoniker *tempMk,*tempMk1,*tempMk2;
969 IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
970 ULONG nbRestMk=0;
971 DWORD mkSys;
972 HRESULT res1,res2;
974 *restMk=0;
976 /* to create an enumerator for pGenMk with current position pointed on the first element after common */
977 /* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
978 /* on the first difference. */
979 IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
981 IMoniker_IsSystemMoniker(commonMk,&mkSys);
983 if (mkSys==MKSYS_GENERICCOMPOSITE){
985 IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
986 while(1){
988 res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
989 res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
991 if ((res1==S_FALSE)||(res2==S_FALSE)){
993 if (res1==S_OK)
995 nbRestMk++;
997 IMoniker_Release(tempMk1);
998 IMoniker_Release(tempMk1);
1000 break;
1002 IMoniker_Release(tempMk1);
1003 IMoniker_Release(tempMk1);
1006 else{
1007 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1008 IMoniker_Release(tempMk1);
1011 /* count the number of elements in the enumerator after the common prefix */
1012 IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
1014 for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
1016 IMoniker_Release(tempMk);
1018 if (nbRestMk==0)
1019 return;
1021 /* create a generic composite moniker with monikers located after the common prefix */
1022 IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
1024 if (nbRestMk==1){
1026 *restMk= tempMk1;
1027 return;
1029 else {
1031 IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
1033 CreateGenericComposite(tempMk1,tempMk2,restMk);
1035 IMoniker_Release(tempMk1);
1037 IMoniker_Release(tempMk2);
1039 while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
1041 CreateGenericComposite(*restMk,tempMk1,&tempMk2);
1043 IMoniker_Release(tempMk1);
1045 IMoniker_Release(*restMk);
1047 *restMk=tempMk2;
1052 /******************************************************************************
1053 * CompositeMoniker_RelativePathTo
1054 ******************************************************************************/
1055 static HRESULT WINAPI
1056 CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther,
1057 IMoniker** ppmkRelPath)
1059 HRESULT res;
1060 IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
1062 TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
1064 if (ppmkRelPath==NULL)
1065 return E_POINTER;
1067 *ppmkRelPath=0;
1069 /* This method finds the common prefix of the two monikers and creates two monikers that consist */
1070 /* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
1071 /* of this moniker and composes the remainder of the other moniker on the right of it. */
1073 /* finds the common prefix of the two monikers */
1074 res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
1076 /* if there's no common prefix or the two moniker are equal the relative is the other moniker */
1077 if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
1079 *ppmkRelPath=pmkOther;
1080 IMoniker_AddRef(pmkOther);
1081 return MK_S_HIM;
1084 GetAfterCommonPrefix(iface,commonMk,&restThisMk);
1085 GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
1087 /* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
1088 /* moniker when the common prefix is removed */
1089 if (res==MK_S_HIM){
1091 IMoniker_Inverse(restThisMk,ppmkRelPath);
1092 IMoniker_Release(restThisMk);
1094 /* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
1095 /* when the common prefix is removed */
1096 else if (res==MK_S_ME){
1098 *ppmkRelPath=restOtherMk;
1099 IMoniker_AddRef(restOtherMk);
1101 /* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
1102 /* moniker on the right of it. */
1103 else if (res==S_OK){
1105 IMoniker_Inverse(restThisMk,&invRestThisMk);
1106 IMoniker_Release(restThisMk);
1107 CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
1108 IMoniker_Release(invRestThisMk);
1109 IMoniker_Release(restOtherMk);
1111 return S_OK;
1114 /******************************************************************************
1115 * CompositeMoniker_GetDisplayName
1116 ******************************************************************************/
1117 static HRESULT WINAPI
1118 CompositeMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
1119 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
1121 ULONG lengthStr=1;
1122 IEnumMoniker *enumMoniker;
1123 IMoniker* tempMk;
1124 LPOLESTR tempStr;
1126 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
1128 if (ppszDisplayName==NULL)
1129 return E_POINTER;
1131 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
1133 if (*ppszDisplayName==NULL)
1134 return E_OUTOFMEMORY;
1136 /* This method returns the concatenation of the display names returned by each component moniker of */
1137 /* the composite */
1139 **ppszDisplayName=0;
1141 IMoniker_Enum(iface,TRUE,&enumMoniker);
1143 while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
1145 IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
1147 lengthStr+=lstrlenW(tempStr);
1149 *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
1151 if (*ppszDisplayName==NULL)
1152 return E_OUTOFMEMORY;
1154 strcatW(*ppszDisplayName,tempStr);
1156 CoTaskMemFree(tempStr);
1157 IMoniker_Release(tempMk);
1160 IEnumMoniker_Release(enumMoniker);
1162 return S_OK;
1165 /******************************************************************************
1166 * CompositeMoniker_ParseDisplayName
1167 ******************************************************************************/
1168 static HRESULT WINAPI
1169 CompositeMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
1170 IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten,
1171 IMoniker** ppmkOut)
1173 IEnumMoniker *enumMoniker;
1174 IMoniker *tempMk,*mostRigthMk,*antiMk;
1175 /* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
1176 /* passing everything else as the pmkToLeft parameter for that call. */
1178 /* get the most right moniker */
1179 IMoniker_Enum(iface,FALSE,&enumMoniker);
1180 IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
1181 IEnumMoniker_Release(enumMoniker);
1183 /* get the left moniker */
1184 CreateAntiMoniker(&antiMk);
1185 IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
1186 IMoniker_Release(antiMk);
1188 return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
1191 /******************************************************************************
1192 * CompositeMoniker_IsSystemMoniker
1193 ******************************************************************************/
1194 static HRESULT WINAPI
1195 CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
1197 TRACE("(%p,%p)\n",iface,pwdMksys);
1199 if (!pwdMksys)
1200 return E_POINTER;
1202 (*pwdMksys)=MKSYS_GENERICCOMPOSITE;
1204 return S_OK;
1207 /*******************************************************************************
1208 * CompositeMonikerIROTData_QueryInterface
1209 *******************************************************************************/
1210 static HRESULT WINAPI
1211 CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
1212 VOID** ppvObject)
1215 IMoniker *This = impl_from_IROTData(iface);
1217 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
1219 return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
1222 /***********************************************************************
1223 * CompositeMonikerIROTData_AddRef
1225 static ULONG WINAPI
1226 CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
1228 IMoniker *This = impl_from_IROTData(iface);
1230 TRACE("(%p)\n",iface);
1232 return IMoniker_AddRef(This);
1235 /***********************************************************************
1236 * CompositeMonikerIROTData_Release
1238 static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
1240 IMoniker *This = impl_from_IROTData(iface);
1242 TRACE("(%p)\n",iface);
1244 return IMoniker_Release(This);
1247 /******************************************************************************
1248 * CompositeMonikerIROTData_GetComparaisonData
1249 ******************************************************************************/
1250 static HRESULT WINAPI
1251 CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
1252 BYTE* pbData, ULONG cbMax, ULONG* pcbData)
1254 FIXME("(),stub!\n");
1255 return E_NOTIMPL;
1258 /******************************************************************************
1259 * EnumMonikerImpl_QueryInterface
1260 ******************************************************************************/
1261 static HRESULT WINAPI
1262 EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)
1264 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1266 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
1268 /* Perform a sanity check on the parameters.*/
1269 if ( (This==0) || (ppvObject==0) )
1270 return E_INVALIDARG;
1272 /* Initialize the return parameter */
1273 *ppvObject = 0;
1275 /* Compare the riid with the interface IDs implemented by this object.*/
1276 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IEnumMoniker, riid))
1277 *ppvObject = iface;
1279 /* Check that we obtained an interface.*/
1280 if ((*ppvObject)==0)
1281 return E_NOINTERFACE;
1283 /* Query Interface always increases the reference count by one when it is successful */
1284 IEnumMoniker_AddRef(iface);
1286 return S_OK;
1289 /******************************************************************************
1290 * EnumMonikerImpl_AddRef
1291 ******************************************************************************/
1292 static ULONG WINAPI
1293 EnumMonikerImpl_AddRef(IEnumMoniker* iface)
1295 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1297 TRACE("(%p)\n",This);
1299 return InterlockedIncrement(&This->ref);
1303 /******************************************************************************
1304 * EnumMonikerImpl_Release
1305 ******************************************************************************/
1306 static ULONG WINAPI
1307 EnumMonikerImpl_Release(IEnumMoniker* iface)
1309 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1310 ULONG i;
1311 ULONG ref;
1312 TRACE("(%p)\n",This);
1314 ref = InterlockedDecrement(&This->ref);
1316 /* destroy the object if there's no more reference on it */
1317 if (ref == 0) {
1319 for(i=0;i<This->tabSize;i++)
1320 IMoniker_Release(This->tabMoniker[i]);
1322 HeapFree(GetProcessHeap(),0,This->tabMoniker);
1323 HeapFree(GetProcessHeap(),0,This);
1325 return ref;
1328 /******************************************************************************
1329 * EnumMonikerImpl_Next
1330 ******************************************************************************/
1331 static HRESULT WINAPI
1332 EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt,
1333 ULONG* pceltFethed)
1335 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1336 ULONG i;
1338 /* retrieve the requested number of moniker from the current position */
1339 for(i=0;((This->currentPos < This->tabSize) && (i < celt));i++)
1341 rgelt[i]=This->tabMoniker[This->currentPos++];
1343 if (pceltFethed!=NULL)
1344 *pceltFethed= i;
1346 if (i==celt)
1347 return S_OK;
1348 else
1349 return S_FALSE;
1352 /******************************************************************************
1353 * EnumMonikerImpl_Skip
1354 ******************************************************************************/
1355 static HRESULT WINAPI
1356 EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt)
1358 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1360 if ((This->currentPos+celt) >= This->tabSize)
1361 return S_FALSE;
1363 This->currentPos+=celt;
1365 return S_OK;
1368 /******************************************************************************
1369 * EnumMonikerImpl_Reset
1370 ******************************************************************************/
1371 static HRESULT WINAPI
1372 EnumMonikerImpl_Reset(IEnumMoniker* iface)
1375 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1377 This->currentPos=0;
1379 return S_OK;
1382 /******************************************************************************
1383 * EnumMonikerImpl_Clone
1384 ******************************************************************************/
1385 static HRESULT WINAPI
1386 EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum)
1388 EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
1390 return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
1393 /********************************************************************************/
1394 /* Virtual function table for the IROTData class */
1395 static const IEnumMonikerVtbl VT_EnumMonikerImpl =
1397 EnumMonikerImpl_QueryInterface,
1398 EnumMonikerImpl_AddRef,
1399 EnumMonikerImpl_Release,
1400 EnumMonikerImpl_Next,
1401 EnumMonikerImpl_Skip,
1402 EnumMonikerImpl_Reset,
1403 EnumMonikerImpl_Clone
1406 /******************************************************************************
1407 * EnumMonikerImpl_CreateEnumMoniker
1408 ******************************************************************************/
1409 static HRESULT
1410 EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, ULONG tabSize,
1411 ULONG currentPos, BOOL leftToRigth, IEnumMoniker ** ppmk)
1413 EnumMonikerImpl* newEnumMoniker;
1414 int i;
1416 if (currentPos > tabSize)
1417 return E_INVALIDARG;
1419 newEnumMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(EnumMonikerImpl));
1421 if (newEnumMoniker == 0)
1422 return STG_E_INSUFFICIENTMEMORY;
1424 /* Initialize the virtual function table. */
1425 newEnumMoniker->lpVtbl = &VT_EnumMonikerImpl;
1426 newEnumMoniker->ref = 0;
1428 newEnumMoniker->tabSize=tabSize;
1429 newEnumMoniker->currentPos=currentPos;
1431 newEnumMoniker->tabMoniker=HeapAlloc(GetProcessHeap(),0,tabSize*sizeof(IMoniker));
1433 if (newEnumMoniker->tabMoniker==NULL) {
1434 HeapFree(GetProcessHeap(), 0, newEnumMoniker);
1435 return E_OUTOFMEMORY;
1438 if (leftToRigth)
1439 for (i=0;i<tabSize;i++){
1441 newEnumMoniker->tabMoniker[i]=tabMoniker[i];
1442 IMoniker_AddRef(tabMoniker[i]);
1444 else
1445 for (i=tabSize-1;i>=0;i--){
1447 newEnumMoniker->tabMoniker[tabSize-i-1]=tabMoniker[i];
1448 IMoniker_AddRef(tabMoniker[i]);
1451 *ppmk=(IEnumMoniker*)newEnumMoniker;
1453 return S_OK;
1456 /********************************************************************************/
1457 /* Virtual function table for the CompositeMonikerImpl class which includes */
1458 /* IPersist, IPersistStream and IMoniker functions. */
1460 static const IMonikerVtbl VT_CompositeMonikerImpl =
1462 CompositeMonikerImpl_QueryInterface,
1463 CompositeMonikerImpl_AddRef,
1464 CompositeMonikerImpl_Release,
1465 CompositeMonikerImpl_GetClassID,
1466 CompositeMonikerImpl_IsDirty,
1467 CompositeMonikerImpl_Load,
1468 CompositeMonikerImpl_Save,
1469 CompositeMonikerImpl_GetSizeMax,
1470 CompositeMonikerImpl_BindToObject,
1471 CompositeMonikerImpl_BindToStorage,
1472 CompositeMonikerImpl_Reduce,
1473 CompositeMonikerImpl_ComposeWith,
1474 CompositeMonikerImpl_Enum,
1475 CompositeMonikerImpl_IsEqual,
1476 CompositeMonikerImpl_Hash,
1477 CompositeMonikerImpl_IsRunning,
1478 CompositeMonikerImpl_GetTimeOfLastChange,
1479 CompositeMonikerImpl_Inverse,
1480 CompositeMonikerImpl_CommonPrefixWith,
1481 CompositeMonikerImpl_RelativePathTo,
1482 CompositeMonikerImpl_GetDisplayName,
1483 CompositeMonikerImpl_ParseDisplayName,
1484 CompositeMonikerImpl_IsSystemMoniker
1487 /********************************************************************************/
1488 /* Virtual function table for the IROTData class. */
1489 static const IROTDataVtbl VT_ROTDataImpl =
1491 CompositeMonikerROTDataImpl_QueryInterface,
1492 CompositeMonikerROTDataImpl_AddRef,
1493 CompositeMonikerROTDataImpl_Release,
1494 CompositeMonikerROTDataImpl_GetComparaisonData
1497 /******************************************************************************
1498 * Composite-Moniker_Construct (local function)
1499 *******************************************************************************/
1500 static HRESULT
1501 CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,
1502 LPMONIKER pmkFirst, LPMONIKER pmkRest)
1504 DWORD mkSys;
1505 IEnumMoniker *enumMoniker;
1506 IMoniker *tempMk;
1507 HRESULT res;
1509 TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
1511 /* Initialize the virtual function table. */
1512 This->lpvtbl1 = &VT_CompositeMonikerImpl;
1513 This->lpvtbl2 = &VT_ROTDataImpl;
1514 This->ref = 0;
1516 This->tabSize=BLOCK_TAB_SIZE;
1517 This->tabLastIndex=0;
1519 This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));
1520 if (This->tabMoniker==NULL)
1521 return E_OUTOFMEMORY;
1523 IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
1525 /* put the first moniker contents in the beginning of the table */
1526 if (mkSys!=MKSYS_GENERICCOMPOSITE){
1528 This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
1529 IMoniker_AddRef(pmkFirst);
1531 else{
1533 IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
1535 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
1538 if (++This->tabLastIndex==This->tabSize){
1540 This->tabSize+=BLOCK_TAB_SIZE;
1541 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1543 if (This->tabMoniker==NULL)
1544 return E_OUTOFMEMORY;
1548 IEnumMoniker_Release(enumMoniker);
1551 /* put the rest moniker contents after the first one and make simplification if needed */
1553 IMoniker_IsSystemMoniker(pmkRest,&mkSys);
1555 if (mkSys!=MKSYS_GENERICCOMPOSITE){
1557 /* add a simple moniker to the moniker table */
1559 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
1561 if (res==MK_E_NEEDGENERIC){
1563 /* there's no simplification in this case */
1564 This->tabMoniker[This->tabLastIndex]=pmkRest;
1566 This->tabLastIndex++;
1568 IMoniker_AddRef(pmkRest);
1570 else if (tempMk==NULL){
1572 /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
1573 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1575 This->tabLastIndex--;
1577 else if (SUCCEEDED(res)){
1579 /* the non-generic composition was successful so we can make a simplification in this case */
1580 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1582 This->tabMoniker[This->tabLastIndex-1]=tempMk;
1583 } else
1584 return res;
1586 /* resize tabMoniker if needed */
1587 if (This->tabLastIndex==This->tabSize){
1589 This->tabSize+=BLOCK_TAB_SIZE;
1591 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1593 if (This->tabMoniker==NULL)
1594 return E_OUTOFMEMORY;
1597 else{
1599 /* add a composite moniker to the moniker table (do the same thing
1600 * for each moniker within the composite moniker as a simple moniker
1601 * (see above for how to add a simple moniker case) )
1603 IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
1605 while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
1607 res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
1609 if (res==MK_E_NEEDGENERIC){
1611 This->tabLastIndex++;
1613 else if (tempMk==NULL){
1615 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1616 IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
1617 This->tabLastIndex--;
1619 else{
1621 IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
1623 This->tabMoniker[This->tabLastIndex-1]=tempMk;
1626 if (This->tabLastIndex==This->tabSize){
1628 This->tabSize+=BLOCK_TAB_SIZE;
1630 This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
1632 if (This->tabMoniker==NULL)
1633 return E_OUTOFMEMORY;
1637 IEnumMoniker_Release(enumMoniker);
1640 return S_OK;
1643 /******************************************************************************
1644 * CreateGenericComposite [OLE32.@]
1645 ******************************************************************************/
1646 HRESULT WINAPI
1647 CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest,
1648 LPMONIKER* ppmkComposite)
1650 CompositeMonikerImpl* newCompositeMoniker = 0;
1651 HRESULT hr = S_OK;
1653 TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
1655 if (ppmkComposite==NULL)
1656 return E_POINTER;
1658 *ppmkComposite=0;
1660 if (pmkFirst==NULL && pmkRest!=NULL){
1662 *ppmkComposite=pmkRest;
1663 return S_OK;
1665 else if (pmkFirst!=NULL && pmkRest==NULL){
1666 *ppmkComposite=pmkFirst;
1667 return S_OK;
1669 else if (pmkFirst==NULL && pmkRest==NULL)
1670 return S_OK;
1672 newCompositeMoniker = HeapAlloc(GetProcessHeap(), 0,sizeof(CompositeMonikerImpl));
1674 if (newCompositeMoniker == 0)
1675 return STG_E_INSUFFICIENTMEMORY;
1677 hr = CompositeMonikerImpl_Construct(newCompositeMoniker,pmkFirst,pmkRest);
1679 if (FAILED(hr)){
1681 HeapFree(GetProcessHeap(),0,newCompositeMoniker);
1682 return hr;
1684 if (newCompositeMoniker->tabLastIndex==1)
1686 hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);
1687 else
1689 hr = IMoniker_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);
1691 return hr;
1694 /******************************************************************************
1695 * MonikerCommonPrefixWith [OLE32.@]
1696 ******************************************************************************/
1697 HRESULT WINAPI
1698 MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)
1700 FIXME("(),stub!\n");
1701 return E_NOTIMPL;