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

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

Wine 20020215 resync

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