|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
perfobj.c
Abstract:
This file implements an Performance Object that presents System Object Performance Counters
Created:
Bob Watson 22-Oct-1996
Revision History
--*/ //
// Include Files
//
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <winperf.h>
#include <ntprfctr.h>
#include <perfutil.h>
#include <stdio.h>
#include "perfos.h"
#include "perfosmc.h"
#include "dataobj.h"
DWORD dwObjOpenCount = 0; // count of "Open" threads
// variables local to this module.
static HANDLE hEvent = NULL; static HANDLE hMutex = NULL; static HANDLE hSemaphore = NULL; static HANDLE hSection = NULL;
DWORD APIENTRY OpenObjectsObject ( LPWSTR lpDeviceNames )
/*++
Routine Description:
This routine will initialize the data structures used to pass data back to the registry
Arguments:
Pointer to object ID of each device to be opened (PerfGen)
Return Value:
None.
--*/
{ DWORD status = ERROR_SUCCESS; LONG_PTR TempHandle = -1; //
// 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
//
UNREFERENCED_PARAMETER (lpDeviceNames);
if (dwObjOpenCount == 0) { // open Eventlog interface
hEvent = CreateEvent(NULL,TRUE,TRUE,NULL); hSemaphore = CreateSemaphore(NULL,1,256,NULL); hMutex = CreateMutex(NULL,FALSE,NULL); hSection = CreateFileMapping((HANDLE)TempHandle,NULL,PAGE_READWRITE,0,8192,NULL); }
dwObjOpenCount++; // increment OPEN counter
status = ERROR_SUCCESS; // for successful exit
return status; }
DWORD APIENTRY CollectObjectsObjectData ( IN OUT LPVOID *lppData, IN OUT LPDWORD lpcbTotalBytes, IN OUT LPDWORD lpNumObjectTypes ) /*++
Routine Description:
This routine will return the data for the system objects object
Arguments:
IN OUT LPVOID *lppData IN: pointer to the address of the buffer to receive the completed PerfDataBlock and subordinate structures. This routine will append its data to the buffer starting at the point referenced by *lppData. OUT: points to the first byte after the data structure added by this routine. This routine updated the value at lppdata after appending its data.
IN OUT LPDWORD lpcbTotalBytes IN: the address of the DWORD that tells the size in bytes of the buffer referenced by the lppData argument OUT: the number of bytes added by this routine is writted to the DWORD pointed to by this argument
IN OUT LPDWORD NumObjectTypes IN: the address of the DWORD to receive the number of objects added by this routine OUT: the number of objects added by this routine is writted to the DWORD pointed to by this argument
Returns:
0 if successful, else Win 32 error code of failure
--*/ { DWORD TotalLen; // Length of the total return block
NTSTATUS status;
POBJECTS_DATA_DEFINITION pObjectsDataDefinition; POBJECTS_COUNTER_DATA pOCD;
POBJECT_TYPE_INFORMATION ObjectInfo; WCHAR Buffer[ 256 ];
//
// Check for sufficient space for objects data
//
pObjectsDataDefinition = (OBJECTS_DATA_DEFINITION *) *lppData;
TotalLen = sizeof(OBJECTS_DATA_DEFINITION) + sizeof (OBJECTS_COUNTER_DATA);
TotalLen = QWORD_MULTIPLE (TotalLen);
if ( *lpcbTotalBytes < TotalLen ) { *lpcbTotalBytes = (DWORD) 0; *lpNumObjectTypes = (DWORD) 0; return ERROR_MORE_DATA; }
//
// Define objects data block
//
memcpy (pObjectsDataDefinition, &ObjectsDataDefinition, sizeof(OBJECTS_DATA_DEFINITION));
//
// Format and collect objects data
//
pOCD = (POBJECTS_COUNTER_DATA)&pObjectsDataDefinition[1];
pOCD->CounterBlock.ByteLength = sizeof (OBJECTS_COUNTER_DATA);
ObjectInfo = (POBJECT_TYPE_INFORMATION)Buffer; status = NtQueryObject( NtCurrentProcess(), ObjectTypeInformation, ObjectInfo, sizeof( Buffer ), NULL );
if (NT_SUCCESS(status)) { pOCD->Processes = ObjectInfo->TotalNumberOfObjects; } else { ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, 0, PERFOS_UNABLE_QUERY_PROCESS_OBJECT_INFO, NULL, 0, sizeof(DWORD), NULL, (LPVOID)&status);
pOCD->Processes = 0; }
status = NtQueryObject( NtCurrentThread(), ObjectTypeInformation, ObjectInfo, sizeof( Buffer ), NULL );
if (NT_SUCCESS(status)) { pOCD->Threads = ObjectInfo->TotalNumberOfObjects; } else { ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, 0, PERFOS_UNABLE_QUERY_THREAD_OBJECT_INFO, NULL, 0, sizeof(DWORD), NULL, (LPVOID)&status);
pOCD->Threads = 0; }
status = NtQueryObject( hEvent, ObjectTypeInformation, ObjectInfo, sizeof( Buffer ), NULL );
if (NT_SUCCESS(status)) { pOCD->Events = ObjectInfo->TotalNumberOfObjects; } else { ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, 0, PERFOS_UNABLE_QUERY_EVENT_OBJECT_INFO, NULL, 0, sizeof(DWORD), NULL, (LPVOID)&status);
pOCD->Events = 0; }
status = NtQueryObject( hSemaphore, ObjectTypeInformation, ObjectInfo, sizeof( Buffer ), NULL );
if (NT_SUCCESS(status)) { pOCD->Semaphores = ObjectInfo->TotalNumberOfObjects; } else { ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, 0, PERFOS_UNABLE_QUERY_SEMAPHORE_OBJECT_INFO, NULL, 0, sizeof(DWORD), NULL, (LPVOID)&status);
pOCD->Semaphores = 0; }
status = NtQueryObject( hMutex, ObjectTypeInformation, ObjectInfo, sizeof( Buffer ), NULL );
if (NT_SUCCESS(status)) { pOCD->Mutexes = ObjectInfo->TotalNumberOfObjects; } else { ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, 0, PERFOS_UNABLE_QUERY_MUTEX_OBJECT_INFO, NULL, 0, sizeof(DWORD), NULL, (LPVOID)&status);
pOCD->Mutexes = 0; }
status = NtQueryObject( hSection, ObjectTypeInformation, ObjectInfo, sizeof( Buffer ), NULL );
if (NT_SUCCESS(status)) { pOCD->Sections = ObjectInfo->TotalNumberOfObjects; } else { ReportEvent (hEventLog, EVENTLOG_WARNING_TYPE, 0, PERFOS_UNABLE_QUERY_SECTION_OBJECT_INFO, NULL, 0, sizeof(DWORD), NULL, (LPVOID)&status);
pOCD->Sections = 0; }
*lppData = (LPVOID)&pOCD[1];
// round up buffer to the nearest QUAD WORD
*lppData = ALIGN_ON_QWORD (*lppData);
*lpcbTotalBytes = pObjectsDataDefinition->ObjectsObjectType.TotalByteLength = (DWORD)((LPBYTE) *lppData - (LPBYTE) pObjectsDataDefinition);
*lpNumObjectTypes = 1;
return ERROR_SUCCESS; }
#pragma warning (disable : 4706)
DWORD APIENTRY CloseObjectsObject ( ) /*++
Routine Description:
This routine closes the open handles to the Signal Gen counters.
Arguments:
None.
Return Value:
ERROR_SUCCESS
--*/
{ if (dwObjOpenCount > 0) { dwObjOpenCount--; if (dwObjOpenCount == 0) { // when this is the last thread...
// close stuff here
if (hEvent != NULL) { CloseHandle(hEvent); hEvent = NULL; }
if (hMutex != NULL) { CloseHandle(hMutex); hMutex = NULL; }
if (hSemaphore != NULL) { CloseHandle(hSemaphore); hSemaphore = NULL; } if (hSection != NULL) { CloseHandle(hSection); hSection = NULL; } } }
return ERROR_SUCCESS;
} #pragma warning (default : 4706)
|