/*++ Copyright (c) 2000 Microsoft Corporation Module Name: cpuperf.c Abstract: Display Acpi 2.0 Processor Performance States Author: Todd Carpenter Environment: user mode Notes: THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. Copyright (c) 2000 Microsoft Corporation. All Rights Reserved. Revision History: 10-18-2000 : ToddCar - created --*/ #include "cpuperf.h" VOID __cdecl _tmain( IN INT argc, IN TCHAR *argv[] ) /*++ Routine Description: Main() Arguments: Return Value: --*/ { ULONG rc = (ULONG) 0xdeaddead; ULONG status; ULONG targetState; PTSTR instanceName = NULL; PPROCESSOR_WMI_STATUS_DATA processorData = NULL; status = GetInstanceName(&instanceName); _tprintf(TEXT("InstanceName == %s\n"), instanceName); if (status != ERROR_SUCCESS) { if (status == ERROR_WMI_GUID_NOT_FOUND) { _tprintf(TEXT("\n")); _tprintf(TEXT("This processor driver does not support WMI interface\n")); _tprintf(TEXT("\n")); } else { _tprintf(TEXT("GetInstanceName() Failed! rc=0x%x\n"), status); } return; } // // if called with "setstate X", call SetProcessorPerformanceState(X) first. // if (argc > 1) { if ((_tcsstr(argv[1], TEXT("setstate"))) && argc > 2) { targetState = _ttoi(argv[2]); _tprintf(TEXT("\n")); _tprintf(TEXT("Setting Processor Performance to state %u\n"), targetState); status = SetProcessorPerformanceState(targetState, instanceName, &rc); if (status != ERROR_SUCCESS) { _tprintf(TEXT("SetProcessorPerformanceState() Failed! rc=0x%x\n"), rc); return; } } else { // // display help? or just ignor and continue? // } } status = GetProcessorPerformanceStatusData(&processorData); if (status == ERROR_SUCCESS) { DisplayProcessorData(processorData, instanceName); } //FreeData(instanceName); //FreeData(processorData); return; } ULONG GetProcessorPerformanceStatusData( IN PPROCESSOR_WMI_STATUS_DATA *ProcessorData ) /*++ Routine Description: GetProcessorPerformanceStatusData() Arguments: Return Value: --*/ { ULONG status; ULONG sizeNeeded; PTSTR buffer = NULL; PTSTR instanceName = NULL; ULONG instanceNameOffset; WMIHANDLE wmiStatusHandle; PWNODE_ALL_DATA wmiAllData; PPROCESSOR_WMI_STATUS_DATA processorStatusData; status = WmiOpenBlock(&ProcessorStatusGuid, GENERIC_READ, &wmiStatusHandle); if (status != ERROR_SUCCESS) { _tprintf(TEXT("WmiOpenBlock() Failed! rc=0x%x\n"), status); goto GetProcessorPerformanceStatusDataExit; } status = WmiQueryAllData(wmiStatusHandle, &sizeNeeded, 0); if (status != ERROR_INSUFFICIENT_BUFFER) { _tprintf(TEXT("WmiQueryAllData() Failed! rc=0x%x\n"), status); goto GetProcessorPerformanceStatusDataExit; } buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeNeeded); //_tprintf(TEXT("HeapAlloc(size=0x%x) allocated: %p\n"), sizeNeeded, buffer); if (!buffer) { _tprintf(TEXT("HeapAlloc(size=0x%x) Failed!\n"), sizeNeeded); status = ERROR_INSUFFICIENT_BUFFER; goto GetProcessorPerformanceStatusDataExit; } status = WmiQueryAllData(wmiStatusHandle, &sizeNeeded, buffer); if (status != ERROR_SUCCESS) { _tprintf(TEXT("WmiQueryAllData() Failed! rc=0x%x\n"), status); goto GetProcessorPerformanceStatusDataExit; } wmiAllData = (PWNODE_ALL_DATA) buffer; if (wmiAllData->WnodeHeader.Flags & WNODE_FLAG_FIXED_INSTANCE_SIZE) { _tprintf(TEXT("WNODE_FLAG_FIXED_INSTANCE_SIZE\n"), sizeNeeded); processorStatusData = (PPROCESSOR_WMI_STATUS_DATA) &buffer[wmiAllData->DataBlockOffset]; } else { processorStatusData = (PPROCESSOR_WMI_STATUS_DATA) &buffer[wmiAllData->OffsetInstanceDataAndLength[0].OffsetInstanceData]; } if (processorStatusData) { *ProcessorData = processorStatusData; } GetProcessorPerformanceStatusDataExit: return status; } ULONG SetProcessorPerformanceState( IN ULONG TargetState, IN PTSTR InstanceName, OUT PULONG ReturnedValue ) /*++ Routine Description: SetProcessorPerformanceState() Arguments: Return Value: --*/ { ULONG status; ULONG sizeReturned = sizeof(ULONG); WMIHANDLE wmiMethodHandle; status = WmiOpenBlock(&ProcessorMethodGuid, GENERIC_EXECUTE, &wmiMethodHandle); if (status != ERROR_SUCCESS) { _tprintf(TEXT("SetProcessorPerformanceState: WmiOpenBlock() Failed! rc=0x%x\n"), status); return status; } status = WmiExecuteMethod(wmiMethodHandle, InstanceName, WmiSetProcessorPerfStateMethodId, sizeof(ULONG), (PVOID) &TargetState, &sizeReturned, (PVOID) ReturnedValue); return status; } ULONG GetInstanceName( OUT PTSTR *Buffer ) /*++ Routine Description: GetInstanceName() Arguments: Return Value: --*/ { ULONG status; ULONG sizeNeeded; PUCHAR buffer; PTSTR instanceName; ULONG instanceNameOffset; WMIHANDLE wmiStatusHandle; // // NOTE: must use ProcessorMethodGuid to get Instance Name ... not // sure why others guid don't work. // // // Open connection // status = WmiOpenBlock(&ProcessorMethodGuid, GENERIC_READ, &wmiStatusHandle); if (status != ERROR_SUCCESS) { //_tprintf(TEXT("GetInstanceName: WmiOpenBlock() Failed! rc=0x%x\n"), status); goto GetProcessorPerformanceStatusDataExit; } // // Query for buffer size needed // status = WmiQueryAllData(wmiStatusHandle, &sizeNeeded, 0); if (status != ERROR_INSUFFICIENT_BUFFER) { _tprintf(TEXT("GetInstanceName:WmiQueryAllData(0) Failed! rc=0x%x\n"), status); goto GetProcessorPerformanceStatusDataExit; } // // Allocate buffer // buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeNeeded); if (!buffer) { _tprintf(TEXT("GetInstanceName: HeapAlloc(size=0x%x) Failed!\n"), sizeNeeded); status = ERROR_INSUFFICIENT_BUFFER; goto GetProcessorPerformanceStatusDataExit; } // // Retrieve Data // status = WmiQueryAllData(wmiStatusHandle, &sizeNeeded, buffer); if (status != ERROR_SUCCESS) { _tprintf(TEXT("GetInstanceName: WmiQueryAllData() Failed! rc=0x%x\n"), status); goto GetProcessorPerformanceStatusDataExit; } // // Get instance name. // instanceNameOffset = (ULONG) buffer[((PWNODE_ALL_DATA)buffer)->OffsetInstanceNameOffsets]; instanceName = (PTSTR) &buffer[instanceNameOffset + sizeof(USHORT)]; // // Copy instance name // if (instanceName && Buffer) { ULONG nameSize = lstrlen(instanceName) + sizeof(TCHAR); *Buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nameSize); if (!(*Buffer)) { status = ERROR_INSUFFICIENT_BUFFER; goto GetProcessorPerformanceStatusDataExit; } lstrcpyn(*Buffer, instanceName, nameSize); } // // Close connection // WmiCloseBlock(wmiStatusHandle); GetProcessorPerformanceStatusDataExit: if (buffer) { //HeapFree(GetProcessHeap(), 0, buffer); } return status; } VOID DisplayProcessorData ( IN PPROCESSOR_WMI_STATUS_DATA Data, IN PTSTR InstanceName ) /*++ Routine Description: DisplayProcessorData() Arguments: Return Value: --*/ { ULONG index; _tprintf(TEXT("\n")); _tprintf(TEXT("Processor Performance States\n")); _tprintf(TEXT(" Current Performance State: %u\n"), Data->CurrentPerfState); _tprintf(TEXT(" Last Requested Throttle: %u%%\n"), Data->LastRequestedThrottle); _tprintf(TEXT(" Last Transition Result: %s (0x%x)\n"), (Data->LastTransitionResult ? TEXT("Failed") : TEXT("Succeeded")), Data->LastTransitionResult); _tprintf(TEXT(" Current Throttle Value: %u\n"), Data->ThrottleValue); _tprintf(TEXT(" Lowest Performance State: %u\n"), Data->LowestPerfState); _tprintf(TEXT(" Using Legacy Interface: %s\n"), Data->UsingLegacyInterface ? TEXT("Yes") : TEXT("No")); _tprintf(TEXT("\n")); _tprintf(TEXT(" PerfStates:\n")); _tprintf(TEXT(" Max Transition Latency: %u us\n"), Data->PerfStates.TransitionLatency); _tprintf(TEXT(" Number of States: %u\n\n"), Data->PerfStates.Count); _tprintf(TEXT(" State Speed (Mhz) Type\n")); _tprintf(TEXT(" ----- ------------ ----\n")); for (index = 0; index < Data->PerfStates.Count; index++) { _tprintf(TEXT(" %-5u %4u (%3u%%) %-7s\n"), index, Data->PerfStates.State[index].Frequency, Data->PerfStates.State[index].PercentFrequency, (((Data->PerfStates.State[index].Flags) & PROCESSOR_STATE_TYPE_PERFORMANCE) ? "Performance" : "Throttle")); } _tprintf(TEXT("\n")); } VOID FreeData( IN PVOID Data ) /*++ Routine Description: FreeInstanceName() Arguments: Return Value: --*/ { if (Data) { HeapFree(GetProcessHeap(), 0, Data); } }