Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

554 lines
14 KiB

/*++
Copyright (c) 1998-1999 Microsoft Corporation
Module Name:
ulperf.cpp
Abstract:
This is the main code for the ul.sys performance counter support object
Author:
Paul McDaniel (paulmcd) 11-May-1999
Revision History:
--*/
#include "precomp.h"
#include "ulperf.h"
//
// Globals
//
LONG g_lInit;
HINSTANCE g_hInstance;
//
// Active "opens" reference count for Open/Close PerformanceData
//
ULONG OpenCount = 0;
//
// An open handle to the event log for error logging
//
HANDLE hEventLog;
//
// Initialize the constant portions of the HKEY_PERFORMANCE data structure.
// Certain parts (especially the name/help indices) will be
// updated at initialization time.
//
const UL_COUNTER_BLOCK CounterBlock;
UL_PERF_OBJECT_DEFINITION ObjectDefinition =
{
{ // ObjectType
sizeof(UL_PERF_OBJECT_DEFINITION) + sizeof(UL_COUNTER_BLOCK),
sizeof(UL_PERF_OBJECT_DEFINITION),
sizeof(PERF_OBJECT_TYPE),
UL_COUNTER_OBJECT,
NULL,
UL_COUNTER_OBJECT,
NULL,
PERF_DETAIL_ADVANCED,
NUMBER_OF_UL_COUNTERS,
-1, // DefaultCounter
PERF_NO_INSTANCES,
0,
{ 0, 0 },
{ 0, 0 }
},
{ // BytesSent
sizeof(PERF_COUNTER_DEFINITION),
UL_BYTES_SENT_COUNTER,
NULL, // assigned in OpenPerformanceData()
UL_BYTES_SENT_COUNTER,
NULL, // assigned in OpenPerformanceData()
0,
PERF_DETAIL_ADVANCED,
PERF_COUNTER_COUNTER,
0, // assigned in OpenPerformanceData()
0 // assigned in OpenPerformanceData()
},
{ // BytesReceived
sizeof(PERF_COUNTER_DEFINITION),
UL_BYTES_RECEIVED_COUNTER,
NULL,
UL_BYTES_RECEIVED_COUNTER,
NULL,
0,
PERF_DETAIL_ADVANCED,
PERF_COUNTER_COUNTER,
0,
0
},
{ // CurrentConnections
sizeof(PERF_COUNTER_DEFINITION),
UL_CURRENT_CONNECTIONS_NUMBER,
NULL,
UL_CURRENT_CONNECTIONS_NUMBER,
NULL,
0,
PERF_DETAIL_ADVANCED,
PERF_COUNTER_RAWCOUNT,
0,
0
},
{ // CurrentRequests
sizeof(PERF_COUNTER_DEFINITION),
UL_CURRENT_REQUESTS_NUMBER,
NULL,
UL_CURRENT_REQUESTS_NUMBER,
NULL,
0,
PERF_DETAIL_ADVANCED,
PERF_COUNTER_RAWCOUNT,
0,
0
},
{ // QueuedRequests
sizeof(PERF_COUNTER_DEFINITION),
UL_QUEUED_REQUESTS_NUMBER,
NULL,
UL_QUEUED_REQUESTS_NUMBER,
NULL,
0,
PERF_DETAIL_ADVANCED,
PERF_COUNTER_RAWCOUNT,
0,
0
},
{ // AttachedProcesses
sizeof(PERF_COUNTER_DEFINITION),
UL_ATTACHED_PROCESSES_NUMBER,
NULL,
UL_ATTACHED_PROCESSES_NUMBER,
NULL,
0,
PERF_DETAIL_ADVANCED,
PERF_COUNTER_RAWCOUNT,
0,
0
}
};
DWORD
OpenPerformanceData(
LPWSTR lpDeviceNames
)
{
DWORD Error = NO_ERROR;
HKEY hkey = NULL;
DWORD size;
DWORD type;
DWORD dwFirstCounter;
DWORD dwFirstHelp;
DWORD i;
PERF_COUNTER_DEFINITION * pctr;
//
// Since WINLOGON is multi-threaded and will call this routine in
// order to service remote performance queries, this library
// must keep track of how many times it has been opened (i.e.
// how many threads have accessed it). The registry routines will
// limit access to the initialization routine to only one thread
// at a time so synchronization (i.e. reentrancy) should not be
// a problem.
//
if (OpenCount == 0)
{
//
// This is the *first* open.
//
// open event log interface
if (hEventLog == NULL)
{
hEventLog = RegisterEventSource(
(LPTSTR)NULL, // Use Local Machine
APP_NAME // event log app name
// to find in registry
);
}
//
// open the performance key
//
Error = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
REGISTRY_UL_INFORMATION L"\\Performance",
0,
KEY_ALL_ACCESS,
&hkey
);
if( err == NO_ERROR )
{
//
// Read the first counter DWORD.
//
size = sizeof(DWORD);
err = RegQueryValueEx(
hkey,
L"First Counter",
NULL,
&type,
(LPBYTE)&dwFirstCounter,
&size
);
if( err == NO_ERROR )
{
//
// Read the first help DWORD.
//
size = sizeof(DWORD);
err = RegQueryValueEx( hkey,
L"First Help",
NULL,
&type,
(LPBYTE)&dwFirstHelp,
&size );
if ( err == NO_ERROR )
{
//
// Update the object & counter name & help indicies.
//
ObjectDefinition.ObjectType.ObjectNameTitleIndex
+= dwFirstCounter;
ObjectDefinition.ObjectType.ObjectHelpTitleIndex
+= dwFirstHelp;
#define ADJUST_VALUES(CounterName) \
do {\
ObjectDefinition.##CounterName.CounterNameTitleIndex \
+= dwFirstCounter; \
ObjectDefinition.##CounterName.CounterHelpTitleIndex \
+= dwFirstHelp; \
ObjectDefinition.##CounterName.CounterSize \
= sizeof(CounterBlock.##CounterName); \
ObjectDefinition.##CounterName.CounterOffset = \
DIFF((LPBYTE)&CounterBlock.##CounterName - (LPBYTE)&CounterBlock);\
} while (0)
ADJUST_VALUES(BytesSent);
ADJUST_VALUES(BytesReceived);
ADJUST_VALUES(CurrentConnections);
ADJUST_VALUES(CurrentRequests);
ADJUST_VALUES(QueuedRequests);
ADJUST_VALUES(AttachedProcesses);
//
// Remember that we initialized OK.
//
fInitOK = TRUE;
} else {
ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
0, W3_UNABLE_READ_FIRST_HELP,
(PSID)NULL, 0,
sizeof(err), NULL,
(PVOID)(&err));
}
} else {
ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
0, W3_UNABLE_READ_FIRST_COUNTER,
(PSID)NULL, 0,
sizeof(err), NULL,
(PVOID)(&err));
}
//
// Close the registry if we managed to actually open it.
//
if( hkey != NULL )
{
RegCloseKey( hkey );
hkey = NULL;
}
} else {
ReportEvent (hEventLog, EVENTLOG_ERROR_TYPE,
0, W3_UNABLE_OPEN_W3SVC_PERF_KEY,
(PSID)NULL, 0,
sizeof(err), NULL,
(PVOID)(&err));
}
}
//
// Bump open counter.
//
OpenCount += 1;
end:
return Error;
} // OpenPerformanceData
DWORD
CollectPerformanceData(
LPWSTR lpwszValue,
LPVOID *lppData,
LPDWORD lpcbBytes,
LPDWORD lpcObjectTypes
)
{
}
DWORD
WINAPI
ClosePerformanceData(
)
{
//
// Clean up
//
OpenCount -= 1;
if (OpenCount == 0)
{
if (hEventLog != NULL)
{
DeregisterEventSource(hEventLog);
hEventLog = NULL;
}
}
return NO_ERROR;
} // ClosePerformanceData
CUlPerfCounters::CUlPerfCounters()
{
}
CUlPerfCounters::~CUlPerfCounters()
{
}
//
// IWbemProviderInit
//
STDMETHODIMP CUlPerfCounters::Initialize(LPWSTR wszUser,LONG lFlags,LPWSTR wszNamespace,LPWSTR wszLocale,IWbemServices* pNamespace,IWbemContext* pCtx,IWbemProviderInitSink* pInitSink)
{
HRESULT Result;
ASSERT(pInitSink != NULL);
TRACE(L"ulperf!CUlPerfCounters::Initialize called\n");
//
// tell wbem we are ready to go.
//
Result = pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
return Result;
} // CUlPerfCounters::Initialize
//
// IWbemServices
//
// Context.
// ========
STDMETHODIMP CUlPerfCounters::OpenNamespace(BSTR strNamespace, long lFlags, IWbemContext* pCtx, IWbemServices** ppWorkingNamespace, IWbemCallResult** ppResult)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::CancelAsyncCall(IWbemObjectSink* pSink)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::QueryObjectSink(long lFlags,IWbemObjectSink** ppResponseHandler)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
// Classes and instances.
// ======================
STDMETHODIMP CUlPerfCounters::GetObject(BSTR strObjectPath,long lFlags,IWbemContext* pCtx,IWbemClassObject** ppObject,IWbemCallResult** ppCallResult)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::GetObjectAsync(BSTR strObjectPath,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
{
IWbemClassObject pObj;
HRESULT Result;
CObjectPathParser PathParser;
ParsedObjectPath *pParsedPath = NULL;
Result = WBEM_S_NO_ERROR;
//
// crack the object path
//
Result = PathParser.Parse(strObjectPath, &pParsedPath);
if (Result != CObjectPathParser::NoError)
return E_FAIL;
//
// create a perfctr object
//
pObject = new CComObject<CUlPerfCounterObject>;
if (pObject == NULL)
{
Result = E_OUTOFMEMORY
goto end;
}
//
// init it
//
Result = pObject->Init(pParsedPath);
if (FAILED(Result))
goto end;
//
// and hand it off to wbem
//
Result = pGroup->_InternalQueryInterface(IID_IWbemClassObject, (PVOID*)&pWbemObj);
if (FAILED(Result))
goto end;
Result = pHandler->Indicate(1, &pWbemObj);
if (FAILED(Result))
goto end;
end:
if (pParsedPath != NULL)
{
PathParser.Free(pParsedPath);
pParsedPath = NULL;
}
if (pWbemObj != NULL)
{
pWbemObj->Release();
pWbemObj = NULL;
}
pHandler->SetStatus(0, Result, NULL, NULL);
return Result;
}
// Class manipulation.
// ===================
STDMETHODIMP CUlPerfCounters::PutClass(IWbemClassObject* pObject,long lFlags,IWbemContext* pCtx,IWbemCallResult** ppCallResult)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::PutClassAsync(IWbemClassObject* pObject,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::DeleteClass(BSTR strClass,long lFlags,IWbemContext* pCtx,IWbemCallResult** ppCallResult)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::DeleteClassAsync(BSTR strClass,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::CreateClassEnum(BSTR strSuperclass,long lFlags,IWbemContext* pCtx,IEnumWbemClassObject** ppEnum)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::CreateClassEnumAsync(BSTR strSuperclass,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
// Instances.
// ==========
STDMETHODIMP CUlPerfCounters::PutInstance(IWbemClassObject* pInst,long lFlags,IWbemContext* pCtx,IWbemCallResult** ppCallResult)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::PutInstanceAsync(IWbemClassObject* pInst,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::DeleteInstance(BSTR strObjectPath,long lFlags,IWbemContext* pCtx,IWbemCallResult** ppCallResult)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::DeleteInstanceAsync(BSTR strObjectPath,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::CreateInstanceEnum(BSTR strClass,long lFlags,IWbemContext* pCtx,IEnumWbemClassObject** ppEnum)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::CreateInstanceEnumAsync(BSTR strClass,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
// Queries.
// ========
STDMETHODIMP CUlPerfCounters::ExecQuery(BSTR strQueryLanguage,BSTR strQuery,long lFlags,IWbemContext* pCtx,IEnumWbemClassObject** ppEnum)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::ExecQueryAsync(BSTR strQueryLanguage,BSTR strQuery,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::ExecNotificationQuery(BSTR strQueryLanguage,BSTR strQuery,long lFlags,IWbemContext* pCtx,IEnumWbemClassObject** ppEnum)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::ExecNotificationQueryAsync(BSTR strQueryLanguage,BSTR strQuery,long lFlags,IWbemContext* pCtx,IWbemObjectSink* pResponseHandler)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
// Methods
// =======
STDMETHODIMP CUlPerfCounters::ExecMethod(BSTR strObjectPath,BSTR strMethodName,long lFlags,IWbemContext* pCtx,IWbemClassObject* pInParams,IWbemClassObject** ppOutParams,IWbemCallResult** ppCallResult)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }
STDMETHODIMP CUlPerfCounters::ExecMethodAsync(BSTR strObjectPath,BSTR strMethodName,long lFlags,IWbemContext* pCtx,IWbemClassObject* pInParams,IWbemObjectSink* pResponseHandler)
{ return WBEM_E_METHOD_NOT_IMPLEMENTED; }