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

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

Added $Id:$ keyword.

File size: 34.5 KB
Line 
1/* $Id: itemmoniker.c,v 1.2 2001-09-05 13:17:10 bird Exp $ */
2/***************************************************************************************
3 * ItemMonikers implementation
4 *
5 * Copyright 1999 Noomen Hamza
6 ***************************************************************************************/
7
8#include <assert.h>
9#include <string.h>
10#include "winerror.h"
11#include "winbase.h"
12#include "winnls.h"
13#include "debugtools.h"
14#include "wine/obj_base.h"
15#include "wine/obj_misc.h"
16#include "wine/obj_storage.h"
17#include "wine/obj_moniker.h"
18#include "wine/obj_inplace.h"
19#include "wine/unicode.h"
20
21DEFAULT_DEBUG_CHANNEL(ole);
22
23/* ItemMoniker data structure */
24typedef struct ItemMonikerImpl{
25
26 ICOM_VTABLE(IMoniker)* lpvtbl1; /* VTable relative to the IMoniker interface.*/
27
28 /* The ROT (RunningObjectTable implementation) uses the IROTData interface to test whether
29 * two monikers are equal. That's whay IROTData interface is implemented by monikers.
30 */
31 ICOM_VTABLE(IROTData)* lpvtbl2; /* VTable relative to the IROTData interface.*/
32
33 ULONG ref; /* reference counter for this object */
34
35 LPOLESTR itemName; /* item name identified by this ItemMoniker */
36
37 LPOLESTR itemDelimiter; /* Delimiter string */
38
39} ItemMonikerImpl;
40
41/********************************************************************************/
42/* ItemMoniker prototype functions : */
43
44/* IUnknown prototype functions */
45static HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);
46static ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface);
47static ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface);
48
49/* IPersist prototype functions */
50static HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);
51
52/* IPersistStream prototype functions */
53static HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface);
54static HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface, IStream* pStm);
55static HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);
56static HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);
57
58/* IMoniker prototype functions */
59static HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
60static HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);
61static HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);
62static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);
63static HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);
64static HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);
65static HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);
66static HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);
67static HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pItemTime);
68static HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);
69static HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);
70static HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);
71static HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);
72static HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);
73static HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);
74
75/* Local function used by ItemMoniker implementation */
76HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* iface, LPCOLESTR lpszDelim,LPCOLESTR lpszPathName);
77HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* iface);
78
79/********************************************************************************/
80/* IROTData prototype functions */
81
82/* IUnknown prototype functions */
83static HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);
84static ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData* iface);
85static ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface);
86
87/* IROTData prototype function */
88static HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);
89
90/********************************************************************************/
91/* Virtual function table for the ItemMonikerImpl class which include IPersist,*/
92/* IPersistStream and IMoniker functions. */
93static ICOM_VTABLE(IMoniker) VT_ItemMonikerImpl =
94 {
95 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
96 ItemMonikerImpl_QueryInterface,
97 ItemMonikerImpl_AddRef,
98 ItemMonikerImpl_Release,
99 ItemMonikerImpl_GetClassID,
100 ItemMonikerImpl_IsDirty,
101 ItemMonikerImpl_Load,
102 ItemMonikerImpl_Save,
103 ItemMonikerImpl_GetSizeMax,
104 ItemMonikerImpl_BindToObject,
105 ItemMonikerImpl_BindToStorage,
106 ItemMonikerImpl_Reduce,
107 ItemMonikerImpl_ComposeWith,
108 ItemMonikerImpl_Enum,
109 ItemMonikerImpl_IsEqual,
110 ItemMonikerImpl_Hash,
111 ItemMonikerImpl_IsRunning,
112 ItemMonikerImpl_GetTimeOfLastChange,
113 ItemMonikerImpl_Inverse,
114 ItemMonikerImpl_CommonPrefixWith,
115 ItemMonikerImpl_RelativePathTo,
116 ItemMonikerImpl_GetDisplayName,
117 ItemMonikerImpl_ParseDisplayName,
118 ItemMonikerImpl_IsSystemMoniker
119};
120
121/********************************************************************************/
122/* Virtual function table for the IROTData class. */
123static ICOM_VTABLE(IROTData) VT_ROTDataImpl =
124{
125 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
126 ItemMonikerROTDataImpl_QueryInterface,
127 ItemMonikerROTDataImpl_AddRef,
128 ItemMonikerROTDataImpl_Release,
129 ItemMonikerROTDataImpl_GetComparaisonData
130};
131
132/*******************************************************************************
133 * ItemMoniker_QueryInterface
134 *******************************************************************************/
135HRESULT WINAPI ItemMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
136{
137 ICOM_THIS(ItemMonikerImpl,iface);
138
139 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
140
141 /* Perform a sanity check on the parameters.*/
142 if ( (This==0) || (ppvObject==0) )
143 return E_INVALIDARG;
144
145 /* Initialize the return parameter */
146 *ppvObject = 0;
147
148 /* Compare the riid with the interface IDs implemented by this object.*/
149 if (IsEqualIID(&IID_IUnknown, riid) ||
150 IsEqualIID(&IID_IPersist, riid) ||
151 IsEqualIID(&IID_IPersistStream, riid) ||
152 IsEqualIID(&IID_IMoniker, riid)
153 )
154 *ppvObject = iface;
155
156 else if (IsEqualIID(&IID_IROTData, riid))
157 *ppvObject = (IROTData*)&(This->lpvtbl2);
158
159 /* Check that we obtained an interface.*/
160 if ((*ppvObject)==0)
161 return E_NOINTERFACE;
162
163 /* Query Interface always increases the reference count by one when it is successful */
164 ItemMonikerImpl_AddRef(iface);
165
166 return S_OK;
167}
168
169/******************************************************************************
170 * ItemMoniker_AddRef
171 ******************************************************************************/
172ULONG WINAPI ItemMonikerImpl_AddRef(IMoniker* iface)
173{
174 ICOM_THIS(ItemMonikerImpl,iface);
175
176 TRACE("(%p)\n",This);
177
178 return ++(This->ref);
179}
180
181/******************************************************************************
182 * ItemMoniker_Release
183 ******************************************************************************/
184ULONG WINAPI ItemMonikerImpl_Release(IMoniker* iface)
185{
186 ICOM_THIS(ItemMonikerImpl,iface);
187
188 TRACE("(%p)\n",This);
189
190 This->ref--;
191
192 /* destroy the object if there's no more reference on it */
193 if (This->ref==0){
194
195 ItemMonikerImpl_Destroy(This);
196
197 return 0;
198 }
199 return This->ref;;
200}
201
202/******************************************************************************
203 * ItemMoniker_GetClassID
204 ******************************************************************************/
205HRESULT WINAPI ItemMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
206{
207 TRACE("(%p,%p),stub!\n",iface,pClassID);
208
209 if (pClassID==NULL)
210 return E_POINTER;
211
212 *pClassID = CLSID_ItemMoniker;
213
214 return S_OK;
215}
216
217/******************************************************************************
218 * ItemMoniker_IsDirty
219 ******************************************************************************/
220HRESULT WINAPI ItemMonikerImpl_IsDirty(IMoniker* iface)
221{
222 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
223 method in the OLE-provided moniker interfaces always return S_FALSE because
224 their internal state never changes. */
225
226 TRACE("(%p)\n",iface);
227
228 return S_FALSE;
229}
230
231/******************************************************************************
232 * ItemMoniker_Load
233 ******************************************************************************/
234HRESULT WINAPI ItemMonikerImpl_Load(IMoniker* iface,IStream* pStm)
235{
236
237 ICOM_THIS(ItemMonikerImpl,iface);
238 HRESULT res;
239 DWORD delimiterLength,nameLength,lenW;
240 CHAR *itemNameA,*itemDelimiterA;
241 ULONG bread;
242
243 /* for more details about data read by this function see coments of ItemMonikerImpl_Save function */
244
245 /* read item delimiter string length + 1 */
246 res=IStream_Read(pStm,&delimiterLength,sizeof(DWORD),&bread);
247 if (bread != sizeof(DWORD))
248 return E_FAIL;
249
250 /* read item delimiter string */
251 if (!(itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength)))
252 return E_OUTOFMEMORY;
253 res=IStream_Read(pStm,itemDelimiterA,delimiterLength,&bread);
254 if (bread != delimiterLength)
255 {
256 HeapFree( GetProcessHeap(), 0, itemDelimiterA );
257 return E_FAIL;
258 }
259
260 lenW = MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, NULL, 0 );
261 This->itemDelimiter=HeapReAlloc(GetProcessHeap(),0,This->itemDelimiter,lenW*sizeof(WCHAR));
262 if (!This->itemDelimiter)
263 {
264 HeapFree( GetProcessHeap(), 0, itemDelimiterA );
265 return E_OUTOFMEMORY;
266 }
267 MultiByteToWideChar( CP_ACP, 0, itemDelimiterA, -1, This->itemDelimiter, lenW );
268 HeapFree( GetProcessHeap(), 0, itemDelimiterA );
269
270 /* read item name string length + 1*/
271 res=IStream_Read(pStm,&nameLength,sizeof(DWORD),&bread);
272 if (bread != sizeof(DWORD))
273 return E_FAIL;
274
275 /* read item name string */
276 if (!(itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength)))
277 return E_OUTOFMEMORY;
278 res=IStream_Read(pStm,itemNameA,nameLength,&bread);
279 if (bread != nameLength)
280 {
281 HeapFree( GetProcessHeap(), 0, itemNameA );
282 return E_FAIL;
283 }
284
285 lenW = MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, NULL, 0 );
286 This->itemName=HeapReAlloc(GetProcessHeap(),0,This->itemName,lenW*sizeof(WCHAR));
287 if (!This->itemName)
288 {
289 HeapFree( GetProcessHeap(), 0, itemNameA );
290 return E_OUTOFMEMORY;
291 }
292 MultiByteToWideChar( CP_ACP, 0, itemNameA, -1, This->itemName, lenW );
293 HeapFree( GetProcessHeap(), 0, itemNameA );
294
295 return res;
296}
297
298/******************************************************************************
299 * ItemMoniker_Save
300 ******************************************************************************/
301HRESULT WINAPI ItemMonikerImpl_Save(IMoniker* iface,
302 IStream* pStm,/* pointer to the stream where the object is to be saved */
303 BOOL fClearDirty)/* Specifies whether to clear the dirty flag */
304{
305 ICOM_THIS(ItemMonikerImpl,iface);
306 HRESULT res;
307 CHAR *itemNameA,*itemDelimiterA;
308
309 /* data writen by this function are : 1) DWORD : size of item delimiter string ('\0' included ) */
310 /* 2) String (type A): item delimiter string ('\0' included) */
311 /* 3) DWORD : size of item name string ('\0' included) */
312 /* 4) String (type A): item name string ('\0' included) */
313
314 DWORD nameLength = WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, NULL, 0, NULL, NULL);
315 DWORD delimiterLength = WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, NULL, 0, NULL, NULL);
316 itemNameA=HeapAlloc(GetProcessHeap(),0,nameLength);
317 itemDelimiterA=HeapAlloc(GetProcessHeap(),0,delimiterLength);
318 WideCharToMultiByte( CP_ACP, 0, This->itemName, -1, itemNameA, nameLength, NULL, NULL);
319 WideCharToMultiByte( CP_ACP, 0, This->itemDelimiter, -1, itemDelimiterA, delimiterLength, NULL, NULL);
320
321 res=IStream_Write(pStm,&delimiterLength,sizeof(DWORD),NULL);
322 res=IStream_Write(pStm,itemDelimiterA,delimiterLength * sizeof(CHAR),NULL);
323 res=IStream_Write(pStm,&nameLength,sizeof(DWORD),NULL);
324 res=IStream_Write(pStm,itemNameA,nameLength * sizeof(CHAR),NULL);
325
326 return res;
327}
328
329/******************************************************************************
330 * ItemMoniker_GetSizeMax
331 ******************************************************************************/
332HRESULT WINAPI ItemMonikerImpl_GetSizeMax(IMoniker* iface,
333 ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */
334{
335 ICOM_THIS(ItemMonikerImpl,iface);
336 DWORD delimiterLength=lstrlenW(This->itemDelimiter)+1;
337 DWORD nameLength=lstrlenW(This->itemName)+1;
338
339 TRACE("(%p,%p)\n",iface,pcbSize);
340
341 if (pcbSize!=NULL)
342 return E_POINTER;
343
344 /* for more details see ItemMonikerImpl_Save coments */
345
346 pcbSize->s.LowPart = sizeof(DWORD) + /* DWORD which contains delimiter length */
347 delimiterLength + /* item delimiter string */
348 sizeof(DWORD) + /* DWORD which contains item name length */
349 nameLength + /* item name string */
350 34; /* this constant was added ! because when I tested this function it usually */
351 /* returns 34 bytes more than the number of bytes used by IMoniker::Save function */
352 pcbSize->s.HighPart=0;
353
354 return S_OK;
355}
356
357/******************************************************************************
358 * ItemMoniker_Construct (local function)
359 *******************************************************************************/
360HRESULT WINAPI ItemMonikerImpl_Construct(ItemMonikerImpl* This, LPCOLESTR lpszDelim,LPCOLESTR lpszItem)
361{
362
363 int sizeStr1=lstrlenW(lpszItem), sizeStr2;
364 static const OLECHAR emptystr[1];
365 LPCOLESTR delim;
366
367 TRACE("(%p,%p)\n",This,lpszItem);
368
369 /* Initialize the virtual fgunction table. */
370 This->lpvtbl1 = &VT_ItemMonikerImpl;
371 This->lpvtbl2 = &VT_ROTDataImpl;
372 This->ref = 0;
373
374 This->itemName=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr1+1));
375 if (!This->itemName)
376 return E_OUTOFMEMORY;
377 strcpyW(This->itemName,lpszItem);
378
379 if (!lpszDelim)
380 FIXME("lpszDelim is NULL. Using empty string which is possibly wrong.\n");
381
382 delim = lpszDelim ? lpszDelim : emptystr;
383
384 sizeStr2=strlenW(delim);
385 This->itemDelimiter=HeapAlloc(GetProcessHeap(),0,sizeof(WCHAR)*(sizeStr2+1));
386 if (!This->itemDelimiter) {
387 HeapFree(GetProcessHeap(),0,This->itemName);
388 return E_OUTOFMEMORY;
389 }
390 strcpyW(This->itemDelimiter,delim);
391 return S_OK;
392}
393
394/******************************************************************************
395 * ItemMoniker_Destroy (local function)
396 *******************************************************************************/
397HRESULT WINAPI ItemMonikerImpl_Destroy(ItemMonikerImpl* This)
398{
399 TRACE("(%p)\n",This);
400
401 if (This->itemName)
402 HeapFree(GetProcessHeap(),0,This->itemName);
403
404 if (This->itemDelimiter)
405 HeapFree(GetProcessHeap(),0,This->itemDelimiter);
406
407 HeapFree(GetProcessHeap(),0,This);
408
409 return S_OK;
410}
411
412/******************************************************************************
413 * ItemMoniker_BindToObject
414 ******************************************************************************/
415HRESULT WINAPI ItemMonikerImpl_BindToObject(IMoniker* iface,
416 IBindCtx* pbc,
417 IMoniker* pmkToLeft,
418 REFIID riid,
419 VOID** ppvResult)
420{
421 ICOM_THIS(ItemMonikerImpl,iface);
422
423 HRESULT res;
424 IID refid=IID_IOleItemContainer;
425 IOleItemContainer *poic=0;
426
427 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
428
429 if(ppvResult ==NULL)
430 return E_POINTER;
431
432 if(pmkToLeft==NULL)
433 return E_INVALIDARG;
434
435 *ppvResult=0;
436
437 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&refid,(void**)&poic);
438
439 if (SUCCEEDED(res)){
440
441 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,riid,ppvResult);
442
443 IOleItemContainer_Release(poic);
444 }
445
446 return res;
447}
448
449/******************************************************************************
450 * ItemMoniker_BindToStorage
451 ******************************************************************************/
452HRESULT WINAPI ItemMonikerImpl_BindToStorage(IMoniker* iface,
453 IBindCtx* pbc,
454 IMoniker* pmkToLeft,
455 REFIID riid,
456 VOID** ppvResult)
457{
458 ICOM_THIS(ItemMonikerImpl,iface);
459
460 HRESULT res;
461 IOleItemContainer *poic=0;
462
463 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
464
465 *ppvResult=0;
466
467 if(pmkToLeft==NULL)
468 return E_INVALIDARG;
469
470 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
471
472 if (SUCCEEDED(res)){
473
474 res=IOleItemContainer_GetObjectStorage(poic,This->itemName,pbc,riid,ppvResult);
475
476 IOleItemContainer_Release(poic);
477 }
478
479 return res;
480}
481
482/******************************************************************************
483 * ItemMoniker_Reduce
484 ******************************************************************************/
485HRESULT WINAPI ItemMonikerImpl_Reduce(IMoniker* iface,
486 IBindCtx* pbc,
487 DWORD dwReduceHowFar,
488 IMoniker** ppmkToLeft,
489 IMoniker** ppmkReduced)
490{
491 TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
492
493 if (ppmkReduced==NULL)
494 return E_POINTER;
495
496 ItemMonikerImpl_AddRef(iface);
497
498 *ppmkReduced=iface;
499
500 return MK_S_REDUCED_TO_SELF;
501}
502/******************************************************************************
503 * ItemMoniker_ComposeWith
504 ******************************************************************************/
505HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
506 IMoniker* pmkRight,
507 BOOL fOnlyIfNotGeneric,
508 IMoniker** ppmkComposite)
509{
510 HRESULT res=S_OK;
511 DWORD mkSys,mkSys2;
512 IEnumMoniker* penumMk=0;
513 IMoniker *pmostLeftMk=0;
514 IMoniker* tempMkComposite=0;
515
516 TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
517
518 if ((ppmkComposite==NULL)||(pmkRight==NULL))
519 return E_POINTER;
520
521 *ppmkComposite=0;
522
523 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
524
525 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
526 if(mkSys==MKSYS_ANTIMONIKER)
527 return res;
528
529 else
530 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
531 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
532
533 if(mkSys==MKSYS_GENERICCOMPOSITE){
534
535 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
536
537 if (FAILED(res))
538 return res;
539
540 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
541
542 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
543
544 if(mkSys2==MKSYS_ANTIMONIKER){
545
546 IMoniker_Release(pmostLeftMk);
547
548 tempMkComposite=iface;
549 IMoniker_AddRef(iface);
550
551 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
552
553 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
554
555 IMoniker_Release(tempMkComposite);
556 IMoniker_Release(pmostLeftMk);
557
558 tempMkComposite=*ppmkComposite;
559 IMoniker_AddRef(tempMkComposite);
560}
561 return res;
562 }
563 else
564 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
565 }
566 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
567 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
568 a NULL moniker and a return value of MK_E_NEEDGENERIC */
569 else
570 if (!fOnlyIfNotGeneric)
571 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
572
573 else
574 return MK_E_NEEDGENERIC;
575}
576
577/******************************************************************************
578 * ItemMoniker_Enum
579 ******************************************************************************/
580HRESULT WINAPI ItemMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
581{
582 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
583
584 if (ppenumMoniker == NULL)
585 return E_POINTER;
586
587 *ppenumMoniker = NULL;
588
589 return S_OK;
590}
591
592/******************************************************************************
593 * ItemMoniker_IsEqual
594 ******************************************************************************/
595HRESULT WINAPI ItemMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
596{
597
598 CLSID clsid;
599 LPOLESTR dispName1,dispName2;
600 IBindCtx* bind;
601 HRESULT res;
602
603 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
604
605 if (pmkOtherMoniker==NULL)
606 return S_FALSE;
607
608 /* This method returns S_OK if both monikers are item monikers and their display names are */
609 /* identical (using a case-insensitive comparison); otherwise, the method returns S_FALSE. */
610
611 IMoniker_GetClassID(pmkOtherMoniker,&clsid);
612
613 if (!IsEqualCLSID(&clsid,&CLSID_ItemMoniker))
614 return S_FALSE;
615
616 res=CreateBindCtx(0,&bind);
617 if (FAILED(res))
618 return res;
619
620 IMoniker_GetDisplayName(iface,bind,NULL,&dispName1);
621 IMoniker_GetDisplayName(pmkOtherMoniker,bind,NULL,&dispName2);
622
623 if (lstrcmpW(dispName1,dispName2)!=0)
624 return S_FALSE;
625
626 return S_OK;
627}
628
629/******************************************************************************
630 * ItemMoniker_Hash
631 ******************************************************************************/
632HRESULT WINAPI ItemMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
633{
634 ICOM_THIS(ItemMonikerImpl,iface);
635
636 int h = 0,i,skip,len;
637 int off = 0;
638 LPOLESTR val;
639
640 if (pdwHash==NULL)
641 return E_POINTER;
642
643 val = This->itemName;
644 len = lstrlenW(val);
645
646 if (len < 16) {
647 for (i = len ; i > 0; i--) {
648 h = (h * 37) + val[off++];
649}
650 } else {
651 /* only sample some characters */
652 skip = len / 8;
653 for (i = len ; i > 0; i -= skip, off += skip) {
654 h = (h * 39) + val[off];
655 }
656 }
657
658 *pdwHash=h;
659
660 return S_OK;
661}
662
663/******************************************************************************
664 * ItemMoniker_IsRunning
665 ******************************************************************************/
666HRESULT WINAPI ItemMonikerImpl_IsRunning(IMoniker* iface,
667 IBindCtx* pbc,
668 IMoniker* pmkToLeft,
669 IMoniker* pmkNewlyRunning)
670{
671 IRunningObjectTable* rot;
672 HRESULT res;
673 IOleItemContainer *poic=0;
674 ICOM_THIS(ItemMonikerImpl,iface);
675
676 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
677
678 /* If pmkToLeft is NULL, this method returns TRUE if pmkNewlyRunning is non-NULL and is equal to this */
679 /* moniker. Otherwise, the method checks the ROT to see whether this moniker is running. */
680 if (pmkToLeft==NULL)
681 if ((pmkNewlyRunning!=NULL)&&(IMoniker_IsEqual(pmkNewlyRunning,iface)==S_OK))
682 return S_OK;
683 else {
684 if (pbc==NULL)
685 return E_POINTER;
686
687 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
688
689 if (FAILED(res))
690 return res;
691
692 res = IRunningObjectTable_IsRunning(rot,iface);
693
694 IRunningObjectTable_Release(rot);
695 }
696 else{
697
698 /* If pmkToLeft is non-NULL, the method calls IMoniker::BindToObject on the pmkToLeft parameter, */
699 /* requesting an IOleItemContainer interface pointer. The method then calls IOleItemContainer::IsRunning,*/
700 /* passing the string contained within this moniker. */
701
702 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
703
704 if (SUCCEEDED(res)){
705
706 res=IOleItemContainer_IsRunning(poic,This->itemName);
707
708 IOleItemContainer_Release(poic);
709 }
710 }
711
712 return res;
713}
714
715/******************************************************************************
716 * ItemMoniker_GetTimeOfLastChange
717 ******************************************************************************/
718HRESULT WINAPI ItemMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
719 IBindCtx* pbc,
720 IMoniker* pmkToLeft,
721 FILETIME* pItemTime)
722{
723 IRunningObjectTable* rot;
724 HRESULT res;
725 IMoniker *compositeMk;
726
727 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pItemTime);
728
729 if (pItemTime==NULL)
730 return E_INVALIDARG;
731
732 /* If pmkToLeft is NULL, this method returns MK_E_NOTBINDABLE */
733 if (pmkToLeft==NULL)
734
735 return MK_E_NOTBINDABLE;
736 else {
737
738 /* Otherwise, the method creates a composite of pmkToLeft and this moniker and uses the ROT to access */
739 /* the time of last change. If the object is not in the ROT, the method calls */
740 /* IMoniker::GetTimeOfLastChange on the pmkToLeft parameter. */
741
742 res=CreateGenericComposite(pmkToLeft,iface,&compositeMk);
743
744 res=IBindCtx_GetRunningObjectTable(pbc,&rot);
745
746 if (IRunningObjectTable_GetTimeOfLastChange(rot,compositeMk,pItemTime)!=S_OK)
747
748 res=IMoniker_GetTimeOfLastChange(pmkToLeft,pbc,NULL,pItemTime);
749
750 IMoniker_Release(compositeMk);
751}
752
753 return res;
754}
755
756/******************************************************************************
757 * ItemMoniker_Inverse
758 ******************************************************************************/
759HRESULT WINAPI ItemMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
760{
761 TRACE("(%p,%p)\n",iface,ppmk);
762
763 if (ppmk==NULL)
764 return E_POINTER;
765
766 return CreateAntiMoniker(ppmk);
767}
768
769/******************************************************************************
770 * ItemMoniker_CommonPrefixWith
771 ******************************************************************************/
772HRESULT WINAPI ItemMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
773{
774 DWORD mkSys;
775 IMoniker_IsSystemMoniker(pmkOther,&mkSys);
776 /* If the other moniker is an item moniker that is equal to this moniker, this method sets *ppmkPrefix */
777 /* to this moniker and returns MK_S_US */
778
779 if((mkSys==MKSYS_ITEMMONIKER) && (IMoniker_IsEqual(iface,pmkOther)==S_OK) ){
780
781 *ppmkPrefix=iface;
782
783 IMoniker_AddRef(iface);
784
785 return MK_S_US;
786 }
787 else
788 /* otherwise, the method calls the MonikerCommonPrefixWith function. This function correctly handles */
789 /* the case where the other moniker is a generic composite. */
790 return MonikerCommonPrefixWith(iface,pmkOther,ppmkPrefix);
791}
792
793/******************************************************************************
794 * ItemMoniker_RelativePathTo
795 ******************************************************************************/
796HRESULT WINAPI ItemMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
797{
798 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
799
800 if (ppmkRelPath==NULL)
801 return E_POINTER;
802
803 *ppmkRelPath=0;
804
805 return MK_E_NOTBINDABLE;
806}
807
808/******************************************************************************
809 * ItemMoniker_GetDisplayName
810 ******************************************************************************/
811HRESULT WINAPI ItemMonikerImpl_GetDisplayName(IMoniker* iface,
812 IBindCtx* pbc,
813 IMoniker* pmkToLeft,
814 LPOLESTR *ppszDisplayName)
815{
816 ICOM_THIS(ItemMonikerImpl,iface);
817
818 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
819
820 if (ppszDisplayName==NULL)
821 return E_POINTER;
822
823 if (pmkToLeft!=NULL){
824 return E_INVALIDARG;
825 }
826
827 *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR)*(lstrlenW(This->itemDelimiter)+lstrlenW(This->itemName)+1));
828
829 if (*ppszDisplayName==NULL)
830 return E_OUTOFMEMORY;
831
832 strcpyW(*ppszDisplayName,This->itemDelimiter);
833 strcatW(*ppszDisplayName,This->itemName);
834
835 return S_OK;
836}
837
838/******************************************************************************
839 * ItemMoniker_ParseDisplayName
840 ******************************************************************************/
841HRESULT WINAPI ItemMonikerImpl_ParseDisplayName(IMoniker* iface,
842 IBindCtx* pbc,
843 IMoniker* pmkToLeft,
844 LPOLESTR pszDisplayName,
845 ULONG* pchEaten,
846 IMoniker** ppmkOut)
847{
848 IOleItemContainer* poic=0;
849 IParseDisplayName* ppdn=0;
850 LPOLESTR displayName;
851 HRESULT res;
852 ICOM_THIS(ItemMonikerImpl,iface);
853
854 /* If pmkToLeft is NULL, this method returns MK_E_SYNTAX */
855 if (pmkToLeft==NULL)
856
857 return MK_E_SYNTAX;
858
859 else{
860 /* Otherwise, the method calls IMoniker::BindToObject on the pmkToLeft parameter, requesting an */
861 /* IParseDisplayName interface pointer to the object identified by the moniker, and passes the display */ /* name to IParseDisplayName::ParseDisplayName */
862 res=IMoniker_BindToObject(pmkToLeft,pbc,NULL,&IID_IOleItemContainer,(void**)&poic);
863
864 if (SUCCEEDED(res)){
865
866 res=IOleItemContainer_GetObject(poic,This->itemName,BINDSPEED_MODERATE,pbc,&IID_IParseDisplayName,(void**)&ppdn);
867
868 res=IMoniker_GetDisplayName(iface,pbc,NULL,&displayName);
869
870 res=IParseDisplayName_ParseDisplayName(ppdn,pbc,displayName,pchEaten,ppmkOut);
871
872 IOleItemContainer_Release(poic);
873 IParseDisplayName_Release(ppdn);
874 }
875}
876 return res;
877}
878
879/******************************************************************************
880 * ItemMoniker_IsSystemMoniker
881 ******************************************************************************/
882HRESULT WINAPI ItemMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
883{
884 TRACE("(%p,%p)\n",iface,pwdMksys);
885
886 if (!pwdMksys)
887 return E_POINTER;
888
889 (*pwdMksys)=MKSYS_ITEMMONIKER;
890
891 return S_OK;
892}
893
894/*******************************************************************************
895 * ItemMonikerIROTData_QueryInterface
896 *******************************************************************************/
897HRESULT WINAPI ItemMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
898{
899
900 ICOM_THIS_From_IROTData(IMoniker, iface);
901
902 TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
903
904 return ItemMonikerImpl_QueryInterface(This, riid, ppvObject);
905}
906
907/***********************************************************************
908 * ItemMonikerIROTData_AddRef
909 */
910ULONG WINAPI ItemMonikerROTDataImpl_AddRef(IROTData *iface)
911{
912 ICOM_THIS_From_IROTData(IMoniker, iface);
913
914 TRACE("(%p)\n",iface);
915
916 return ItemMonikerImpl_AddRef(This);
917}
918
919/***********************************************************************
920 * ItemMonikerIROTData_Release
921 */
922ULONG WINAPI ItemMonikerROTDataImpl_Release(IROTData* iface)
923{
924 ICOM_THIS_From_IROTData(IMoniker, iface);
925
926 TRACE("(%p)\n",iface);
927
928 return ItemMonikerImpl_Release(This);
929}
930
931/******************************************************************************
932 * ItemMonikerIROTData_GetComparaisonData
933 ******************************************************************************/
934HRESULT WINAPI ItemMonikerROTDataImpl_GetComparaisonData(IROTData* iface,
935 BYTE* pbData,
936 ULONG cbMax,
937 ULONG* pcbData)
938{
939 FIXME("(),stub!\n");
940 return E_NOTIMPL;
941}
942
943/******************************************************************************
944 * CreateItemMoniker16 [OLE2.28]
945 ******************************************************************************/
946HRESULT WINAPI CreateItemMoniker16(LPCOLESTR16 lpszDelim,LPCOLESTR lpszItem,LPMONIKER* ppmk)
947{
948
949 FIXME("(%s,%p),stub!\n",lpszDelim,ppmk);
950 *ppmk = NULL;
951 return E_NOTIMPL;
952}
953
954/******************************************************************************
955 * CreateItemMoniker [OLE.55]
956 ******************************************************************************/
957HRESULT WINAPI CreateItemMoniker(LPCOLESTR lpszDelim,LPCOLESTR lpszItem, LPMONIKER * ppmk)
958{
959 ItemMonikerImpl* newItemMoniker = 0;
960 HRESULT hr = S_OK;
961 IID riid=IID_IMoniker;
962
963 TRACE("(%p,%p,%p)\n",lpszDelim,lpszItem,ppmk);
964
965 newItemMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(ItemMonikerImpl));
966
967 if (newItemMoniker == 0)
968 return STG_E_INSUFFICIENTMEMORY;
969
970 hr = ItemMonikerImpl_Construct(newItemMoniker,lpszDelim,lpszItem);
971
972 if (FAILED(hr)){
973
974 HeapFree(GetProcessHeap(),0,newItemMoniker);
975 return hr;
976 }
977
978 return ItemMonikerImpl_QueryInterface((IMoniker*)newItemMoniker,&riid,(void**)ppmk);
979}
Note: See TracBrowser for help on using the repository browser.