Synchronize with trunk r58606.
[reactos.git] / dll / win32 / ole32 / pointermoniker.c
1 /*
2 * Pointer Moniker Implementation
3 *
4 * Copyright 1999 Noomen Hamza
5 * Copyright 2008 Robert Shearman (for CodeWeavers)
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #define WIN32_NO_STATUS
23 #define _INC_WINDOWS
24
25 #include <stdarg.h>
26 //#include <string.h>
27
28 #define COBJMACROS
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
31
32 #include <windef.h>
33 #include <winbase.h>
34 //#include "winerror.h"
35 //#include "winuser.h"
36 #include <objbase.h>
37 #include <oleidl.h>
38 #include <wine/debug.h>
39 #include "moniker.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(ole);
42
43 /* PointerMoniker data structure */
44 typedef struct PointerMonikerImpl{
45
46 IMoniker IMoniker_iface;
47
48 LONG ref; /* reference counter for this object */
49
50 IUnknown *pObject; /* custom marshaler */
51 } PointerMonikerImpl;
52
53 static inline PointerMonikerImpl *impl_from_IMoniker(IMoniker *iface)
54 {
55 return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface);
56 }
57
58 static HRESULT WINAPI
59 PointerMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
60 {
61 PointerMonikerImpl *This = impl_from_IMoniker(iface);
62
63 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
64
65 /* Perform a sanity check on the parameters.*/
66 if ( (This==0) || (ppvObject==0) )
67 return E_INVALIDARG;
68
69 /* Initialize the return parameter */
70 *ppvObject = 0;
71
72 /* Compare the riid with the interface IDs implemented by this object.*/
73 if (IsEqualIID(&IID_IUnknown, riid) ||
74 IsEqualIID(&IID_IPersist, riid) ||
75 IsEqualIID(&IID_IPersistStream, riid) ||
76 IsEqualIID(&IID_IMoniker, riid))
77 *ppvObject = iface;
78
79 /* Check that we obtained an interface.*/
80 if ((*ppvObject)==0)
81 return E_NOINTERFACE;
82
83 /* always increase the reference count by one when it is successful */
84 IMoniker_AddRef(iface);
85
86 return S_OK;
87 }
88
89 /******************************************************************************
90 * PointerMoniker_AddRef
91 ******************************************************************************/
92 static ULONG WINAPI
93 PointerMonikerImpl_AddRef(IMoniker* iface)
94 {
95 PointerMonikerImpl *This = impl_from_IMoniker(iface);
96
97 TRACE("(%p)\n",This);
98
99 return InterlockedIncrement(&This->ref);
100 }
101
102 /******************************************************************************
103 * PointerMoniker_Release
104 ******************************************************************************/
105 static ULONG WINAPI
106 PointerMonikerImpl_Release(IMoniker* iface)
107 {
108 PointerMonikerImpl *This = impl_from_IMoniker(iface);
109 ULONG ref;
110
111 TRACE("(%p)\n",This);
112
113 ref = InterlockedDecrement(&This->ref);
114
115 /* destroy the object if there's no more reference on it */
116 if (ref == 0)
117 {
118 if (This->pObject) IUnknown_Release(This->pObject);
119 HeapFree(GetProcessHeap(),0,This);
120 }
121
122 return ref;
123 }
124
125 /******************************************************************************
126 * PointerMoniker_GetClassID
127 ******************************************************************************/
128 static HRESULT WINAPI
129 PointerMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
130 {
131 TRACE("(%p,%p)\n",iface,pClassID);
132
133 if (pClassID==NULL)
134 return E_POINTER;
135
136 *pClassID = CLSID_PointerMoniker;
137
138 return S_OK;
139 }
140
141 /******************************************************************************
142 * PointerMoniker_IsDirty
143 ******************************************************************************/
144 static HRESULT WINAPI
145 PointerMonikerImpl_IsDirty(IMoniker* iface)
146 {
147 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
148 method in the OLE-provided moniker interfaces always return S_FALSE because
149 their internal state never changes. */
150
151 TRACE("(%p)\n",iface);
152
153 return S_FALSE;
154 }
155
156 /******************************************************************************
157 * PointerMoniker_Load
158 ******************************************************************************/
159 static HRESULT WINAPI
160 PointerMonikerImpl_Load(IMoniker* iface,IStream* pStm)
161 {
162 TRACE("(%p)\n", pStm);
163
164 return E_NOTIMPL;
165 }
166
167 /******************************************************************************
168 * PointerMoniker_Save
169 ******************************************************************************/
170 static HRESULT WINAPI
171 PointerMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
172 {
173 TRACE("(%p, %d)\n", pStm, fClearDirty);
174
175 return E_NOTIMPL;
176 }
177
178 /******************************************************************************
179 * PointerMoniker_GetSizeMax
180 *
181 * PARAMS
182 * pcbSize [out] Pointer to size of stream needed to save object
183 ******************************************************************************/
184 static HRESULT WINAPI
185 PointerMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
186 {
187 TRACE("(%p,%p)\n",iface,pcbSize);
188
189 if (!pcbSize)
190 return E_POINTER;
191
192 pcbSize->u.LowPart = 0;
193 pcbSize->u.HighPart = 0;
194
195 return E_NOTIMPL;
196 }
197
198 /******************************************************************************
199 * PointerMoniker_BindToObject
200 ******************************************************************************/
201 static HRESULT WINAPI
202 PointerMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
203 REFIID riid, VOID** ppvResult)
204 {
205 PointerMonikerImpl *This = impl_from_IMoniker(iface);
206
207 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
208
209 if (!This->pObject)
210 return E_UNEXPECTED;
211
212 return IUnknown_QueryInterface(This->pObject, riid, ppvResult);
213 }
214
215 /******************************************************************************
216 * PointerMoniker_BindToStorage
217 ******************************************************************************/
218 static HRESULT WINAPI
219 PointerMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
220 REFIID riid, VOID** ppvResult)
221 {
222 PointerMonikerImpl *This = impl_from_IMoniker(iface);
223
224 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
225
226 if (!This->pObject)
227 return E_UNEXPECTED;
228
229 return IUnknown_QueryInterface(This->pObject, riid, ppvResult);
230 }
231
232 /******************************************************************************
233 * PointerMoniker_Reduce
234 ******************************************************************************/
235 static HRESULT WINAPI
236 PointerMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
237 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
238 {
239 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
240
241 if (ppmkReduced==NULL)
242 return E_POINTER;
243
244 PointerMonikerImpl_AddRef(iface);
245
246 *ppmkReduced=iface;
247
248 return MK_S_REDUCED_TO_SELF;
249 }
250 /******************************************************************************
251 * PointerMoniker_ComposeWith
252 ******************************************************************************/
253 static HRESULT WINAPI
254 PointerMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
255 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
256 {
257
258 HRESULT res=S_OK;
259 DWORD mkSys,mkSys2;
260 IEnumMoniker* penumMk=0;
261 IMoniker *pmostLeftMk=0;
262 IMoniker* tempMkComposite=0;
263
264 TRACE("(%p,%d,%p)\n", pmkRight, fOnlyIfNotGeneric, ppmkComposite);
265
266 if ((ppmkComposite==NULL)||(pmkRight==NULL))
267 return E_POINTER;
268
269 *ppmkComposite=0;
270
271 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
272
273 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
274 if(mkSys==MKSYS_ANTIMONIKER)
275 return res;
276
277 else
278 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
279 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
280
281 if(mkSys==MKSYS_GENERICCOMPOSITE){
282
283 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
284
285 if (FAILED(res))
286 return res;
287
288 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
289
290 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
291
292 if(mkSys2==MKSYS_ANTIMONIKER){
293
294 IMoniker_Release(pmostLeftMk);
295
296 tempMkComposite=iface;
297 IMoniker_AddRef(iface);
298
299 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
300
301 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
302
303 IMoniker_Release(tempMkComposite);
304 IMoniker_Release(pmostLeftMk);
305
306 tempMkComposite=*ppmkComposite;
307 IMoniker_AddRef(tempMkComposite);
308 }
309 return res;
310 }
311 else
312 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
313 }
314 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
315 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
316 a NULL moniker and a return value of MK_E_NEEDGENERIC */
317 else
318 if (!fOnlyIfNotGeneric)
319 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
320
321 else
322 return MK_E_NEEDGENERIC;
323 }
324
325 /******************************************************************************
326 * PointerMoniker_Enum
327 ******************************************************************************/
328 static HRESULT WINAPI
329 PointerMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
330 {
331 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
332
333 if (ppenumMoniker == NULL)
334 return E_POINTER;
335
336 *ppenumMoniker = NULL;
337
338 return S_OK;
339 }
340
341 /******************************************************************************
342 * PointerMoniker_IsEqual
343 ******************************************************************************/
344 static HRESULT WINAPI
345 PointerMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
346 {
347 PointerMonikerImpl *This = impl_from_IMoniker(iface);
348 DWORD mkSys;
349
350 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
351
352 if (pmkOtherMoniker==NULL)
353 return S_FALSE;
354
355 IMoniker_IsSystemMoniker(pmkOtherMoniker,&mkSys);
356
357 if (mkSys==MKSYS_POINTERMONIKER)
358 {
359 PointerMonikerImpl *pOtherMoniker = impl_from_IMoniker(pmkOtherMoniker);
360 return This->pObject == pOtherMoniker->pObject ? S_OK : S_FALSE;
361 }
362 else
363 return S_FALSE;
364 }
365
366 /******************************************************************************
367 * PointerMoniker_Hash
368 ******************************************************************************/
369 static HRESULT WINAPI PointerMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
370 {
371 PointerMonikerImpl *This = impl_from_IMoniker(iface);
372
373 if (pdwHash==NULL)
374 return E_POINTER;
375
376 *pdwHash = PtrToUlong(This->pObject);
377
378 return S_OK;
379 }
380
381 /******************************************************************************
382 * PointerMoniker_IsRunning
383 ******************************************************************************/
384 static HRESULT WINAPI
385 PointerMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
386 IMoniker* pmkNewlyRunning)
387 {
388 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
389
390 return S_OK;
391 }
392
393 /******************************************************************************
394 * PointerMoniker_GetTimeOfLastChange
395 ******************************************************************************/
396 static HRESULT WINAPI PointerMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
397 IBindCtx* pbc,
398 IMoniker* pmkToLeft,
399 FILETIME* pAntiTime)
400 {
401 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime);
402 return E_NOTIMPL;
403 }
404
405 /******************************************************************************
406 * PointerMoniker_Inverse
407 ******************************************************************************/
408 static HRESULT WINAPI
409 PointerMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
410 {
411 TRACE("(%p,%p)\n",iface,ppmk);
412
413 return CreateAntiMoniker(ppmk);
414 }
415
416 /******************************************************************************
417 * PointerMoniker_CommonPrefixWith
418 ******************************************************************************/
419 static HRESULT WINAPI
420 PointerMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
421 {
422 TRACE("(%p, %p)\n", pmkOther, ppmkPrefix);
423
424 *ppmkPrefix = NULL;
425
426 if (PointerMonikerImpl_IsEqual(iface, pmkOther))
427 {
428 IMoniker_AddRef(iface);
429
430 *ppmkPrefix=iface;
431
432 return MK_S_US;
433 }
434 else
435 return MK_E_NOPREFIX;
436 }
437
438 /******************************************************************************
439 * PointerMoniker_RelativePathTo
440 ******************************************************************************/
441 static HRESULT WINAPI
442 PointerMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
443 {
444 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
445
446 if (ppmkRelPath==NULL)
447 return E_POINTER;
448
449 *ppmkRelPath = NULL;
450
451 return E_NOTIMPL;
452 }
453
454 /******************************************************************************
455 * PointerMoniker_GetDisplayName
456 ******************************************************************************/
457 static HRESULT WINAPI
458 PointerMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
459 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
460 {
461 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
462
463 if (ppszDisplayName==NULL)
464 return E_POINTER;
465
466 *ppszDisplayName = NULL;
467 return E_NOTIMPL;
468 }
469
470 /******************************************************************************
471 * PointerMoniker_ParseDisplayName
472 ******************************************************************************/
473 static HRESULT WINAPI
474 PointerMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
475 IMoniker* pmkToLeft, LPOLESTR pszDisplayName,
476 ULONG* pchEaten, IMoniker** ppmkOut)
477 {
478 PointerMonikerImpl *This = impl_from_IMoniker(iface);
479 HRESULT hr;
480 IParseDisplayName *pPDN;
481
482 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
483
484 if (pmkToLeft)
485 return MK_E_SYNTAX;
486
487 if (!This->pObject)
488 return E_UNEXPECTED;
489
490 hr = IUnknown_QueryInterface(This->pObject, &IID_IParseDisplayName, (void **)&pPDN);
491 if (FAILED(hr))
492 return hr;
493
494 hr = IParseDisplayName_ParseDisplayName(pPDN, pbc, pszDisplayName, pchEaten, ppmkOut);
495 IParseDisplayName_Release(pPDN);
496
497 return hr;
498 }
499
500 /******************************************************************************
501 * PointerMoniker_IsSystemMoniker
502 ******************************************************************************/
503 static HRESULT WINAPI
504 PointerMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
505 {
506 TRACE("(%p,%p)\n",iface,pwdMksys);
507
508 if (!pwdMksys)
509 return E_POINTER;
510
511 *pwdMksys = MKSYS_POINTERMONIKER;
512
513 return S_OK;
514 }
515
516 /********************************************************************************/
517 /* Virtual function table for the PointerMonikerImpl class which include IPersist,*/
518 /* IPersistStream and IMoniker functions. */
519 static const IMonikerVtbl VT_PointerMonikerImpl =
520 {
521 PointerMonikerImpl_QueryInterface,
522 PointerMonikerImpl_AddRef,
523 PointerMonikerImpl_Release,
524 PointerMonikerImpl_GetClassID,
525 PointerMonikerImpl_IsDirty,
526 PointerMonikerImpl_Load,
527 PointerMonikerImpl_Save,
528 PointerMonikerImpl_GetSizeMax,
529 PointerMonikerImpl_BindToObject,
530 PointerMonikerImpl_BindToStorage,
531 PointerMonikerImpl_Reduce,
532 PointerMonikerImpl_ComposeWith,
533 PointerMonikerImpl_Enum,
534 PointerMonikerImpl_IsEqual,
535 PointerMonikerImpl_Hash,
536 PointerMonikerImpl_IsRunning,
537 PointerMonikerImpl_GetTimeOfLastChange,
538 PointerMonikerImpl_Inverse,
539 PointerMonikerImpl_CommonPrefixWith,
540 PointerMonikerImpl_RelativePathTo,
541 PointerMonikerImpl_GetDisplayName,
542 PointerMonikerImpl_ParseDisplayName,
543 PointerMonikerImpl_IsSystemMoniker
544 };
545
546 /******************************************************************************
547 * PointerMoniker_Construct (local function)
548 *******************************************************************************/
549 static void PointerMonikerImpl_Construct(PointerMonikerImpl* This, IUnknown *punk)
550 {
551 TRACE("(%p)\n",This);
552
553 /* Initialize the virtual function table. */
554 This->IMoniker_iface.lpVtbl = &VT_PointerMonikerImpl;
555 This->ref = 1;
556 if (punk)
557 IUnknown_AddRef(punk);
558 This->pObject = punk;
559 }
560
561 /***********************************************************************
562 * CreatePointerMoniker (OLE32.@)
563 *
564 * Creates a moniker which represents a pointer.
565 *
566 * PARAMS
567 * punk [I] Pointer to the object to represent.
568 * ppmk [O] Address that receives the pointer to the created moniker.
569 *
570 * RETURNS
571 * Success: S_OK.
572 * Failure: Any HRESULT code.
573 */
574 HRESULT WINAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER *ppmk)
575 {
576 PointerMonikerImpl *This;
577
578 TRACE("(%p, %p)\n", punk, ppmk);
579
580 if (!ppmk)
581 return E_INVALIDARG;
582
583 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
584 if (!This)
585 {
586 *ppmk = NULL;
587 return E_OUTOFMEMORY;
588 }
589
590 PointerMonikerImpl_Construct(This, punk);
591 *ppmk = &This->IMoniker_iface;
592 return S_OK;
593 }
594
595 static HRESULT WINAPI PointerMonikerCF_QueryInterface(LPCLASSFACTORY iface,
596 REFIID riid, LPVOID *ppv)
597 {
598 *ppv = NULL;
599 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
600 {
601 *ppv = iface;
602 IClassFactory_AddRef(iface);
603 return S_OK;
604 }
605 return E_NOINTERFACE;
606 }
607
608 static ULONG WINAPI PointerMonikerCF_AddRef(LPCLASSFACTORY iface)
609 {
610 return 2; /* non-heap based object */
611 }
612
613 static ULONG WINAPI PointerMonikerCF_Release(LPCLASSFACTORY iface)
614 {
615 return 1; /* non-heap based object */
616 }
617
618 static HRESULT WINAPI PointerMonikerCF_CreateInstance(LPCLASSFACTORY iface,
619 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
620 {
621 IMoniker *pMoniker;
622 HRESULT hr;
623
624 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
625
626 *ppv = NULL;
627
628 if (pUnk)
629 return CLASS_E_NOAGGREGATION;
630
631 hr = CreatePointerMoniker(NULL, &pMoniker);
632 if (FAILED(hr))
633 return hr;
634
635 hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
636
637 if (FAILED(hr))
638 IMoniker_Release(pMoniker);
639
640 return hr;
641 }
642
643 static HRESULT WINAPI PointerMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
644 {
645 FIXME("(%d), stub!\n",fLock);
646 return S_OK;
647 }
648
649 static const IClassFactoryVtbl PointerMonikerCFVtbl =
650 {
651 PointerMonikerCF_QueryInterface,
652 PointerMonikerCF_AddRef,
653 PointerMonikerCF_Release,
654 PointerMonikerCF_CreateInstance,
655 PointerMonikerCF_LockServer
656 };
657 static const IClassFactoryVtbl *PointerMonikerCF = &PointerMonikerCFVtbl;
658
659 HRESULT PointerMonikerCF_Create(REFIID riid, LPVOID *ppv)
660 {
661 return IClassFactory_QueryInterface((IClassFactory *)&PointerMonikerCF, riid, ppv);
662 }