/*++ Copyright (c) 2000-2001 Microsoft Corporation Module Name: perfgen.c Abstract: This is the main file of the WINMGMT perf library. Created: davj 17-May-2000 Revision History --*/ #include #include #include #include #include "genctrs.h" // error message definition #include "perfmsg.h" #include "perfutil.h" #include "datagen.h" DWORD dwDataSize[MAXVALUES]; // This is the shared data segment which allows wbemcore.dll to be able to set // the counter values #pragma data_seg(".shared") DWORD dwCounterValues[MAXVALUES] = {0,0,0,0,0,0,0,0}; #pragma data_seg() // // References to constants which initialize the Object type definitions // extern REG_DATA_DEFINITION RegDataDefinition; DWORD dwOpenCount = 0; // count of "Open" threads BOOL bInitOK = FALSE; // true = DLL initialized OK // // Function Prototypes // // these are used to insure that the data collection functions // accessed by Perflib will have the correct calling format. // PM_OPEN_PROC OpenWmiPerformanceData; PM_COLLECT_PROC CollectWmiPerformanceData; PM_CLOSE_PROC CloseWmiPerformanceData; DWORD GetData(DWORD * pData, DWORD dwIndex) { *pData = dwCounterValues[dwIndex]; return 4; } DWORD APIENTRY OpenWmiPerformanceData( LPWSTR lpDeviceNames ) /*++ Routine Description: This routine will initialize the data structures used to pass data back to perfmon Arguments: Pointer to object ID of each device to be opened (WMIPerf) Return Value: None. --*/ { LONG status; HKEY hKeyDriverPerf; DWORD size, x; DWORD type; DWORD dwFirstCounter; DWORD dwFirstHelp; // // 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 (!dwOpenCount) { // open Eventlog interface hEventLog = MonOpenEventLog(); // get counter and help index base values from registry // Open key to registry entry // read First Counter and First Help values // update static data strucutures by adding base to // offset value in structure. status = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Winmgmt\\Performance", 0L, KEY_READ, &hKeyDriverPerf); if (status != ERROR_SUCCESS) { REPORT_ERROR_DATA (GENPERF_UNABLE_OPEN_DRIVER_KEY, LOG_ERROR, &status, sizeof(status)); // this is fatal, if we can't get the base values of the // counter or help names, then the names won't be available // to the requesting application so there's not much // point in continuing. goto OpenExitPoint; } size = sizeof (DWORD); status = RegQueryValueEx( hKeyDriverPerf, "First Counter", 0L, &type, (LPBYTE)&dwFirstCounter, &size); if (status != ERROR_SUCCESS) { REPORT_ERROR_DATA (GENPERF_UNABLE_READ_FIRST_COUNTER, LOG_ERROR, &status, sizeof(status)); // this is fatal, if we can't get the base values of the // counter or help names, then the names won't be available // to the requesting application so there's not much // point in continuing. goto OpenExitPoint; } size = sizeof (DWORD); status = RegQueryValueEx( hKeyDriverPerf, "First Help", 0L, &type, (LPBYTE)&dwFirstHelp, &size); if (status != ERROR_SUCCESS) { REPORT_ERROR_DATA (GENPERF_UNABLE_READ_FIRST_HELP, LOG_ERROR, &status, sizeof(status)); // this is fatal, if we can't get the base values of the // counter or help names, then the names won't be available // to the requesting application so there's not much // point in continuing. goto OpenExitPoint; } // Set some of the static information into the structure RegDataDefinition.RegObjectType.ObjectNameTitleIndex += dwFirstCounter; RegDataDefinition.RegObjectType.ObjectHelpTitleIndex += dwFirstHelp; for (x=0; xRegObjectType.TotalByteLength += dwTotSize; pRegCounterDefinition = (PERF_COUNTER_DEFINITION *) ( ((PBYTE) pRegDataDefinition) + pRegDataDefinition->RegObjectType.HeaderLength); dwDataOffset = sizeof(PERF_COUNTER_BLOCK); pPerfCounterBlock->ByteLength = dwTotSize; for (x=0; xCounterSize = dwDataSize[x]; pRegCounterDefinition->CounterOffset = dwDataOffset; memcpy((PBYTE) pPerfCounterBlock + dwDataOffset, &Data[x], dwDataSize[x]); dwDataOffset += dwDataSize[x]; pRegCounterDefinition++; } *lppData = (PBYTE) pRegDataDefinition + pRegDataDefinition->RegObjectType.TotalByteLength; *lpcbTotalBytes = pRegDataDefinition->RegObjectType.TotalByteLength; // update arguments for return *lpNumObjectTypes = 1; // Number of objects returned (objects, not counters) return ERROR_SUCCESS; } DWORD APIENTRY CloseWmiPerformanceData( ) /*++ Routine Description: This routine closes the open handles. Arguments: None. Return Value: ERROR_SUCCESS --*/ { if (!(--dwOpenCount)) { // when this is the last thread... MonCloseEventLog(); } return ERROR_SUCCESS; } DWORD APIENTRY WriteCounter(DWORD dwCountNum, DWORD dwCountValue) /*++ Routine Description: This routine is where wbemcore.dll calls to set a counter value. Arguments: IN DWORD dwCountNum Counter to be set. IN DWORD dwCountValue New counter value. Return Value: ERROR_SUCCESS --*/ { if(dwCountNum < MAXVALUES) { dwCounterValues[dwCountNum] = dwCountValue; return 0; } else return ERROR_INVALID_PARAMETER; } //*************************************************************************** // // DllRegisterServer // // Standard OLE entry point for registering the server. // // RETURN VALUES: // // S_OK Registration was successful // E_FAIL Registration failed. // //*************************************************************************** HRESULT APIENTRY DllRegisterServer(void) { HKEY hKey; DWORD dw = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\winmgmt\\Performance", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL); if(dw == ERROR_SUCCESS) { RegSetValueEx(hKey,"Library", 0, REG_SZ,"wmiperf.dll", 12); RegSetValueEx(hKey,"Open", 0, REG_SZ, "OpenWmiPerformanceData", 23); RegSetValueEx(hKey,"Collect", 0, REG_SZ,"CollectWmiPerformanceData", 26); RegSetValueEx(hKey,"Close", 0, REG_SZ, "CloseWmiPerformanceData", 24); RegCloseKey(hKey); } else return E_FAIL; dw = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\wmiperf", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hKey, NULL); if(dw == ERROR_SUCCESS) { DWORD dwTemp = 7; RegSetValueEx(hKey,"EventMessageFile", 0, REG_EXPAND_SZ, "%systemroot%\\system32\\wmiperf.dll", 34); RegSetValueEx(hKey,"TypesSupported", 0, REG_DWORD, (BYTE *)&dwTemp, 4); RegCloseKey(hKey); } else return E_FAIL; return S_OK; } //*************************************************************************** // // DllUnregisterServer // // Standard OLE entry point for unregistering the server. // // RETURN VALUES: // // S_OK Unregistration was successful // E_FAIL Unregistration failed. // //*************************************************************************** HRESULT APIENTRY DllUnregisterServer(void) { DWORD dw = RegDeleteKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\winmgmt\\Performance"); if(dw != ERROR_SUCCESS) return E_FAIL; dw = RegDeleteKey(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\wmiperf"); if(dw != ERROR_SUCCESS) return E_FAIL; else return S_OK; }