Leaked source code of windows server 2003
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

/*++
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;
}