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
);