odbc32: Don't unload external libraries on process shutdown.
[wine.git] / dlls / ole32 / pointermoniker.c
blob96b580a277d6df39379e69cb72b1c4614dbb9e2e
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 IMoniker IMoniker_iface;
45 LONG ref; /* reference counter for this object */
47 IUnknown *pObject; /* custom marshaler */
48 } PointerMonikerImpl;
50 static inline PointerMonikerImpl *impl_from_IMoniker(IMoniker *iface)
52 return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface);
55 static HRESULT WINAPI
56 PointerMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
58 PointerMonikerImpl *This = impl_from_IMoniker(iface);
60 TRACE("(%p,%p,%p)\n",This,riid,ppvObject);
62 /* Perform a sanity check on the parameters.*/
63 if ( (This==0) || (ppvObject==0) )
64 return E_INVALIDARG;
66 /* Initialize the return parameter */
67 *ppvObject = 0;
69 /* Compare the riid with the interface IDs implemented by this object.*/
70 if (IsEqualIID(&IID_IUnknown, riid) ||
71 IsEqualIID(&IID_IPersist, riid) ||
72 IsEqualIID(&IID_IPersistStream, riid) ||
73 IsEqualIID(&IID_IMoniker, riid))
74 *ppvObject = iface;
76 /* Check that we obtained an interface.*/
77 if ((*ppvObject)==0)
78 return E_NOINTERFACE;
80 /* always increase the reference count by one when it is successful */
81 IMoniker_AddRef(iface);
83 return S_OK;
86 /******************************************************************************
87 * PointerMoniker_AddRef
88 ******************************************************************************/
89 static ULONG WINAPI
90 PointerMonikerImpl_AddRef(IMoniker* iface)
92 PointerMonikerImpl *This = impl_from_IMoniker(iface);
94 TRACE("(%p)\n",This);
96 return InterlockedIncrement(&This->ref);
99 /******************************************************************************
100 * PointerMoniker_Release
101 ******************************************************************************/
102 static ULONG WINAPI
103 PointerMonikerImpl_Release(IMoniker* iface)
105 PointerMonikerImpl *This = impl_from_IMoniker(iface);
106 ULONG ref;
108 TRACE("(%p)\n",This);
110 ref = InterlockedDecrement(&This->ref);
112 /* destroy the object if there's no more reference on it */
113 if (ref == 0)
115 if (This->pObject) IUnknown_Release(This->pObject);
116 HeapFree(GetProcessHeap(),0,This);
119 return ref;
122 /******************************************************************************
123 * PointerMoniker_GetClassID
124 ******************************************************************************/
125 static HRESULT WINAPI
126 PointerMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)
128 TRACE("(%p,%p)\n",iface,pClassID);
130 if (pClassID==NULL)
131 return E_POINTER;
133 *pClassID = CLSID_PointerMoniker;
135 return S_OK;
138 /******************************************************************************
139 * PointerMoniker_IsDirty
140 ******************************************************************************/
141 static HRESULT WINAPI
142 PointerMonikerImpl_IsDirty(IMoniker* iface)
144 /* Note that the OLE-provided implementations of the IPersistStream::IsDirty
145 method in the OLE-provided moniker interfaces always return S_FALSE because
146 their internal state never changes. */
148 TRACE("(%p)\n",iface);
150 return S_FALSE;
153 /******************************************************************************
154 * PointerMoniker_Load
155 ******************************************************************************/
156 static HRESULT WINAPI
157 PointerMonikerImpl_Load(IMoniker* iface,IStream* pStm)
159 TRACE("(%p)\n", pStm);
161 return E_NOTIMPL;
164 /******************************************************************************
165 * PointerMoniker_Save
166 ******************************************************************************/
167 static HRESULT WINAPI
168 PointerMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
170 TRACE("(%p, %d)\n", pStm, fClearDirty);
172 return E_NOTIMPL;
175 /******************************************************************************
176 * PointerMoniker_GetSizeMax
178 * PARAMS
179 * pcbSize [out] Pointer to size of stream needed to save object
180 ******************************************************************************/
181 static HRESULT WINAPI
182 PointerMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
184 TRACE("(%p,%p)\n",iface,pcbSize);
186 if (!pcbSize)
187 return E_POINTER;
189 pcbSize->u.LowPart = 0;
190 pcbSize->u.HighPart = 0;
192 return E_NOTIMPL;
195 /******************************************************************************
196 * PointerMoniker_BindToObject
197 ******************************************************************************/
198 static HRESULT WINAPI
199 PointerMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
200 REFIID riid, VOID** ppvResult)
202 PointerMonikerImpl *This = impl_from_IMoniker(iface);
204 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
206 if (!This->pObject)
207 return E_UNEXPECTED;
209 return IUnknown_QueryInterface(This->pObject, riid, ppvResult);
212 /******************************************************************************
213 * PointerMoniker_BindToStorage
214 ******************************************************************************/
215 static HRESULT WINAPI
216 PointerMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
217 REFIID riid, VOID** ppvResult)
219 PointerMonikerImpl *This = impl_from_IMoniker(iface);
221 TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);
223 if (!This->pObject)
224 return E_UNEXPECTED;
226 return IUnknown_QueryInterface(This->pObject, riid, ppvResult);
229 /******************************************************************************
230 * PointerMoniker_Reduce
231 ******************************************************************************/
232 static HRESULT WINAPI
233 PointerMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
234 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
236 TRACE("(%p,%p,%d,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);
238 if (ppmkReduced==NULL)
239 return E_POINTER;
241 PointerMonikerImpl_AddRef(iface);
243 *ppmkReduced=iface;
245 return MK_S_REDUCED_TO_SELF;
247 /******************************************************************************
248 * PointerMoniker_ComposeWith
249 ******************************************************************************/
250 static HRESULT WINAPI
251 PointerMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
252 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
255 HRESULT res=S_OK;
256 DWORD mkSys,mkSys2;
257 IEnumMoniker* penumMk=0;
258 IMoniker *pmostLeftMk=0;
259 IMoniker* tempMkComposite=0;
261 TRACE("(%p,%d,%p)\n", pmkRight, fOnlyIfNotGeneric, ppmkComposite);
263 if ((ppmkComposite==NULL)||(pmkRight==NULL))
264 return E_POINTER;
266 *ppmkComposite=0;
268 IMoniker_IsSystemMoniker(pmkRight,&mkSys);
270 /* If pmkRight is an anti-moniker, the returned moniker is NULL */
271 if(mkSys==MKSYS_ANTIMONIKER)
272 return res;
274 else
275 /* if pmkRight is a composite whose leftmost component is an anti-moniker, */
276 /* the returned moniker is the composite after the leftmost anti-moniker is removed. */
278 if(mkSys==MKSYS_GENERICCOMPOSITE){
280 res=IMoniker_Enum(pmkRight,TRUE,&penumMk);
282 if (FAILED(res))
283 return res;
285 res=IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL);
287 IMoniker_IsSystemMoniker(pmostLeftMk,&mkSys2);
289 if(mkSys2==MKSYS_ANTIMONIKER){
291 IMoniker_Release(pmostLeftMk);
293 tempMkComposite=iface;
294 IMoniker_AddRef(iface);
296 while(IEnumMoniker_Next(penumMk,1,&pmostLeftMk,NULL)==S_OK){
298 res=CreateGenericComposite(tempMkComposite,pmostLeftMk,ppmkComposite);
300 IMoniker_Release(tempMkComposite);
301 IMoniker_Release(pmostLeftMk);
303 tempMkComposite=*ppmkComposite;
304 IMoniker_AddRef(tempMkComposite);
306 return res;
308 else
309 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
311 /* If pmkRight is not an anti-moniker, the method combines the two monikers into a generic
312 composite if fOnlyIfNotGeneric is FALSE; if fOnlyIfNotGeneric is TRUE, the method returns
313 a NULL moniker and a return value of MK_E_NEEDGENERIC */
314 else
315 if (!fOnlyIfNotGeneric)
316 return CreateGenericComposite(iface,pmkRight,ppmkComposite);
318 else
319 return MK_E_NEEDGENERIC;
322 /******************************************************************************
323 * PointerMoniker_Enum
324 ******************************************************************************/
325 static HRESULT WINAPI
326 PointerMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
328 TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
330 if (ppenumMoniker == NULL)
331 return E_POINTER;
333 *ppenumMoniker = NULL;
335 return S_OK;
338 /******************************************************************************
339 * PointerMoniker_IsEqual
340 ******************************************************************************/
341 static HRESULT WINAPI
342 PointerMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
344 PointerMonikerImpl *This = impl_from_IMoniker(iface);
345 DWORD mkSys;
347 TRACE("(%p,%p)\n",iface,pmkOtherMoniker);
349 if (pmkOtherMoniker==NULL)
350 return S_FALSE;
352 IMoniker_IsSystemMoniker(pmkOtherMoniker,&mkSys);
354 if (mkSys==MKSYS_POINTERMONIKER)
356 PointerMonikerImpl *pOtherMoniker = impl_from_IMoniker(pmkOtherMoniker);
357 return This->pObject == pOtherMoniker->pObject ? S_OK : S_FALSE;
359 else
360 return S_FALSE;
363 /******************************************************************************
364 * PointerMoniker_Hash
365 ******************************************************************************/
366 static HRESULT WINAPI PointerMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
368 PointerMonikerImpl *This = impl_from_IMoniker(iface);
370 if (pdwHash==NULL)
371 return E_POINTER;
373 *pdwHash = PtrToUlong(This->pObject);
375 return S_OK;
378 /******************************************************************************
379 * PointerMoniker_IsRunning
380 ******************************************************************************/
381 static HRESULT WINAPI
382 PointerMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
383 IMoniker* pmkNewlyRunning)
385 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pmkNewlyRunning);
387 return S_OK;
390 /******************************************************************************
391 * PointerMoniker_GetTimeOfLastChange
392 ******************************************************************************/
393 static HRESULT WINAPI PointerMonikerImpl_GetTimeOfLastChange(IMoniker* iface,
394 IBindCtx* pbc,
395 IMoniker* pmkToLeft,
396 FILETIME* pAntiTime)
398 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pAntiTime);
399 return E_NOTIMPL;
402 /******************************************************************************
403 * PointerMoniker_Inverse
404 ******************************************************************************/
405 static HRESULT WINAPI
406 PointerMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)
408 TRACE("(%p,%p)\n",iface,ppmk);
410 return CreateAntiMoniker(ppmk);
413 /******************************************************************************
414 * PointerMoniker_CommonPrefixWith
415 ******************************************************************************/
416 static HRESULT WINAPI
417 PointerMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
419 TRACE("(%p, %p)\n", pmkOther, ppmkPrefix);
421 *ppmkPrefix = NULL;
423 if (PointerMonikerImpl_IsEqual(iface, pmkOther))
425 IMoniker_AddRef(iface);
427 *ppmkPrefix=iface;
429 return MK_S_US;
431 else
432 return MK_E_NOPREFIX;
435 /******************************************************************************
436 * PointerMoniker_RelativePathTo
437 ******************************************************************************/
438 static HRESULT WINAPI
439 PointerMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
441 TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);
443 if (ppmkRelPath==NULL)
444 return E_POINTER;
446 *ppmkRelPath = NULL;
448 return E_NOTIMPL;
451 /******************************************************************************
452 * PointerMoniker_GetDisplayName
453 ******************************************************************************/
454 static HRESULT WINAPI
455 PointerMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
456 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
458 TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
460 if (ppszDisplayName==NULL)
461 return E_POINTER;
463 *ppszDisplayName = NULL;
464 return E_NOTIMPL;
467 /******************************************************************************
468 * PointerMoniker_ParseDisplayName
469 ******************************************************************************/
470 static HRESULT WINAPI
471 PointerMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
472 IMoniker* pmkToLeft, LPOLESTR pszDisplayName,
473 ULONG* pchEaten, IMoniker** ppmkOut)
475 PointerMonikerImpl *This = impl_from_IMoniker(iface);
476 HRESULT hr;
477 IParseDisplayName *pPDN;
479 TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
481 if (pmkToLeft)
482 return MK_E_SYNTAX;
484 if (!This->pObject)
485 return E_UNEXPECTED;
487 hr = IUnknown_QueryInterface(This->pObject, &IID_IParseDisplayName, (void **)&pPDN);
488 if (FAILED(hr))
489 return hr;
491 hr = IParseDisplayName_ParseDisplayName(pPDN, pbc, pszDisplayName, pchEaten, ppmkOut);
492 IParseDisplayName_Release(pPDN);
494 return hr;
497 /******************************************************************************
498 * PointerMoniker_IsSystemMoniker
499 ******************************************************************************/
500 static HRESULT WINAPI
501 PointerMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
503 TRACE("(%p,%p)\n",iface,pwdMksys);
505 if (!pwdMksys)
506 return E_POINTER;
508 *pwdMksys = MKSYS_POINTERMONIKER;
510 return S_OK;
513 /********************************************************************************/
514 /* Virtual function table for the PointerMonikerImpl class which include IPersist,*/
515 /* IPersistStream and IMoniker functions. */
516 static const IMonikerVtbl VT_PointerMonikerImpl =
518 PointerMonikerImpl_QueryInterface,
519 PointerMonikerImpl_AddRef,
520 PointerMonikerImpl_Release,
521 PointerMonikerImpl_GetClassID,
522 PointerMonikerImpl_IsDirty,
523 PointerMonikerImpl_Load,
524 PointerMonikerImpl_Save,
525 PointerMonikerImpl_GetSizeMax,
526 PointerMonikerImpl_BindToObject,
527 PointerMonikerImpl_BindToStorage,
528 PointerMonikerImpl_Reduce,
529 PointerMonikerImpl_ComposeWith,
530 PointerMonikerImpl_Enum,
531 PointerMonikerImpl_IsEqual,
532 PointerMonikerImpl_Hash,
533 PointerMonikerImpl_IsRunning,
534 PointerMonikerImpl_GetTimeOfLastChange,
535 PointerMonikerImpl_Inverse,
536 PointerMonikerImpl_CommonPrefixWith,
537 PointerMonikerImpl_RelativePathTo,
538 PointerMonikerImpl_GetDisplayName,
539 PointerMonikerImpl_ParseDisplayName,
540 PointerMonikerImpl_IsSystemMoniker
543 /******************************************************************************
544 * PointerMoniker_Construct (local function)
545 *******************************************************************************/
546 static void PointerMonikerImpl_Construct(PointerMonikerImpl* This, IUnknown *punk)
548 TRACE("(%p)\n",This);
550 /* Initialize the virtual function table. */
551 This->IMoniker_iface.lpVtbl = &VT_PointerMonikerImpl;
552 This->ref = 1;
553 if (punk)
554 IUnknown_AddRef(punk);
555 This->pObject = punk;
558 /***********************************************************************
559 * CreatePointerMoniker (OLE32.@)
561 * Creates a moniker which represents a pointer.
563 * PARAMS
564 * punk [I] Pointer to the object to represent.
565 * ppmk [O] Address that receives the pointer to the created moniker.
567 * RETURNS
568 * Success: S_OK.
569 * Failure: Any HRESULT code.
571 HRESULT WINAPI CreatePointerMoniker(LPUNKNOWN punk, LPMONIKER *ppmk)
573 PointerMonikerImpl *This;
575 TRACE("(%p, %p)\n", punk, ppmk);
577 if (!ppmk)
578 return E_INVALIDARG;
580 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
581 if (!This)
583 *ppmk = NULL;
584 return E_OUTOFMEMORY;
587 PointerMonikerImpl_Construct(This, punk);
588 *ppmk = &This->IMoniker_iface;
589 return S_OK;
592 static HRESULT WINAPI PointerMonikerCF_QueryInterface(LPCLASSFACTORY iface,
593 REFIID riid, LPVOID *ppv)
595 *ppv = NULL;
596 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
598 *ppv = iface;
599 IClassFactory_AddRef(iface);
600 return S_OK;
602 return E_NOINTERFACE;
605 static ULONG WINAPI PointerMonikerCF_AddRef(LPCLASSFACTORY iface)
607 return 2; /* non-heap based object */
610 static ULONG WINAPI PointerMonikerCF_Release(LPCLASSFACTORY iface)
612 return 1; /* non-heap based object */
615 static HRESULT WINAPI PointerMonikerCF_CreateInstance(LPCLASSFACTORY iface,
616 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
618 IMoniker *pMoniker;
619 HRESULT hr;
621 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
623 *ppv = NULL;
625 if (pUnk)
626 return CLASS_E_NOAGGREGATION;
628 hr = CreatePointerMoniker(NULL, &pMoniker);
629 if (FAILED(hr))
630 return hr;
632 hr = IMoniker_QueryInterface(pMoniker, riid, ppv);
634 if (FAILED(hr))
635 IMoniker_Release(pMoniker);
637 return hr;
640 static HRESULT WINAPI PointerMonikerCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
642 FIXME("(%d), stub!\n",fLock);
643 return S_OK;
646 static const IClassFactoryVtbl PointerMonikerCFVtbl =
648 PointerMonikerCF_QueryInterface,
649 PointerMonikerCF_AddRef,
650 PointerMonikerCF_Release,
651 PointerMonikerCF_CreateInstance,
652 PointerMonikerCF_LockServer
654 static const IClassFactoryVtbl *PointerMonikerCF = &PointerMonikerCFVtbl;
656 HRESULT PointerMonikerCF_Create(REFIID riid, LPVOID *ppv)
658 return IClassFactory_QueryInterface((IClassFactory *)&PointerMonikerCF, riid, ppv);