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.
 
 
 
 
 
 

591 lines
12 KiB

//=================================================================
//
// PowerManagement.cpp --
//
// Copyright 1999- 2002 Microsoft Corporation
//
//=================================================================
#include "precomp.h"
#include <ntddip.h>
#include <ntddtcp.h>
#include "CIpRouteEvent.h"
#include <provexpt.h>
LONG CIPRouteEventProviderClassFactory::s_ObjectsInProgress = 0 ;
LONG CIPRouteEventProviderClassFactory::s_LocksInProgress = 0 ;
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Class: CIPRouteEventProviderClassFactory
Description: Provides class factory support for power management events
Derivations: public IClassFactory
Caveats:
Raid:
History: a-peterc 31-Mar-1999 Created
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
//
CIPRouteEventProviderClassFactory :: CIPRouteEventProviderClassFactory () : m_ReferenceCount ( 0 )
{
InterlockedIncrement ( &s_ObjectsInProgress ) ;
}
//
CIPRouteEventProviderClassFactory::~CIPRouteEventProviderClassFactory ()
{
InterlockedDecrement ( &s_ObjectsInProgress ) ;
}
//
STDMETHODIMP_( ULONG ) CIPRouteEventProviderClassFactory::AddRef()
{
return InterlockedIncrement ( &m_ReferenceCount ) ;
}
//
STDMETHODIMP_(ULONG) CIPRouteEventProviderClassFactory::Release()
{
LONG ref ;
if ( ( ref = InterlockedDecrement( &m_ReferenceCount ) ) == 0 )
{
delete this ;
return 0 ;
}
else
{
return ref ;
}
}
//
BOOL CIPRouteEventProviderClassFactory::DllCanUnloadNow()
{
return ( !(s_ObjectsInProgress || s_LocksInProgress) ) ;
}
//***************************************************************************
//
// CBaseClassFactory::LockServer
//
// Purpose:
// Increments or decrements the lock count of the DLL. If the
// lock count goes to zero and there are no objects, the DLL
// is allowed to unload. See DllCanUnloadNow.
//
// Parameters:
// fLock BOOL specifying whether to increment or
// decrement the lock count.
//
// Return Value:
// HRESULT NOERROR always.
//***************************************************************************
STDMETHODIMP CIPRouteEventProviderClassFactory::LockServer ( BOOL a_fLock )
{
if ( a_fLock )
{
InterlockedIncrement ( &s_LocksInProgress ) ;
}
else
{
InterlockedDecrement ( &s_LocksInProgress ) ;
}
return S_OK ;
}
//
STDMETHODIMP CIPRouteEventProviderClassFactory::QueryInterface (
REFIID a_riid,
PPVOID a_ppv
)
{
*a_ppv = NULL ;
if ( IID_IUnknown == a_riid || IID_IClassFactory == a_riid )
{
*a_ppv = this ;
}
if ( NULL != *a_ppv )
{
AddRef() ;
return NOERROR ;
}
return ResultFromScode( E_NOINTERFACE ) ;
}
//***************************************************************************
//
// CIPRouteEventProviderClassFactory::CreateInstance
//
// Purpose: Instantiates a Event Provider object returning an interface pointer.
//
// Parameters:
// pUnkOuter LPUNKNOWN to the controlling IUnknown if we are
// being used in an aggregation.
// riid REFIID identifying the interface the caller
// desires to have for the new object.
// ppvObj PPVOID in which to store the desired
// interface pointer for the new object.
//
// Return Value:
// HRESULT NOERROR if successful, otherwise E_NOINTERFACE
// if we cannot support the requested interface.
//***************************************************************************
STDMETHODIMP CIPRouteEventProviderClassFactory :: CreateInstance (
LPUNKNOWN a_pUnkOuter ,
REFIID a_riid ,
LPVOID FAR *a_ppvObject
)
{
HRESULT t_status = S_OK ;
if ( a_pUnkOuter )
{
t_status = CLASS_E_NOAGGREGATION ;
}
else
{
try
{
//
// new throws Heap_Exception exception
//
IWbemProviderInit *t_lpunk = ( IWbemProviderInit * ) new CIPRouteEventProvider ;
if ( t_lpunk == NULL )
{
t_status = E_OUTOFMEMORY;
}
else
{
t_status = t_lpunk->QueryInterface ( a_riid , a_ppvObject ) ;
if ( FAILED ( t_status ) )
{
delete t_lpunk ;
}
}
}
catch ( Heap_Exception& e_HE )
{
t_status = E_OUTOFMEMORY ;
}
}
return t_status ;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Class: CIPRouteEventProvider
Description: Provider support for power management events
Derivations: public CIPRouteEventProvider,
public IWbemEventProvider,
public IWbemProviderInit
Caveats:
Raid:
History: a-peterc 31-Mar-1999 Created
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Event provider object
CIPRouteEventProvider :: CIPRouteEventProvider () : m_ReferenceCount( 0 ) ,
m_pHandler(NULL),
m_pClass(NULL),
m_dwThreadID(NULL)
{
InterlockedIncrement ( &CIPRouteEventProviderClassFactory::s_ObjectsInProgress ) ;
InitializeCriticalSection ( &m_csEvent ) ;
// Create a thread that will spin off an event loop
NTSTATUS t_NtStatus = NtCreateEvent (
&m_TerminationEventHandle,
EVENT_ALL_ACCESS,
NULL,
SynchronizationEvent,
FALSE
) ;
if (NT_SUCCESS(t_NtStatus))
{
m_hThreadHandle = CreateThread (
NULL, // pointer to security attributes
0L, // initial thread stack size
dwThreadProc, // pointer to thread function
this, // argument for new thread
0L, // creation flags
&m_dwThreadID
) ;
}
}
//
CIPRouteEventProvider :: ~CIPRouteEventProvider ()
{
LONG t_PreviousState = 0 ;
if ( (m_hThreadHandle != INVALID_HANDLE_VALUE) && (m_TerminationEventHandle != INVALID_HANDLE_VALUE) )
{
//the worker thread should exit...
NTSTATUS t_NtStatus = NtSetEvent (
m_TerminationEventHandle ,
& t_PreviousState
) ;
if (!NT_SUCCESS(t_NtStatus))
{
//fallback - next wait will fail and the thread should exit.
m_TerminationEventHandle = INVALID_HANDLE_VALUE;
}
t_NtStatus = NtWaitForSingleObject ( m_hThreadHandle , FALSE, NULL ) ;
}
DeleteCriticalSection ( &m_csEvent ) ;
if ( m_pHandler )
{
m_pHandler->Release () ;
m_pHandler = NULL ;
}
if ( m_pClass )
{
m_pClass->Release () ;
m_pClass = NULL ;
}
InterlockedDecrement ( & CIPRouteEventProviderClassFactory::s_ObjectsInProgress ) ;
}
//
STDMETHODIMP_( ULONG ) CIPRouteEventProvider :: AddRef ()
{
return InterlockedIncrement ( &m_ReferenceCount ) ;
}
//
STDMETHODIMP_(ULONG) CIPRouteEventProvider :: Release ()
{
LONG t_ref ;
if ( ( t_ref = InterlockedDecrement ( &m_ReferenceCount ) ) == 0 )
{
delete this ;
return 0 ;
}
else
{
return t_ref ;
}
}
//
STDMETHODIMP CIPRouteEventProvider :: QueryInterface (
REFIID a_riid,
void **a_ppv
)
{
if ( NULL == a_ppv )
{
return E_INVALIDARG ;
}
else
{
*a_ppv = NULL ;
}
if( a_riid == IID_IWbemEventProvider )
{
*a_ppv = (IWbemEventProvider *)this ;
}
else if ( a_riid == IID_IWbemProviderInit )
{
*a_ppv = (IWbemProviderInit *) this ;
}
else if ( a_riid == IID_IUnknown )
{
*a_ppv = (IWbemProviderInit *) this ;
}
if (*a_ppv != NULL)
{
AddRef() ;
return S_OK ;
}
else
{
return E_NOINTERFACE ;
}
}
//
STDMETHODIMP CIPRouteEventProvider::Initialize (
LPWSTR a_wszUser,
long a_lFlags,
LPWSTR a_wszNamespace,
LPWSTR a_wszLocale,
IWbemServices *a_pNamespace,
IWbemContext *a_pCtx,
IWbemProviderInitSink *a_pSink
)
{
HRESULT t_hRes = WBEM_E_OUT_OF_MEMORY;
if ( (m_hThreadHandle != INVALID_HANDLE_VALUE) && (m_TerminationEventHandle != INVALID_HANDLE_VALUE) )
{
IWbemClassObject *t_pEventClass = NULL;
BSTR t_bstrClass = SysAllocString (IPROUTE_EVENT_CLASS);
if (t_bstrClass)
{
t_hRes = a_pNamespace->GetObject (
t_bstrClass,
0,
a_pCtx,
&t_pEventClass,
NULL
) ;
// ptr initialization routines
if (SUCCEEDED(t_hRes))
{
SetClass ( t_pEventClass ) ;
}
SysFreeString ( t_bstrClass ) ;
}
}
else
{
t_hRes = WBEM_E_FAILED;
}
a_pSink->SetStatus( t_hRes, 0 ) ;
return t_hRes ;
}
//
STDMETHODIMP CIPRouteEventProvider::ProvideEvents (
IWbemObjectSink *a_pSink,
long a_lFlags
)
{
SetHandler( a_pSink ) ;
return S_OK ;
}
void CIPRouteEventProvider::SetHandler( IWbemObjectSink __RPC_FAR *a_pHandler )
{
EnterCriticalSection( &m_csEvent ) ;
if ( m_pHandler )
{
m_pHandler->Release() ;
}
m_pHandler = a_pHandler ;
if ( m_pHandler )
{
m_pHandler->AddRef() ;
}
LeaveCriticalSection( &m_csEvent ) ;
}
//
void CIPRouteEventProvider::SetClass ( IWbemClassObject *a_pClass )
{
EnterCriticalSection( &m_csEvent ) ;
if ( m_pClass )
{
m_pClass->Release() ;
}
m_pClass = a_pClass ;
if ( m_pClass )
{
m_pClass->AddRef() ;
}
LeaveCriticalSection( &m_csEvent ) ;
}
// worker thread pump
DWORD WINAPI CIPRouteEventProvider :: dwThreadProc ( LPVOID a_lpParameter )
{
CIPRouteEventProvider *t_pThis = ( CIPRouteEventProvider * ) a_lpParameter ;
if ( t_pThis )
{
SmartCloseNtHandle t_StackHandle ;
SmartCloseNtHandle t_CompleteEventHandle ;
NTSTATUS t_NtStatus = t_pThis->OpenQuerySource (
t_StackHandle ,
t_CompleteEventHandle
) ;
BOOL t_Continue = TRUE ;
while ( t_Continue && NT_SUCCESS ( t_NtStatus ) )
{
IO_STATUS_BLOCK t_IoStatusBlock ;
t_NtStatus = NtDeviceIoControlFile (
t_StackHandle,
(HANDLE) t_CompleteEventHandle ,
(PIO_APC_ROUTINE) NULL,
(PVOID) NULL,
&t_IoStatusBlock,
IOCTL_IP_RTCHANGE_NOTIFY_REQUEST,
NULL, // input buffer
0,
NULL , // output buffer
0
) ;
if ( t_NtStatus == STATUS_PENDING )
{
HANDLE t_WaitArray [ 2 ] ;
t_WaitArray [ 0 ] = (HANDLE)t_CompleteEventHandle ;
t_WaitArray [ 1 ] = (HANDLE)t_pThis->m_TerminationEventHandle ;
t_NtStatus = NtWaitForMultipleObjects (
2 ,
t_WaitArray ,
WaitAny,
FALSE ,
NULL
);
switch ( t_NtStatus )
{
case STATUS_WAIT_0:
{
}
break ;
case STATUS_WAIT_1:
{
t_Continue = FALSE ;
}
break ;
default:
{
t_Continue = FALSE ;
}
break ;
}
}
else if ( t_NtStatus != STATUS_SUCCESS )
{
}
else if ( t_IoStatusBlock.Status != STATUS_SUCCESS )
{
}
if ( NT_SUCCESS ( t_NtStatus ) )
{
t_pThis->SendEvent () ;
}
}
}
return 0 ;
}
void CIPRouteEventProvider::SendEvent ()
{
if( m_pClass && m_pHandler)
{
IWbemClassObject *t_pInst = NULL ;
if( SUCCEEDED( m_pClass->SpawnInstance( 0L, &t_pInst ) ) )
{
m_pHandler->Indicate ( 1, &t_pInst ) ;
}
t_pInst->Release() ;
}
}
NTSTATUS CIPRouteEventProvider::OpenQuerySource (
HANDLE &a_StackHandle ,
HANDLE &a_CompleteEventHandle
)
{
UNICODE_STRING t_Stack ;
RtlInitUnicodeString ( & t_Stack , DD_IP_DEVICE_NAME ) ;
OBJECT_ATTRIBUTES t_Attributes;
InitializeObjectAttributes (
&t_Attributes,
&t_Stack ,
OBJ_CASE_INSENSITIVE,
NULL,
NULL
) ;
IO_STATUS_BLOCK t_IoStatusBlock ;
NTSTATUS t_NtStatus = NtOpenFile (
&a_StackHandle,
GENERIC_EXECUTE,
&t_Attributes,
&t_IoStatusBlock,
FILE_SHARE_READ,
0
);
if ( NT_SUCCESS ( t_NtStatus ) )
{
t_NtStatus = NtCreateEvent (
&a_CompleteEventHandle,
EVENT_ALL_ACCESS,
NULL,
SynchronizationEvent,
FALSE
) ;
if ( ! NT_SUCCESS ( t_NtStatus ) )
{
NtClose ( a_StackHandle ) ;
a_StackHandle = INVALID_HANDLE_VALUE ;
}
}
return t_NtStatus ;
}