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

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

Wine 20020215 resync

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