mirror of https://github.com/tongzx/nt5src
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.
396 lines
9.0 KiB
396 lines
9.0 KiB
/*++
|
|
|
|
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)
|