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.
 
 
 
 
 
 

662 lines
16 KiB

//////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000 Microsoft Corporation
//
// Module Name:
// SADiskEvent.cpp
//
// Description:
// description-for-module
//
// [Header File:]
// SADiskEvent.h
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <stdio.h>
#include <wbemidl.h>
#include <satrace.h>
#include "SADiskEvent.h"
#include <oahelp.inl>
#include <SAEventComm.h>
const WCHAR SA_DISKEVENTPROVIDER_DISKCOUNTER_NAME[] =
L"\\PhysicalDisk(_Total#0)\\Disk Transfers/sec";
const WCHAR SA_SADEVMONITOR_KEYPATH [] =
L"SOFTWARE\\Microsoft\\ServerAppliance\\DeviceMonitor";
const WCHAR SA_SADISKMONITOR_QUERYINTERVAL[] = L"DiskQueryInterval";
//static DWORD g_dwDiskTimeInterval = 1000;
const DWORD DEFAULTQUERYINTERVAL = 1000;
//////////////////////////////////////////////////////////////////////////////
//
// CSADiskEvent::CSADiskEvent
//
// Description:
// Class constructor.
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
CSADiskEvent::CSADiskEvent()
{
m_cRef = 0;
m_lStatus = Pending;
m_dwDiskTimeInterval = 1000;
m_hThread = NULL;
m_pNs = NULL;
m_pSink = NULL;
m_pEventClassDef = NULL;
m_hqryQuery = NULL;
m_hcntCounter = NULL;
m_hQueryInterval = NULL;
}
//////////////////////////////////////////////////////////////////////////////
//
// CSADiskEvent::~CSADiskEvent
//
// Description:
// Class deconstructor.
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
CSADiskEvent::~CSADiskEvent()
{
if( m_hqryQuery )
{
PdhCloseQuery( m_hqryQuery );
}
if (m_hThread)
{
CloseHandle(m_hThread);
}
if( m_hQueryInterval != NULL )
{
::RegCloseKey( m_hQueryInterval );
}
if (m_pNs)
{
m_pNs->Release();
}
if (m_pSink)
{
m_pSink->Release();
}
if (m_pEventClassDef)
{
m_pEventClassDef->Release();
}
}
//////////////////////////////////////////////////////////////////////////////
//
// CSADiskEvent::QueryInterface
//
// Description:
// An method implement of IUnkown interface.
//
// Arguments:
// [in] riid Identifier of the requested interface
// [out ppv Address of output variable that receives the
// interface pointer requested in iid
//
// Returns:
// NOERROR if the interface is supported
// E_NOINTERFACE if not
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
STDMETHODIMP
CSADiskEvent::QueryInterface(
IN REFIID riid,
OUT LPVOID * ppv
)
{
*ppv = 0;
if (IID_IUnknown==riid || IID_IWbemEventProvider==riid)
{
*ppv = (IWbemEventProvider *) this;
AddRef();
return NOERROR;
}
if (IID_IWbemProviderInit==riid)
{
*ppv = (IWbemProviderInit *) this;
AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
//////////////////////////////////////////////////////////////////////////////
//
// CSADiskEvent::AddRef
//
// Description:
// increments the reference count for an interface on an object.
//
// Returns:
// The new reference count.
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
ULONG
CSADiskEvent::AddRef()
{
return ++m_cRef;
}
//////////////////////////////////////////////////////////////////////////////
//
// CSADiskEvent::Release
//
// Description:
// decrements the reference count for an interface on an object.
//
// Returns:
// The new reference count.
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
ULONG
CSADiskEvent::Release()
{
if (0 != --m_cRef)
{
return m_cRef;
}
//
// If here, we are shutting down.
//
m_lStatus = PendingStop;
return 0;
}
//////////////////////////////////////////////////////////////////////////////
//
// CSADiskEvent::ProvideEvents
//
// Description:
// Called by Windows Management to begin delivery of our events.
//
// Arguments:
// [in] pSinkIn Pointer to the object sink to which we
// will deliver its events
// lFlagsIn Reserved. It must be zero.
//
// Returns:
// WBEM_NO_ERROR Received the sink, and it will begin delivery
// of events
// WBEM_E_FAILED Failed.
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CSADiskEvent::ProvideEvents(
IN IWbemObjectSink __RPC_FAR *pSinkIn,
IN long lFlagsIn
)
{
//
// Copy the sink.
//
m_pSink = pSinkIn;
m_pSink->AddRef();
//
// Open registry key of alertemail settings.
//
ULONG ulReturn;
ulReturn = ::RegOpenKey(
HKEY_LOCAL_MACHINE,
SA_SADEVMONITOR_KEYPATH,
&m_hQueryInterval
);
if( ulReturn == ERROR_SUCCESS )
{
DWORD dwDataSize = sizeof( DWORD );
ulReturn = ::RegQueryValueEx(
m_hQueryInterval,
SA_SADISKMONITOR_QUERYINTERVAL,
NULL,
NULL,
reinterpret_cast<PBYTE>(&m_dwDiskTimeInterval),
&dwDataSize
);
if( ( ulReturn != ERROR_SUCCESS ) ||
( m_dwDiskTimeInterval < DEFAULTQUERYINTERVAL ) )
{
SATraceString(
"CSADiskEvent::ProvideEvents QueryValue failed"
);
m_dwDiskTimeInterval = DEFAULTQUERYINTERVAL;
}
}
else
{
SATraceString(
"CSADiskEvent::ProvideEvents OpenKey failed"
);
m_hQueryInterval = NULL;
}
//
// Create the event thread.
//
DWORD dwTID;
m_hThread = CreateThread(
0,
0,
CSADiskEvent::EventThread,
this,
0,
&dwTID
);
if( m_hThread == NULL )
{
SATraceString(
"CSADiskEvent::ProvideEvents CreateThread failed"
);
return WBEM_E_FAILED;
}
//
// Wait for provider to be 'ready'.
//
while (m_lStatus != Running)
{
Sleep( 1000 );
}
return WBEM_NO_ERROR;
}
//////////////////////////////////////////////////////////////////////////////
//
// [static]
// CSADiskEvent::EventThread
//
// Description:
// The event thread start routine.
//
// Arguments:
// [in] pArg
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI CSADiskEvent::EventThread(
IN LPVOID pArg
)
{
//
// Make transition to the per-instance method.
//
((CSADiskEvent *)pArg)->InstanceThread();
return 0;
}
//////////////////////////////////////////////////////////////////////////////
//
// CSADiskEvent::InstanceThread
//
// Description:
// Called by EventThread to detect disk active.
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
void
CSADiskEvent::InstanceThread()
{
PDH_STATUS pdhStatus;
PDH_FMT_COUNTERVALUE pdhFmt_CounterValue;
m_lStatus = Running;
while (m_lStatus == Running)
{
//
// Polling performance data with time interval.
//
Sleep( m_dwDiskTimeInterval );
//
// Collect the query data before geting counter value.
//
pdhStatus = PdhCollectQueryData( m_hqryQuery );
if( ERROR_SUCCESS == pdhStatus )
{
//
// Get the counter value formatted by PDH.
//
pdhStatus = PdhGetFormattedCounterValue(
m_hcntCounter,
PDH_FMT_LONG,
NULL,
&pdhFmt_CounterValue
);
if( ERROR_SUCCESS == pdhStatus )
{
if( pdhFmt_CounterValue.longValue != 0 )
{
//
// Some disk operations appear during time interval.
//
NotifyDiskEvent(
SA_DISK_DISPLAY_TRANSMITING,
SA_RESOURCEEVENT_DEFAULT_CURRENTSTATE
);
}
else
{
//
// No work on the disk.
//
NotifyDiskEvent(
SA_DISK_DISPLAY_IDLE,
SA_RESOURCEEVENT_DEFAULT_CURRENTSTATE
);
} // pdhFmt_CounterValue.longValue != 0
}//if( ERROR_SUCCESS == pdhStatus )
else
{
//
// System is busy wait a moment.
//
Sleep( m_dwDiskTimeInterval );
SATraceString(
"CSADiskEvent::InstanceThread GetValue failed"
);
} //else
}
}
//
// When we get to here, we are no longer interested in the
// provider and Release() has long since returned.
m_lStatus = Stopped;
delete this;
}
//////////////////////////////////////////////////////////////////////////////
//
// CSADiskEvent::NotifyDiskEvent
//
// Description:
// Called by InstanceThread to begin delivery of our events.
//
// Arguments:
// [in] lDisplayInformationIDIn Resource ID for the disk event.
// lCurrentStateIn Reserved.
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
VOID
CSADiskEvent::NotifyDiskEvent(
LONG lDisplayInformationIDIn,
LONG lCurrentStateIn
)
{
//
// Generate a new event object.
//
IWbemClassObject *pEvt = 0;
CBSTR bstrUniqueName = CBSTR(SA_RESOURCEEVENT_UNIQUENAME);
CBSTR bstrDisplayInfo = CBSTR(SA_RESOURCEEVENT_DISPLAYINFORMATION);
CBSTR bstrCurrentState = CBSTR(SA_RESOURCEEVENT_CURRENTSTATE);
if ( ((BSTR)bstrUniqueName == NULL) ||
((BSTR)bstrDisplayInfo == NULL) ||
((BSTR)bstrCurrentState == NULL) )
{
SATraceString(" SADiskMonitor:CSADiskEvent::NotifyDiskEvent failed on memory allocation ");
return;
}
HRESULT hRes = m_pEventClassDef->SpawnInstance( 0, &pEvt );
if ( hRes != 0 )
{
SATraceString(
"CSADiskEvent::NotifyDiskEvent SpawnInstance failed"
);
return;
}
CVARIANT cvUniqueName( SA_DISK_EVENT );
pEvt->Put(
bstrUniqueName,
0,
cvUniqueName,
0
);
CVARIANT cvDisplayInformationID( lDisplayInformationIDIn );
pEvt->Put(
bstrDisplayInfo,
0,
cvDisplayInformationID,
0
);
CVARIANT cvCount( lCurrentStateIn );
pEvt->Put(
bstrCurrentState,
0,
cvCount,
0
);
//
// Deliver the event to CIMOM.
//
hRes = m_pSink->Indicate(1, &pEvt);
if ( FAILED( hRes ) )
{
SATraceString(
"CSADiskEvent::NotifyDiskEvent Indicate failed"
);
}
pEvt->Release();
}
//////////////////////////////////////////////////////////////////////////////
//
// CSADiskEvent::Initialize
//
// Description:
// Inherite from IWbemProviderInit,called by Windows Management to
// initialize a provider and deem it ready to receive client requests.
//
// Arguments:
// [in] pszUserIn
// lFlagsIn
// pszNamespaceIn
// pszLocaleIn
// pNamespaceIn
// pCtxIn
// pInitSinkIn
//
// Returns:
// WBEM_S_NO_ERROR
// WBEM_E_FAILED
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
HRESULT
CSADiskEvent::Initialize(
LPWSTR pszUserIn,
LONG lFlagsIn,
LPWSTR pszNamespaceIn,
LPWSTR pszLocaleIn,
IWbemServices __RPC_FAR * pNamespaceIn,
IWbemContext __RPC_FAR * pCtxIn,
IWbemProviderInitSink __RPC_FAR * pInitSinkIn
)
{
// We don't care about most of the incoming parameters in this
// simple sample. However, we will save the namespace pointer
// and get our event class definition.
m_pNs = pNamespaceIn;
m_pNs->AddRef();
//
// Grab the class definition for the event.
//
IWbemClassObject *pObj = 0;
CBSTR bstrClassName = CBSTR(SA_RESOURCEEVENT_CLASSNAME);
if ( (BSTR)bstrClassName == NULL )
{
SATraceString(" SADiskMonitor:CSADiskEvent::Initialize failed on memory allocation ");
return E_OUTOFMEMORY;
}
HRESULT hRes = m_pNs->GetObject(
bstrClassName,
0,
pCtxIn,
&pObj,
0
);
if ( hRes != 0 )
{
SATraceString(
"CSADiskEvent::Initialize GetObject failed"
);
return WBEM_E_FAILED;
}
m_pEventClassDef = pObj;
//
// Tell CIMOM that we're up and running.
//
if( InitDiskQueryContext() )
{
pInitSinkIn->SetStatus(WBEM_S_INITIALIZED,0);
return WBEM_NO_ERROR;
}
SATraceString(
"CSADiskEvent::Initialize InitDiskQueryContext failed"
);
pInitSinkIn->SetStatus(WBEM_E_FAILED ,0);
return WBEM_E_FAILED;
}
//////////////////////////////////////////////////////////////////////////////
//
// CSADiskEvent::InitDiskQueryContext
//
// Description:
// Called by Initialize to initial physicaldisk counter.
//
// Arguments:
//
// Returns:
// TRUE Succeed in retrieving disk counter.
// FALSE Failed
//
// History:
// Xing Jin (i-xingj) 06-Dec-2000
//
//////////////////////////////////////////////////////////////////////////////
BOOL
CSADiskEvent::InitDiskQueryContext()
{
PDH_STATUS pdhStatus;
//
// Open a query handle of PDH.
//
pdhStatus = PdhOpenQuery( NULL, 0, &m_hqryQuery );
if( ERROR_SUCCESS == pdhStatus )
{
//
// Add the specified counter we want to our query handle.
//
pdhStatus = PdhAddCounter( m_hqryQuery,
SA_DISKEVENTPROVIDER_DISKCOUNTER_NAME,
0,
&m_hcntCounter );
}
return ( ERROR_SUCCESS == pdhStatus );
}