Writes to stdout and VGA_WriteChars routine now update both VGA
[wine/wine64.git] / dlls / shdocvw / comimpl.c
blob65f73e7c81ebac85654cc69aa1ec5008b0467b21
1 /*
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
21 #include "config.h"
23 #include "windef.h"
24 #include "winerror.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "winnls.h"
29 #include "ole2.h"
31 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(comimpl);
34 #include "comimpl.h"
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;
47 static HRESULT WINAPI
48 IUnknown_fnQueryInterface(IUnknown* iface,REFIID riid,LPVOID *ppobj)
50 ICOM_THIS(COMIMPL_IUnkImpl,iface);
51 size_t ofs;
52 DWORD dwIndex;
53 COMIMPL_IFDelegation* pDelegation;
54 HRESULT hr;
56 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
58 if ( ppobj == NULL )
59 return E_POINTER;
60 *ppobj = NULL;
62 ofs = 0;
64 if ( IsEqualGUID( &IID_IUnknown, riid ) )
66 TRACE("IID_IUnknown - returns inner object.\n");
68 else
70 for ( dwIndex = 0; dwIndex < This->dwEntries; dwIndex++ )
72 if ( IsEqualGUID( This->pEntries[dwIndex].piid, riid ) )
74 ofs = This->pEntries[dwIndex].ofsVTPtr;
75 break;
78 if ( dwIndex == This->dwEntries )
80 hr = E_NOINTERFACE;
82 /* delegation */
83 pDelegation = This->pDelegationFirst;
84 while ( pDelegation != NULL )
86 hr = (*pDelegation->pOnQueryInterface)( iface, riid, ppobj );
87 if ( hr != E_NOINTERFACE )
88 break;
89 pDelegation = pDelegation->pNext;
92 if ( hr == E_NOINTERFACE )
94 FIXME("(%p) unknown interface: %s\n",This,debugstr_guid(riid));
97 return hr;
101 *ppobj = (LPVOID)(((char*)This) + ofs);
102 IUnknown_AddRef((IUnknown*)(*ppobj));
104 return S_OK;
107 static ULONG WINAPI
108 IUnknown_fnAddRef(IUnknown* iface)
110 ICOM_THIS(COMIMPL_IUnkImpl,iface);
112 TRACE("(%p)->()\n",This);
114 return InterlockedExchangeAdd(&(This->ref),1) + 1;
117 static ULONG WINAPI
118 IUnknown_fnRelease(IUnknown* iface)
120 ICOM_THIS(COMIMPL_IUnkImpl,iface);
121 LONG ref;
123 TRACE("(%p)->()\n",This);
124 ref = InterlockedExchangeAdd(&(This->ref),-1) - 1;
125 if ( ref > 0 )
126 return (ULONG)ref;
128 This->ref ++;
129 if ( This->pOnFinalRelease != NULL )
130 (*(This->pOnFinalRelease))(iface);
131 This->ref --;
133 COMIMPL_FreeObj(This);
135 return 0;
139 static ICOM_VTABLE(IUnknown) iunknown =
141 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
142 /* IUnknown fields */
143 IUnknown_fnQueryInterface,
144 IUnknown_fnAddRef,
145 IUnknown_fnRelease,
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;
158 pImpl->ref = 1;
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
195 typedef struct
197 /* IUnknown fields */
198 ICOM_VFIELD(IClassFactory);
199 LONG ref;
200 /* IClassFactory fields */
201 const COMIMPL_CLASSENTRY* pEntry;
202 } IClassFactoryImpl;
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 ) ) )
214 *ppobj = iface;
215 IClassFactory_AddRef(iface);
216 return S_OK;
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);
234 LONG ref;
236 TRACE("(%p)->()\n",This);
237 ref = InterlockedExchangeAdd(&(This->ref),-1) - 1;
238 if ( ref > 0 )
239 return (ULONG)ref;
241 COMIMPL_FreeObj(This);
242 return 0;
245 static HRESULT WINAPI IClassFactory_fnCreateInstance(LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj)
247 ICOM_THIS(IClassFactoryImpl,iface);
248 HRESULT hr;
249 IUnknown* punk;
251 TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
253 if ( ppobj == NULL )
254 return E_POINTER;
255 if ( pOuter != NULL && !IsEqualGUID( riid, &IID_IUnknown ) )
256 return CLASS_E_NOAGGREGATION;
258 *ppobj = NULL;
260 hr = (*This->pEntry->pCreateIUnk)(pOuter,(void**)&punk);
261 if ( hr != S_OK )
262 return hr;
264 hr = IUnknown_QueryInterface(punk,riid,ppobj);
265 IUnknown_Release(punk);
267 return hr;
270 static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface,BOOL dolock)
272 ICOM_THIS(IClassFactoryImpl,iface);
273 HRESULT hr;
275 TRACE("(%p)->(%d)\n",This,dolock);
276 if (dolock)
277 hr = IClassFactory_AddRef(iface);
278 else
279 hr = IClassFactory_Release(iface);
281 return hr;
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 ) )
297 goto found;
298 pEntry ++;
301 return CLASS_E_CLASSNOTAVAILABLE;
302 found:
303 pImpl = (IClassFactoryImpl*)COMIMPL_AllocObj( sizeof(IClassFactoryImpl) );
304 if ( pImpl == NULL )
305 return E_OUTOFMEMORY;
307 TRACE( "allocated successfully.\n" );
309 ICOM_VTBL(pImpl) = &iclassfact;
310 pImpl->ref = 1;
311 pImpl->pEntry = pEntry;
313 *ppobj = (void*)pImpl;
314 return S_OK;
320 /***********************************************************************
321 * COMIMPL_InitProcess (internal)
323 static BOOL COMIMPL_InitProcess( HINSTANCE hInstDLL )
325 TRACE("()\n");
327 dwComImplRef = 0;
328 InitializeCriticalSection( &csComImpl );
330 #ifndef COMIMPL_PERTHREAD_INIT
331 DisableThreadLibraryCalls((HMODULE)hInstDLL);
332 #endif /* COMIMPL_PERTHREAD_INIT */
334 return TRUE;
337 /***********************************************************************
338 * COMIMPL_UninitProcess (internal)
340 static void COMIMPL_UninitProcess( HINSTANCE hInstDLL )
342 CHAR szThisDLL[ MAX_PATH ];
344 TRACE("()\n");
346 if ( dwComImplRef != 0 )
348 szThisDLL[0] = '\0';
349 if ( !GetModuleFileNameA( (HMODULE)hInstDLL, szThisDLL, MAX_PATH ) )
350 szThisDLL[0] = '\0';
351 ERR( "you must release some objects allocated from %s.\n", szThisDLL );
353 DeleteCriticalSection( &csComImpl );
357 /***********************************************************************
358 * COMIMPL_DllMain
360 BOOL WINAPI COMIMPL_DllMain(
361 HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved )
363 TRACE("(%08x,%08lx,%p)\n",hInstDLL,fdwReason,lpvReserved);
365 switch ( fdwReason )
367 case DLL_PROCESS_ATTACH:
368 if ( !COMIMPL_InitProcess( hInstDLL ) )
369 return FALSE;
370 break;
371 case DLL_PROCESS_DETACH:
372 COMIMPL_UninitProcess( hInstDLL );
373 break;
374 case DLL_THREAD_ATTACH:
375 break;
376 case DLL_THREAD_DETACH:
377 break;
380 return TRUE;
383 /***********************************************************************
384 * COMIMPL_DllGetClassObject
386 HRESULT WINAPI COMIMPL_DllGetClassObject(
387 const CLSID* pclsid,const IID* piid,void** ppv)
389 *ppv = NULL;
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
402 * RETURNS
403 * Success: S_OK
404 * Failure: S_FALSE
406 HRESULT WINAPI COMIMPL_DllCanUnloadNow(void)
408 HRESULT hr;
410 EnterCriticalSection( &csComImpl );
411 hr = ( dwComImplRef == 0 ) ? S_OK : S_FALSE;
412 LeaveCriticalSection( &csComImpl );
414 return hr;
417 /***********************************************************************
418 * COMIMPL_AllocObj
420 void* COMIMPL_AllocObj( DWORD dwSize )
422 void* pv;
424 EnterCriticalSection( &csComImpl );
425 dwComImplRef ++;
426 pv = HeapAlloc( COMIMPL_hHeap, 0, dwSize );
427 if ( pv == NULL )
428 dwComImplRef --;
429 LeaveCriticalSection( &csComImpl );
431 return pv;
434 /***********************************************************************
435 * COMIMPL_FreeObj
437 void COMIMPL_FreeObj( void* pobj )
439 EnterCriticalSection( &csComImpl );
440 HeapFree( COMIMPL_hHeap, 0, pobj );
441 dwComImplRef --;
442 LeaveCriticalSection( &csComImpl );