2025-04-27 07:49:33 -04:00

290 lines
5.8 KiB
C++

/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
DLLMAIN.CPP
Abstract:
DLL/COM helpers.
History:
--*/
#include "precomp.h"
#include "commain.cpp"
#define DBG_PRINTFA( a ) { char pBuff[256]; sprintf a ; OutputDebugStringA(pBuff); }
class CDllLifeControl : public CLifeControl
{
protected:
long m_lCount;
public:
CDllLifeControl() : m_lCount(0) {}
virtual BOOL ObjectCreated(IUnknown* pv)
{
InterlockedIncrement(&m_lCount);
//DBG_PRINTFA((pBuff,"+ %p\n",pv));
return TRUE;
}
virtual void ObjectDestroyed(IUnknown* pv)
{
InterlockedDecrement(&m_lCount);
//DBG_PRINTFA((pBuff,"- %p\n",pv));
}
virtual void AddRef(IUnknown* pv){}
virtual void Release(IUnknown* pv){}
HRESULT CanUnloadNow()
{
HRESULT hRes = (m_lCount == 0)?S_OK:S_FALSE;
//DBG_PRINTFA((pBuff,"CanUnloadNow %08x\n",hRes));
return hRes;
}
};
static CMyCritSec g_CS;
static BOOL g_bInit = FALSE;
static BOOL g_fAttached = FALSE;
CLifeControl* g_pLifeControl = NULL;
//
// these 2 functions assume that g_CS is held.
//
HRESULT EnsureInitialized()
{
HRESULT hr;
if ( g_bInit )
{
return S_OK;
}
g_pLifeControl = new CDllLifeControl;
if ( g_pLifeControl == NULL )
{
return E_OUTOFMEMORY;
}
hr = GlobalInitialize();
if ( FAILED(hr) )
{
return hr;
}
g_bInit = TRUE;
return S_OK;
}
void EnsureUninitialized()
{
if ( g_bInit )
{
GlobalUninitialize();
delete g_pLifeControl;
g_pLifeControl = NULL;
g_bInit = FALSE;
}
}
//***************************************************************************
//
// DllGetClassObject
//
// Purpose: Called by Ole when some client wants a a class factory. Return
// one only if it is the sort of class this DLL supports.
//
//***************************************************************************
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void** ppv)
{
HRESULT hr;
CMyInCritSec ics( &g_CS );
if ( !g_fAttached )
{
return E_UNEXPECTED;
}
hr = EnsureInitialized();
if ( FAILED(hr) )
{
return hr;
}
for(int i = 0; i < g_pClassInfos->size(); i++)
{
CClassInfo* pInfo = (*g_pClassInfos)[i];
if(*pInfo->m_pClsid == rclsid)
{
return pInfo->m_pFactory->QueryInterface(riid, ppv);
}
}
return E_FAIL;
}
//***************************************************************************
//
// DllCanUnloadNow
//
// Purpose: Called periodically by Ole in order to determine if the
// DLL can be freed.//
// Return: TRUE if there are no objects in use and the class factory
// isn't locked.
//***************************************************************************
STDAPI DllCanUnloadNow(void)
{
CMyInCritSec ics( &g_CS );
if ( !g_fAttached )
{
return S_FALSE;
}
if ( !g_bInit )
{
return S_OK;
}
HRESULT hres = ((CDllLifeControl*)g_pLifeControl)->CanUnloadNow();
if( hres == S_OK )
{
if ( GlobalCanShutdown() )
{
EnsureUninitialized();
return S_OK;
}
}
return S_FALSE;
}
//***************************************************************************
//
// DllRegisterServer
//
// Purpose: Called during initialization or by regsvr32.
//
// Return: NOERROR if registration successful, error otherwise.
//***************************************************************************
STDAPI DllRegisterServer(void)
{
HRESULT hr;
CMyInCritSec ics( &g_CS );
if ( !g_fAttached )
{
return E_UNEXPECTED;
}
hr = EnsureInitialized();
if ( FAILED(hr) )
{
return hr;
}
GlobalRegister();
if ( NULL == g_pClassInfos )
{
return E_FAIL;
}
for(int i = 0; i < g_pClassInfos->size(); i++)
{
CClassInfo* pInfo = (*g_pClassInfos)[i];
HRESULT hres = RegisterServer(pInfo, FALSE);
if(FAILED(hres)) return hres;
}
return S_OK;
}
//***************************************************************************
//
// DllUnregisterServer
//
// Purpose: Called when it is time to remove the registry entries.
//
// Return: NOERROR if registration successful, error otherwise.
//***************************************************************************
STDAPI DllUnregisterServer(void)
{
HRESULT hr;
CMyInCritSec ics( &g_CS );
if ( !g_fAttached )
{
return E_UNEXPECTED;
}
hr = EnsureInitialized();
if ( FAILED(hr) )
{
return hr;
}
GlobalUnregister();
if ( NULL == g_pClassInfos )
{
return E_FAIL;
}
for(int i = 0; i < g_pClassInfos->size(); i++)
{
CClassInfo* pInfo = (*g_pClassInfos)[i];
HRESULT hres = UnregisterServer(pInfo, FALSE);
if(FAILED(hres)) return hres;
}
return S_OK;
}
BOOL WINAPI DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved)
{
if (DLL_PROCESS_ATTACH==ulReason)
{
SetModuleHandle(hInstance);
g_fAttached = TRUE;
DisableThreadLibraryCalls ( hInstance ) ;
}
else if(DLL_PROCESS_DETACH==ulReason)
{
if ( g_fAttached )
{
GlobalPostUninitialize();
}
// This will prevent us from performing any other logic
// until we are attached to again.
g_fAttached = FALSE;
}
return TRUE;
}