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

Last change on this file since 6648 was 6648, checked in by bird, 24 years ago

Added $Id:$ keyword.

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