2 * A basic implementation for COM DLL implementor.
4 * Copyright (C) Hidenori TAKESHIMA <hidenori@a2.ctktv.ne.jp>
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(comimpl);
37 - All threading model including Apartment and Both are supported.
38 - Aggregation is supported.
39 - CoFreeUnusedLibraries() is supported.
40 - DisableThreadLibraryCalls() is supported.
43 static CRITICAL_SECTION csComImpl;
44 static DWORD dwComImplRef;
48 IUnknown_fnQueryInterface(IUnknown* iface,REFIID riid,LPVOID *ppobj)
50 ICOM_THIS(COMIMPL_IUnkImpl,iface);
53 COMIMPL_IFDelegation* pDelegation;
56 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
64 if ( IsEqualGUID( &IID_IUnknown, riid ) )
66 TRACE("IID_IUnknown - returns inner object.\n");
70 for ( dwIndex = 0; dwIndex < This->dwEntries; dwIndex++ )
72 if ( IsEqualGUID( This->pEntries[dwIndex].piid, riid ) )
74 ofs = This->pEntries[dwIndex].ofsVTPtr;
78 if ( dwIndex == This->dwEntries )
83 pDelegation = This->pDelegationFirst;
84 while ( pDelegation != NULL )
86 hr = (*pDelegation->pOnQueryInterface)( iface, riid, ppobj );
87 if ( hr != E_NOINTERFACE )
89 pDelegation = pDelegation->pNext;
92 if ( hr == E_NOINTERFACE )
94 FIXME("(%p) unknown interface: %s\n",This,debugstr_guid(riid));
101 *ppobj = (LPVOID)(((char*)This) + ofs);
102 IUnknown_AddRef((IUnknown*)(*ppobj));
108 IUnknown_fnAddRef(IUnknown* iface)
110 ICOM_THIS(COMIMPL_IUnkImpl,iface);
112 TRACE("(%p)->()\n",This);
114 return InterlockedExchangeAdd(&(This->ref),1) + 1;
118 IUnknown_fnRelease(IUnknown* iface)
120 ICOM_THIS(COMIMPL_IUnkImpl,iface);
123 TRACE("(%p)->()\n",This);
124 ref = InterlockedExchangeAdd(&(This->ref),-1) - 1;
129 if ( This->pOnFinalRelease != NULL )
130 (*(This->pOnFinalRelease))(iface);
133 COMIMPL_FreeObj(This);
139 static ICOM_VTABLE(IUnknown) iunknown =
141 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
142 /* IUnknown fields */
143 IUnknown_fnQueryInterface,
149 void COMIMPL_IUnkInit( COMIMPL_IUnkImpl* pImpl, IUnknown* punkOuter )
151 TRACE("(%p)\n",pImpl);
153 ICOM_VTBL(pImpl) = &iunknown;
154 pImpl->pEntries = NULL;
155 pImpl->dwEntries = 0;
156 pImpl->pDelegationFirst = NULL;
157 pImpl->pOnFinalRelease = NULL;
159 pImpl->punkControl = (IUnknown*)pImpl;
161 /* for implementing aggregation. */
162 if ( punkOuter != NULL )
163 pImpl->punkControl = punkOuter;
166 void COMIMPL_IUnkAddDelegationHandler(
167 COMIMPL_IUnkImpl* pImpl, COMIMPL_IFDelegation* pDelegation )
169 pDelegation->pNext = pImpl->pDelegationFirst;
170 pImpl->pDelegationFirst = pDelegation;
175 /************************************************************************/
178 static HRESULT WINAPI
179 IClassFactory_fnQueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj);
180 static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface);
181 static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface);
182 static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj);
183 static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface,BOOL dolock);
185 static ICOM_VTABLE(IClassFactory) iclassfact =
187 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
188 IClassFactory_fnQueryInterface,
189 IClassFactory_fnAddRef,
190 IClassFactory_fnRelease,
191 IClassFactory_fnCreateInstance,
192 IClassFactory_fnLockServer
197 /* IUnknown fields */
198 ICOM_VFIELD(IClassFactory);
200 /* IClassFactory fields */
201 const COMIMPL_CLASSENTRY* pEntry;
205 static HRESULT WINAPI
206 IClassFactory_fnQueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
208 ICOM_THIS(IClassFactoryImpl,iface);
210 TRACE("(%p)->(%p,%p)\n",This,riid,ppobj);
211 if ( ( IsEqualGUID( &IID_IUnknown, riid ) ) ||
212 ( IsEqualGUID( &IID_IClassFactory, riid ) ) )
215 IClassFactory_AddRef(iface);
219 return E_NOINTERFACE;
222 static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface)
224 ICOM_THIS(IClassFactoryImpl,iface);
226 TRACE("(%p)->()\n",This);
228 return InterlockedExchangeAdd(&(This->ref),1) + 1;
231 static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface)
233 ICOM_THIS(IClassFactoryImpl,iface);
236 TRACE("(%p)->()\n",This);
237 ref = InterlockedExchangeAdd(&(This->ref),-1) - 1;
241 COMIMPL_FreeObj(This);
245 static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj)
247 ICOM_THIS(IClassFactoryImpl,iface);
251 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
255 if ( pOuter != NULL && !IsEqualGUID( riid, &IID_IUnknown ) )
256 return CLASS_E_NOAGGREGATION;
260 hr = (*This->pEntry->pCreateIUnk)(pOuter,(void**)&punk);
264 hr = IUnknown_QueryInterface(punk,riid,ppobj);
265 IUnknown_Release(punk);
270 static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface,BOOL dolock)
272 ICOM_THIS(IClassFactoryImpl,iface);
275 TRACE("(%p)->(%d)\n",This,dolock);
277 hr = IClassFactory_AddRef(iface);
279 hr = IClassFactory_Release(iface);
286 static HRESULT IClassFactory_Alloc( const CLSID* pclsid, void** ppobj )
288 const COMIMPL_CLASSENTRY* pEntry;
289 IClassFactoryImpl* pImpl;
291 TRACE( "(%s,%p)\n", debugstr_guid(pclsid), ppobj );
293 pEntry = COMIMPL_ClassList;
294 while ( pEntry->pclsid != NULL )
296 if ( IsEqualGUID( pclsid, pEntry->pclsid ) )
301 return CLASS_E_CLASSNOTAVAILABLE;
303 pImpl = (IClassFactoryImpl*)COMIMPL_AllocObj( sizeof(IClassFactoryImpl) );
305 return E_OUTOFMEMORY;
307 TRACE( "allocated successfully.\n" );
309 ICOM_VTBL(pImpl) = &iclassfact;
311 pImpl->pEntry = pEntry;
313 *ppobj = (void*)pImpl;
320 /***********************************************************************
321 * COMIMPL_InitProcess (internal)
323 static BOOL COMIMPL_InitProcess( HINSTANCE hInstDLL )
328 InitializeCriticalSection( &csComImpl );
330 #ifndef COMIMPL_PERTHREAD_INIT
331 DisableThreadLibraryCalls((HMODULE)hInstDLL);
332 #endif /* COMIMPL_PERTHREAD_INIT */
337 /***********************************************************************
338 * COMIMPL_UninitProcess (internal)
340 static void COMIMPL_UninitProcess( HINSTANCE hInstDLL )
342 CHAR szThisDLL[ MAX_PATH ];
346 if ( dwComImplRef != 0 )
349 if ( !GetModuleFileNameA( (HMODULE)hInstDLL, szThisDLL, MAX_PATH ) )
351 ERR( "you must release some objects allocated from %s.\n", szThisDLL );
353 DeleteCriticalSection( &csComImpl );
357 /***********************************************************************
360 BOOL WINAPI COMIMPL_DllMain(
361 HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved )
363 TRACE("(%08x,%08lx,%p)\n",hInstDLL,fdwReason,lpvReserved);
367 case DLL_PROCESS_ATTACH:
368 if ( !COMIMPL_InitProcess( hInstDLL ) )
371 case DLL_PROCESS_DETACH:
372 COMIMPL_UninitProcess( hInstDLL );
374 case DLL_THREAD_ATTACH:
376 case DLL_THREAD_DETACH:
383 /***********************************************************************
384 * COMIMPL_DllGetClassObject
386 HRESULT WINAPI COMIMPL_DllGetClassObject(
387 const CLSID* pclsid,const IID* piid,void** ppv)
390 if ( IsEqualGUID( &IID_IUnknown, piid ) ||
391 IsEqualGUID( &IID_IClassFactory, piid ) )
393 return IClassFactory_Alloc( pclsid, ppv );
396 return CLASS_E_CLASSNOTAVAILABLE;
399 /***********************************************************************
400 * COMIMPL_DllCanUnloadNow
406 HRESULT WINAPI COMIMPL_DllCanUnloadNow(void)
410 EnterCriticalSection( &csComImpl );
411 hr = ( dwComImplRef == 0 ) ? S_OK : S_FALSE;
412 LeaveCriticalSection( &csComImpl );
417 /***********************************************************************
420 void* COMIMPL_AllocObj( DWORD dwSize )
424 EnterCriticalSection( &csComImpl );
426 pv = HeapAlloc( COMIMPL_hHeap, 0, dwSize );
429 LeaveCriticalSection( &csComImpl );
434 /***********************************************************************
437 void COMIMPL_FreeObj( void* pobj )
439 EnterCriticalSection( &csComImpl );
440 HeapFree( COMIMPL_hHeap, 0, pobj );
442 LeaveCriticalSection( &csComImpl );