quartz: Fix support for files with multiple odml indexes.
[wine/wine64.git] / dlls / ole32 / pointermoniker.c
blob299b44e2c0b52f75daf33719e77cd93766a44f77
1 /*
2 * Pointer Moniker Implementation
4 * Copyright 1999 Noomen Hamza
5 * Copyright 2008 Robert Shearman (for CodeWeavers)
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.
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.
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
22 #include <stdarg.h>
23 #include <string.h>
25 #define COBJMACROS
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "winuser.h"
33 #include "objbase.h"
34 #include "oleidl.h"
35 #include "wine/debug.h"
36 #include "moniker.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ole);
40 /* PointerMoniker data structure */
41 typedef struct PointerMonikerImpl{
43 const IMonikerVtbl* lpvtbl; /* VTable relative to the IMoniker interface.*/
45 LONG ref; /* reference counter for this object */
47 IUnknown *pObject; /* custom marshaler */
48 } PointerMonikerImpl;
50 static HRESULT WINAPI
51 PointerMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
53 PointerMonikerImpl *This = (PointerMonikerImpl *)iface;
55 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
57 /* Perform a sanity check on the parameters.*/
58 if ( (This==0) || (ppvObject==0) )
59 return E_INVALIDARG;
61 /* Initialize the return parameter */
62 *ppvObject = 0;
64 /* Compare the riid with the interface IDs implemented by this object.*/
65 if (IsEqualIID(&IID_IUnknown, riid) ||
66 IsEqualIID(&IID_IPersist, riid) ||
67 IsEqualIID(&IID_IPersistStream, riid) ||
68 IsEqualIID(&IID_IMoniker, riid))
69 *ppvObject = iface;
71 /* Check that we obtained an interface.*/
72 if ((*ppvObject)==0)
73 return E_NOINTERFACE;
75 /* always increase the reference count by one when it is successful */
76 IMoniker_AddRef(iface);
78 return S_OK;
81 /******************************************************************************
82 * PointerMoniker_AddRef
83 ******************************************************************************/
84 static ULONG WINAPI
85 PointerMonikerImpl_AddRef(IMoniker* iface)
87 PointerMonikerImpl *This = (PointerMonikerImpl *)iface;
89 TRACE("(%p)\n",This);
91 return InterlockedIncrement(&This->ref);
94 /******************************************************************************
95 * PointerMoniker_Release
96 ******************************************************************************/
97 static ULONG WINAPI
98 PointerMonikerImpl_Release(IMoniker* iface)
100 PointerMonikerImpl *This = (PointerMonikerImpl *)iface;
101 ULONG ref;
103 TRACE("(%p)\n",This);
105 ref = InterlockedDecrement(&This->ref);
107 /* destroy the object if there's no more reference on it */
108 if (ref == 0)
110 if (This->pObject) IUnknown_Release(This->pObject);
111 HeapFree(GetProcessHeap(),0,This);
114 return ref;
117 /******************************************************************************
118 * PointerMoniker_GetClassID
119 ******************************************************************************/
120 static HRESULT WINAPI
121 PointerMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
123 TRACE("(%p,%p)\n",iface,pClassID);
125 if (pClassID==NULL)
126 return E_POINTER;
128 *pClassID = CLSID_PointerMoniker;
130 return S_OK;
133 /******************************************************************************
134 * PointerMoniker_IsDirty
135 ******************************************************************************/
136 static HRESULT WINAPI
137 PointerMonikerImpl_IsDirty(IMoniker* iface)
139 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
140 method in the OLE-provided moniker interfaces always return S_FALSE because
141 their internal state never changes. */
143 TRACE("(%p)\n",iface);
145 return S_FALSE;
148 /******************************************************************************
149 * PointerMoniker_Load
150 ******************************************************************************/
151 static HRESULT WINAPI
152 PointerMonikerImpl_Load(IMoniker* iface,IStream* pStm)
154 TRACE("(%p)\n", pStm);
156 return E_NOTIMPL;
159 /******************************************************************************
160 * PointerMoniker_Save
161 ******************************************************************************/
162 static HRESULT WINAPI
163 PointerMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
165 TRACE("(%p, %d)\n", pStm, fClearDirty);
167 return E_NOTIMPL;
170 /******************************************************************************
171 * PointerMoniker_GetSizeMax
173 * PARAMS
174 * pcbSize [out] Pointer to size of stream needed to save object
175 ******************************************************************************/
176 static HRESULT WINAPI
177 PointerMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
179 TRACE("(%p,%p)\n",iface,pcbSize);
181 if (!pcbSize)
182 return E_POINTER;
184 pcbSize->u.LowPart = 0;
185 pcbSize->u.HighPart = 0;
187 return E_NOTIMPL;
190 /******************************************************************************
191 * PointerMoniker_BindToObject
192 ******************************************************************************/
193 static HRESULT WINAPI
194 PointerMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
195 REFIID riid, VOID** ppvResult)
197 PointerMonikerImpl *This = (PointerMonikerImpl *)iface;
199 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
201 if (!This->pObject)
202 return E_UNEXPECTED;
204 return IUnknown_QueryInterface(This->pObject, riid, ppvResult);
207 /******************************************************************************
208 * PointerMoniker_BindToStorage
209 ******************************************************************************/
210 static HRESULT WINAPI
211 PointerMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
212 REFIID riid, VOID** ppvResult)
214 PointerMonikerImpl *This = (PointerMonikerImpl *)iface;
216 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
218 if (!This->pObject)
219 return E_UNEXPECTED;
221 return IUnknown_QueryInterface(This->pObject, riid, ppvResult);
224 /******************************************************************************
225 * PointerMoniker_Reduce
226 ******************************************************************************/
227 static HRESULT WINAPI
228 PointerMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
229 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
231 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
233 if (ppmkReduced==NULL)
234 return E_POINTER;
236 PointerMonikerImpl_AddRef(iface);
238 *ppmkReduced=iface;
240 return MK_S_REDUCED_TO_SELF;
242 /******************************************************************************
243 * PointerMoniker_ComposeWith
244 ******************************************************************************/
245 static HRESULT WINAPI
246 PointerMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
247 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
250 HRESULT res=S_OK;
251 DWORD mkSys,mkSys2;
252 IEnumMoniker* penumMk=0;
253 IMoniker *pmostLeftMk=0;
254 IMoniker* tempMkComposite=0;
256 TRACE("(%p,%d,%p)\n", pmkRight, fOnlyIfNotGeneric, ppmkComposite);
258 if ((ppmkComposite==NULL)||(pmkRight==NULL))
259 return E_POINTER;
261 *ppmkComposite=0;
263 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
265 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
266 if(mkSys==MKSYS_ANTIMONIKER)
267 return res;
269 else
270 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
271 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
273 if(mkSys==MKSYS_GENERICCOMPOSITE){
275 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
277 if (FAILED(res))
278 return res;
280 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
282 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
284 if(mkSys2==MKSYS_ANTIMONIKER){
286 IMoniker_Release(pmostLeftMk);
288 tempMkComposite=iface;
289 IMoniker_AddRef(iface);
291 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
293 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
295 IMoniker_Release(tempMkComposite);
296 IMoniker_Release(pmostLeftMk);
298 tempMkComposite=*ppmkComposite;
299 IMoniker_AddRef(tempMkComposite);
301 return res;
303 else
304 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
306 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
307 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
308 a NULL moniker and a return value of MK_E_NEEDGENERIC */
309 else
310 if (!fOnlyIfNotGeneric)
311 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
313 else
314 return MK_E_NEEDGENERIC;
317 /******************************************************************************
318 * PointerMoniker_Enum
319 ******************************************************************************/
320 static HRESULT WINAPI
321 PointerMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
323 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
325 if (ppenumMoniker == NULL)
326 return E_POINTER;
328 *ppenumMoniker = NULL;
330 return S_OK;
333 /******************************************************************************
334 * PointerMoniker_IsEqual
335 ******************************************************************************/
336 static HRESULT WINAPI
337 PointerMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
339 PointerMonikerImpl *This = (PointerMonikerImpl *)iface;
340 DWORD mkSys;
342 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
344 if (pmkOtherMoniker==NULL)
345 return S_FALSE;
347 IMoniker_IsSystemMoniker(pmkOtherMoniker,&mkSys);
349 if (mkSys==MKSYS_POINTERMONIKER)
351 PointerMonikerImpl *pOtherMoniker = (PointerMonikerImpl *)pmkOtherMoniker;
352 return This->pObject == pOtherMoniker->pObject ? S_OK : S_FALSE;
354 else
355 return S_FALSE;
358 /******************************************************************************
359 * PointerMoniker_Hash
360 ******************************************************************************/
361 static HRESULT WINAPI PointerMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
363 PointerMonikerImpl *This = (PointerMonikerImpl *)iface;
365 if (pdwHash==NULL)
366 return E_POINTER;
368 *pdwHash = (DWORD)This->pObject;
370 return S_OK;
373 /******************************************************************************
374 * PointerMoniker_IsRunning
375 ******************************************************************************/
376 static HRESULT WINAPI
377 PointerMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
378 IMoniker* pmkNewlyRunning)
380 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
382 return S_OK;
385 /******************************************************************************
386 * PointerMoniker_GetTimeOfLastChange
387 ******************************************************************************/
388 static HRESULT WINAPI PointerMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
389 IBindCtx* pbc,
390 IMoniker* pmkToLeft,
391 FILETIME* pAntiTime)
393 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime);
394 return E_NOTIMPL;
397 /******************************************************************************
398 * PointerMoniker_Inverse
399 ******************************************************************************/
400 static HRESULT WINAPI
401 PointerMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
403 TRACE("(%p,%p)\n",iface,ppmk);
405 return CreateAntiMoniker(ppmk);
408 /******************************************************************************
409 * PointerMoniker_CommonPrefixWith
410 ******************************************************************************/
411 static HRESULT WINAPI
412 PointerMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
414 TRACE("(%p, %p)\n", pmkOther, ppmkPrefix);
416 *ppmkPrefix = NULL;
418 if (PointerMonikerImpl_IsEqual(iface, pmkOther))
420 IMoniker_AddRef(iface);
422 *ppmkPrefix=iface;
424 return MK_S_US;
426 else
427 return MK_E_NOPREFIX;
430 /******************************************************************************
431 * PointerMoniker_RelativePathTo
432 ******************************************************************************/
433 static HRESULT WINAPI
434 PointerMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
436 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
438 if (ppmkRelPath==NULL)
439 return E_POINTER;
441 *ppmkRelPath = NULL;
443 return E_NOTIMPL;
446 /******************************************************************************
447 * PointerMoniker_GetDisplayName
448 ******************************************************************************/
449 static HRESULT WINAPI
450 PointerMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
451 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
453 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
455 if (ppszDisplayName==NULL)
456 return E_POINTER;
458 *ppszDisplayName = NULL;
459 return E_NOTIMPL;
462 /******************************************************************************
463 * PointerMoniker_ParseDisplayName
464 ******************************************************************************/
465 static HRESULT WINAPI
466 PointerMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
467 IMoniker* pmkToLeft, LPOLESTR pszDisplayName,
468 ULONG* pchEaten, IMoniker** ppmkOut)
470 PointerMonikerImpl *This = (PointerMonikerImpl *)iface;
471 HRESULT hr;
472 IParseDisplayName *pPDN;
474 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
476 if (pmkToLeft)
477 return MK_E_SYNTAX;
479 if (!This->pObject)
480 return E_UNEXPECTED;
482 hr = IUnknown_QueryInterface(This->pObject, &IID_IParseDisplayName, (void **)&pPDN);
483 if (FAILED(hr))
484 return hr;
486 hr = IParseDisplayName_ParseDisplayName(pPDN, pbc, pszDisplayName, pchEaten, ppmkOut);
487 IParseDisplayName_Release(pPDN);
489 return hr;
492 /******************************************************************************
493 * PointerMoniker_IsSystemMoniker
494 ******************************************************************************/
495 static HRESULT WINAPI
496 PointerMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
498 TRACE("(%p,%p)\n",iface,pwdMksys);
500 if (!pwdMksys)
501 return E_POINTER;
503 *pwdMksys = MKSYS_POINTERMONIKER;
505 return S_OK;
508 /********************************************************************************/
509 /* Virtual function table for the PointerMonikerImpl class which include IPersist,*/
510 /* IPersistStream and IMoniker functions. */
511 static const IMonikerVtbl VT_PointerMonikerImpl =
513 PointerMonikerImpl_QueryInterface,
514 PointerMonikerImpl_AddRef,
515 PointerMonikerImpl_Release,
516 PointerMonikerImpl_GetClassID,
517 PointerMonikerImpl_IsDirty,
518 PointerMonikerImpl_Load,
519 PointerMonikerImpl_Save,
520 PointerMonikerImpl_GetSizeMax,
521 PointerMonikerImpl_BindToObject,
522 PointerMonikerImpl_BindToStorage,
523 PointerMonikerImpl_Reduce,
524 PointerMonikerImpl_ComposeWith,
525 PointerMonikerImpl_Enum,
526 PointerMonikerImpl_IsEqual,
527 PointerMonikerImpl_Hash,
528 PointerMonikerImpl_IsRunning,
529 PointerMonikerImpl_GetTimeOfLastChange,
530 PointerMonikerImpl_Inverse,
531 PointerMonikerImpl_CommonPrefixWith,
532 PointerMonikerImpl_RelativePathTo,
533 PointerMonikerImpl_GetDisplayName,
534 PointerMonikerImpl_ParseDisplayName,
535 PointerMonikerImpl_IsSystemMoniker
538 /******************************************************************************
539 * PointerMoniker_Construct (local function)
540 *******************************************************************************/
541 static void PointerMonikerImpl_Construct(PointerMonikerImpl* This, IUnknown *punk)
543 TRACE("(%p)\n",This);
545 /* Initialize the virtual function table. */
546 This->lpvtbl = &VT_PointerMonikerImpl;
547 This->ref = 1;
548 if (punk)
549 IUnknown_AddRef(punk);
550 This->pObject = punk;
553 /***********************************************************************
554 * CreatePointerMoniker (OLE32.@)
556 * Creates a moniker which represents a pointer.
558 * PARAMS
559 * punk [I] Pointer to the object to represent.
560 * ppmk [O] Address that receives the pointer to the created moniker.
562 * RETURNS
563 * Success: S_OK.
564 * Failure: Any HRESULT code.
566 HRESULT WINAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER *ppmk)
568 PointerMonikerImpl *This;
570 TRACE("(%p, %p)\n", punk, ppmk);
572 if (!ppmk)
573 return E_INVALIDARG;
575 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
576 if (!This)
578 *ppmk = NULL;
579 return E_OUTOFMEMORY;
582 PointerMonikerImpl_Construct(This, punk);
583 *ppmk = (IMoniker *)&This->lpvtbl;
584 return S_OK;
587 static HRESULT WINAPI PointerMonikerCF_QueryInterface(LPCLASSFACTORY iface,
588 REFIID riid, LPVOID *ppv)
590 *ppv = NULL;
591 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
593 *ppv = iface;
594 IUnknown_AddRef(iface);
595 return S_OK;
597 return E_NOINTERFACE;
600 static ULONG WINAPI PointerMonikerCF_AddRef(LPCLASSFACTORY iface)
602 return 2; /* non-heap based object */
605 static ULONG WINAPI PointerMonikerCF_Release(LPCLASSFACTORY iface)
607 return 1; /* non-heap based object */
610 static HRESULT WINAPI PointerMonikerCF_CreateInstance(LPCLASSFACTORY iface,
611 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
613 IMoniker *pMoniker;
614 HRESULT hr;
616 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
618 *ppv = NULL;
620 if (pUnk)
621 return CLASS_E_NOAGGREGATION;
623 hr = CreatePointerMoniker(NULL, &pMoniker);
624 if (FAILED(hr))
625 return hr;
627 hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
629 if (FAILED(hr))
630 IMoniker_Release(pMoniker);
632 return hr;
635 static HRESULT WINAPI PointerMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
637 FIXME("(%d), stub!\n",fLock);
638 return S_OK;
641 static const IClassFactoryVtbl PointerMonikerCFVtbl =
643 PointerMonikerCF_QueryInterface,
644 PointerMonikerCF_AddRef,
645 PointerMonikerCF_Release,
646 PointerMonikerCF_CreateInstance,
647 PointerMonikerCF_LockServer
649 static const IClassFactoryVtbl *PointerMonikerCF = &PointerMonikerCFVtbl;
651 HRESULT PointerMonikerCF_Create(REFIID riid, LPVOID *ppv)
653 return IClassFactory_QueryInterface((IClassFactory *)&PointerMonikerCF, riid, ppv);