/*++ 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 #include #include #include #include #include #include #include #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)