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