You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
273 lines
5.8 KiB
273 lines
5.8 KiB
/*++
|
|
|
|
Copyright (C) 1996-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
DLLMAIN.CPP
|
|
|
|
Abstract:
|
|
|
|
DLL/COM helpers.
|
|
|
|
History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include "commain.cpp"
|
|
|
|
#include <statsync.h>
|
|
|
|
void EmptyList();
|
|
|
|
class CDllLifeControl : public CLifeControl
|
|
{
|
|
protected:
|
|
long m_lCount;
|
|
public:
|
|
CDllLifeControl() : m_lCount(0) {}
|
|
|
|
virtual BOOL ObjectCreated(IUnknown* pv)
|
|
{
|
|
InterlockedIncrement(&m_lCount);
|
|
return TRUE;
|
|
}
|
|
virtual void ObjectDestroyed(IUnknown* pv)
|
|
{
|
|
InterlockedDecrement(&m_lCount);
|
|
}
|
|
virtual void AddRef(IUnknown* pv){}
|
|
virtual void Release(IUnknown* pv){}
|
|
|
|
HRESULT CanUnloadNow()
|
|
{
|
|
HRESULT hRes = (m_lCount == 0)?S_OK:S_FALSE;
|
|
return hRes;
|
|
}
|
|
};
|
|
|
|
CStaticCritSec g_CS;
|
|
static BOOL g_bInit = FALSE;
|
|
static BOOL g_fAttached = FALSE;
|
|
CDllLifeControl g_LifeControl;
|
|
CLifeControl* g_pLifeControl = &g_LifeControl;
|
|
|
|
//
|
|
// these 2 functions assume that g_CS is held.
|
|
//
|
|
|
|
HRESULT EnsureInitialized()
|
|
{
|
|
HRESULT hr;
|
|
|
|
if ( g_bInit )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
hr = GlobalInitialize();
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
g_bInit = TRUE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void EnsureUninitialized()
|
|
{
|
|
if ( g_bInit )
|
|
{
|
|
GlobalUninitialize();
|
|
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;
|
|
|
|
if ( !g_fAttached ) return E_UNEXPECTED;
|
|
|
|
CMyInCritSec ics( &g_CS );
|
|
|
|
if ( !g_fAttached ) return E_UNEXPECTED;
|
|
|
|
hr = EnsureInitialized();
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
for(LIST_ENTRY * pEntry = g_ClassInfoHead.Flink;
|
|
pEntry != &g_ClassInfoHead ;
|
|
pEntry = pEntry->Flink)
|
|
{
|
|
CClassInfo* pInfo = CONTAINING_RECORD(pEntry,CClassInfo,m_Entry);
|
|
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)
|
|
{
|
|
|
|
if ( !g_fAttached ) return S_FALSE;
|
|
|
|
CMyInCritSec ics( &g_CS );
|
|
|
|
if ( !g_fAttached ) return S_FALSE;
|
|
|
|
if ( !g_bInit )
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT hres = g_LifeControl.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;
|
|
|
|
if ( !g_fAttached ) return E_UNEXPECTED;
|
|
CMyInCritSec ics( &g_CS );
|
|
if ( !g_fAttached ) return E_UNEXPECTED;
|
|
|
|
hr = EnsureInitialized();
|
|
|
|
if ( FAILED(hr) ) return hr;
|
|
|
|
|
|
GlobalRegister();
|
|
|
|
for(LIST_ENTRY * pEntry = g_ClassInfoHead.Flink;
|
|
pEntry != &g_ClassInfoHead;
|
|
pEntry = pEntry->Flink)
|
|
{
|
|
CClassInfo* pInfo = CONTAINING_RECORD(pEntry,CClassInfo,m_Entry);
|
|
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;
|
|
|
|
if ( !g_fAttached ) return E_UNEXPECTED;
|
|
CMyInCritSec ics( &g_CS );
|
|
if ( !g_fAttached ) return E_UNEXPECTED;
|
|
|
|
|
|
hr = EnsureInitialized();
|
|
|
|
if ( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
GlobalUnregister();
|
|
|
|
for(LIST_ENTRY * pEntry = g_ClassInfoHead.Flink;
|
|
pEntry != &g_ClassInfoHead;
|
|
pEntry = pEntry->Flink)
|
|
{
|
|
CClassInfo* pInfo = CONTAINING_RECORD(pEntry,CClassInfo,m_Entry);
|
|
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 ) ;
|
|
if (CStaticCritSec::anyFailure())
|
|
return FALSE;
|
|
}
|
|
else if(DLL_PROCESS_DETACH==ulReason)
|
|
{
|
|
if ( g_fAttached )
|
|
{
|
|
GlobalPostUninitialize();
|
|
|
|
CMyInCritSec ics( &g_CS );
|
|
EmptyList();
|
|
}
|
|
|
|
// This will prevent us from performing any other logic
|
|
// until we are attached to again.
|
|
g_fAttached = FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|