home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2005 March / PCpro_2005_03.ISO / files / systools / speedswitchxp / sswitchxp14.exe / Typical / speedswitch.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2005-01-14  |  19.3 KB  |  572 lines

  1. /*
  2.    SpeedswitchXP V1.4
  3.    - Windows XP CPU Frequency Control for Notebooks -
  4.  
  5.    Copyright(c) 2002-2004 Christian Diefer
  6.  
  7.    This program is free software; you can redistribute it and/or modify
  8.    it under the terms of the GNU General Public License version 2 as 
  9.    published by the Free Software Foundation.
  10.    
  11.    This program is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.    
  16.    You should have received a copy of the GNU General Public License
  17.    along with this program; if not, write to the Free Software
  18.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. */
  20.  
  21. //------------------------------------------------------------------
  22. // 
  23. // (c) 2002/2003 Christian Diefer
  24. //------------------------------------------------------------------
  25. #include <stdafx.h>
  26.  
  27. #include "TOptions.h"
  28. #include "speedswitch.h"
  29. #include <stdio.h>
  30. #include "SpeedswitchXP.h"
  31.  
  32. #define PROFILENAME "Speedswitch Control"
  33.  
  34. static char* uc2char( char* dest, void* s );   // unicode to ansi (char*)
  35. static char* char2uc( char* dest, char* s );   // ansi (char*) to unicode
  36. static BOOL comparePowerProfile( POWER_POLICY& pol1, POWER_POLICY& pol2 );
  37. static BOOL compareCPUScheme( MACHINE_PROCESSOR_POWER_POLICY& pol1, MACHINE_PROCESSOR_POWER_POLICY& pol2 );
  38. static BOOL comparePowerActionPolicy( POWER_ACTION_POLICY& pol1, POWER_ACTION_POLICY& pol2 );
  39. static BOOL compareCPUPowerPolicy( PROCESSOR_POWER_POLICY& pol1, PROCESSOR_POWER_POLICY& pol2 );
  40. static BOOL compareCPUPowerPolicyInfo( PROCESSOR_POWER_POLICY_INFO& pol1, PROCESSOR_POWER_POLICY_INFO& pol2 );
  41.  
  42. BOOLEAN __stdcall powerSchemeCallback(
  43.   UINT uiIndex,      // power scheme index
  44.   DWORD dwName,      // size of the sName string, in bytes
  45.   LPTSTR sName,      // name of the power scheme
  46.   DWORD dwDesc,      // size of the sDesc string, in bytes
  47.   LPTSTR sDesc,      // description string
  48.   PPOWER_POLICY pp,  // receives the power policy
  49.   LPARAM lParam      // user-defined value
  50. );
  51.  
  52. static char msg[2048];
  53. static char dummy[256];
  54. static UINT internalProfile;                  // the no of our own profile
  55. static UINT lastChecked;
  56. static POWER_POLICY toBeCopied;
  57.  
  58. int acThrottle;
  59. int dcThrottle;
  60. POWER_POLICY internalPolicy;           // our own profile policy
  61. MACHINE_PROCESSOR_POWER_POLICY mach;   // our own cpu policy
  62.  
  63. //------------------------------------------------------------------
  64. // Detect our own profile no
  65. //
  66. // return codes:
  67. //   -1: profile enumeration failed
  68. //   -2: profile not found (profile creation necessary)
  69. //   -3: CPU policy reading from our own profile failed
  70. //   -4: new profile activation failed
  71. //   >=0: profile no (success)
  72. //------------------------------------------------------------------
  73. int detectProfile()
  74. {
  75.   internalProfile = 0xffffffff;
  76.   lastChecked = 0xffffffff;
  77.  
  78.   if( !EnumPwrSchemes(&powerSchemeCallback,0) )
  79.     return -1;      // enumeration failed
  80.  
  81.   if( internalProfile == 0xffffffff )
  82.     return -2;      // profile not found
  83.  
  84.   // read the current CPU policy from our profile
  85.   if( !ReadProcessorPwrScheme(internalProfile,&mach) )
  86.     return -3;      // CPU policy reading failed
  87.  
  88.   if( !SetActivePwrScheme(internalProfile,NULL,NULL) )
  89.     return -4;  
  90.  
  91.   updateStates();
  92.  
  93.   return internalProfile;   // profile found, return profile no
  94. }
  95.  
  96. //------------------------------------------------------------------
  97. // create new profile from current one
  98. //
  99. // return codes:
  100. //   -1: active profile detection failed
  101. //   -2: reading active profile policy failed
  102. //   -3: writing our own profile failed
  103. //   -4: reading active cpu policy failed
  104. //   -5: writing our own cpu policy failed
  105. //   -6: new profile activation failed
  106. //   0: profile creation successful
  107. //------------------------------------------------------------------
  108. int createProfile()
  109. {
  110.   // get the # of the currently active profile
  111.   UINT activeProfile;
  112.   if( !GetActivePwrScheme(&activeProfile) )
  113.     return -1;  
  114.  
  115.   // read the profile policy settings
  116.   if( !ReadPwrScheme(activeProfile,&toBeCopied) )
  117.     return -2;
  118.  
  119.   // copy this to the one we use later
  120.   internalPolicy = toBeCopied;
  121.  
  122.   // create the # of our own profile
  123.   lastChecked++;
  124.  
  125.   // disable throttling in this new profile
  126.   internalPolicy.user.ForcedThrottleAc = 100;
  127.   internalPolicy.user.ForcedThrottleDc = 100;
  128.  
  129.   // write our own profile policy settings to the registry
  130.   if( !WritePwrScheme(&lastChecked,char2uc(dummy,PROFILENAME),"\0\0",&internalPolicy) )
  131.     return -3;
  132.  
  133.   // this is our profile #
  134.   internalProfile = lastChecked;
  135.  
  136.   // read the CPU policy from the active profile
  137.   if( !ReadProcessorPwrScheme(activeProfile,&mach) )
  138.     return -4;
  139.  
  140.   // use this CPU policy for our own profile
  141.   if( !WriteProcessorPwrScheme(internalProfile,&mach) )
  142.     return -5;
  143.  
  144.   if( !SetActivePwrScheme(internalProfile,NULL,NULL) )
  145.     return -6;
  146.  
  147.   updateStates();
  148.  
  149.   return 0;
  150. }
  151.  
  152. //------------------------------------------------------------------
  153. // Callback function for power profile policy enumeration
  154. //------------------------------------------------------------------
  155. BOOLEAN __stdcall powerSchemeCallback(
  156.   UINT uiIndex,      // power scheme index
  157.   DWORD dwName,      // size of the sName string, in bytes
  158.   LPTSTR sName,      // name of the power scheme
  159.   DWORD dwDesc,      // size of the sDesc string, in bytes
  160.   LPTSTR sDesc,      // description string
  161.   PPOWER_POLICY pp,  // receives the power policy
  162.   LPARAM lParam      // user-defined value
  163. )
  164. {
  165.   lastChecked = uiIndex;
  166.  
  167.   wsprintf( &msg[strlen(msg)], "Checking scheme: %s (#%d)\n", uc2char(dummy,sName), uiIndex );
  168.  
  169.   if( !stricmp(dummy,PROFILENAME) )
  170.   {
  171.     internalProfile = uiIndex;
  172.     internalPolicy = *pp;
  173.     return FALSE;
  174.   }
  175.   
  176.   return TRUE;
  177. }
  178.  
  179. //------------------------------------------------------------------
  180. // get current ac/dc throttle from cpu policy
  181. //------------------------------------------------------------------
  182. void updateStates()
  183. {
  184.   acThrottle = mach.ProcessorPolicyAc.DynamicThrottle;
  185.   dcThrottle = mach.ProcessorPolicyDc.DynamicThrottle;
  186. }
  187.  
  188. //------------------------------------------------------------------
  189. // set current ac/dc throttle and activate that
  190. //------------------------------------------------------------------
  191. BOOL setState( BOOL ac, BYTE policy )
  192. {
  193.   checkProfile( 1 );
  194.  
  195.   if( ac )
  196.   {
  197.     acThrottle = policy;
  198.     mach.ProcessorPolicyAc.DynamicThrottle = policy;
  199.   }
  200.   else
  201.   {
  202.     dcThrottle = policy;
  203.     mach.ProcessorPolicyDc.DynamicThrottle = policy;
  204.   }
  205.  
  206.   if( !WriteProcessorPwrScheme(internalProfile,&mach) )
  207.     return FALSE;
  208.  
  209.   if( !SetActivePwrScheme(internalProfile,NULL,NULL) )
  210.     return FALSE;  
  211.  
  212.   return TRUE;
  213. }
  214.  
  215. //------------------------------------------------------------------
  216. // convert unicode string to ansi string
  217. //------------------------------------------------------------------
  218. static char* uc2char( char* dest, void* s )
  219. {
  220.   char* t = (char*)s;
  221.   int i=-1;
  222.   int j=-1;
  223.   
  224.   do {
  225.     dest[++i] = t[++j];
  226.     t++;
  227.   } while( dest[i] );
  228.   
  229.   return dest;      
  230. }
  231.  
  232. //------------------------------------------------------------------
  233. // convert ansi string to unicode string
  234. //------------------------------------------------------------------
  235. static char* char2uc( char* dest, char* s )
  236. {
  237.   char* t = (char*)s;
  238.   int i=-1;
  239.   int j=-1;
  240.   
  241.   do {
  242.     dest[++i] = t[++j];
  243.     dest[++i] = '\0';
  244.   } while( t[j] );
  245.   
  246.   return dest;      
  247. }
  248.  
  249. //------------------------------------------------------------------
  250. // convert CPU policy setting to string
  251. //------------------------------------------------------------------
  252. char* throttleString( UCHAR throttle )
  253. {
  254.   switch( throttle )
  255.   {
  256.     case PO_THROTTLE_NONE:      return "Max. Performance";
  257.     case PO_THROTTLE_CONSTANT:  return "Battery optimized";
  258.     case PO_THROTTLE_DEGRADE:   return "Max. Battery";
  259.     case PO_THROTTLE_ADAPTIVE:  return "Dynamic switching";
  260.   }
  261.   
  262.   return "(UNKNOWN)";    
  263. }
  264.  
  265. //------------------------------------------------------------------
  266. // power state to string
  267. //------------------------------------------------------------------
  268. char* sysPwrState( SYSTEM_POWER_STATE state )
  269. {
  270.   switch( state )
  271.   {
  272.     case PowerSystemUnspecified: return "No wake up when lid opened";
  273.     case PowerSystemWorking:     return "S0";
  274.     case PowerSystemSleeping1:   return "S1";
  275.     case PowerSystemSleeping2:   return "S2";
  276.     case PowerSystemSleeping3:   return "S3";
  277.     case PowerSystemHibernate:   return "S4 (Hibernate)";
  278.     case PowerSystemShutdown:    return "S5 (Off)";
  279.     case PowerSystemMaximum:     return "???";
  280.   }
  281.     
  282.   return "(UNKNOWN)";
  283. }
  284.  
  285. //------------------------------------------------------------------
  286. // power action to string
  287. //------------------------------------------------------------------
  288. char* pwrAction( POWER_ACTION action )
  289. {
  290.   switch( action )
  291.   {
  292.     case PowerActionNone:          return "No action";
  293.     case PowerActionReserved:      return "(reserved setting)";
  294.     case PowerActionSleep:         return "Sleep";
  295.     case PowerActionHibernate:     return "Hibernate";
  296.     case PowerActionShutdown:      return "Shutdown";
  297.     case PowerActionShutdownReset: return "Shutdown and reset";
  298.     case PowerActionShutdownOff:   return "Shutdown and power off";
  299.     case PowerActionWarmEject:     return "Warm eject";
  300.   }
  301.     
  302.   return "(UNKNOWN)";
  303. }
  304.  
  305. //------------------------------------------------------------------
  306. // get CPU usage on NT-style operating systems
  307. //------------------------------------------------------------------
  308. DWORD cpuUsageNT()
  309. {
  310.   static SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo;
  311.   static SYSTEM_TIME_INFORMATION SysTimeInfo;
  312.   static SYSTEM_BASIC_INFORMATION SysBaseInfo;
  313.   static double dbIdleTime;
  314.   static double dbSystemTime;
  315.   static LONG status;
  316.   static LARGE_INTEGER liOldIdleTime = {0,0};
  317.   static LARGE_INTEGER liOldSystemTime = {0,0};
  318.   static BOOL init = FALSE;
  319.   static PROCNTQSI NtQuerySystemInformation = NULL;
  320.   DWORD retVal = 0xffffffff;
  321.  
  322.   if( !init )
  323.   {
  324.     NtQuerySystemInformation = (PROCNTQSI)GetProcAddress( GetModuleHandle("ntdll"), "NtQuerySystemInformation" );
  325.  
  326.     if( !NtQuerySystemInformation )
  327.       return 0xffffffff;
  328.  
  329.     // get number of processors in the system
  330.     status = NtQuerySystemInformation( SystemBasicInformation, &SysBaseInfo, sizeof(SysBaseInfo), NULL );
  331.     if( status != NO_ERROR )
  332.       return 0xffffffff;
  333.  
  334.     init = TRUE;
  335.   }
  336.  
  337.   // get new system time
  338.   status = NtQuerySystemInformation( SystemTimeInformation, &SysTimeInfo, sizeof(SysTimeInfo), 0 );
  339.  
  340.   if( status != NO_ERROR )
  341.     return 0xffffffff;
  342.  
  343.   // get new CPU's idle time
  344.   status = NtQuerySystemInformation( SystemPerformanceInformation, &SysPerfInfo, sizeof(SysPerfInfo), NULL );
  345.   if( status != NO_ERROR )
  346.     return 0xffffffff;
  347.  
  348.   // if it's a first call - skip it
  349.   if( liOldIdleTime.QuadPart != 0 )
  350.   {
  351.     // CurrentValue = NewValue - OldValue
  352.     dbIdleTime = Li2Double( SysPerfInfo.liIdleTime ) - Li2Double( liOldIdleTime );
  353.     dbSystemTime = Li2Double( SysTimeInfo.liKeSystemTime ) - Li2Double( liOldSystemTime );
  354.  
  355.     // CurrentCpuIdle = IdleTime / SystemTime
  356.     dbIdleTime = dbIdleTime / dbSystemTime;
  357.  
  358.     // CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors
  359.     dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SysBaseInfo.bKeNumberProcessors + 0.5;
  360.     
  361.     retVal = (DWORD)dbIdleTime;
  362.   }
  363.  
  364.   // store new CPU's idle and system time
  365.   liOldIdleTime = SysPerfInfo.liIdleTime;
  366.   liOldSystemTime = SysTimeInfo.liKeSystemTime;
  367.  
  368.   return retVal;
  369. }
  370.  
  371. //------------------------------------------------------------------
  372. // write changed power policies
  373. //
  374. // return codes:
  375. //   -1: power policy writing failure
  376. //   -2: cpu policy writing failure
  377. //   0: success
  378. //------------------------------------------------------------------
  379. int writePolicies( BOOL power, BOOL cpu )
  380. {
  381.   if( power && !WritePwrScheme(&internalProfile,char2uc(dummy,PROFILENAME),"\0\0",&internalPolicy) )
  382.   {
  383.     ReadPwrScheme( internalProfile, &internalPolicy );
  384.     return -1;
  385.   }
  386.  
  387.   if( cpu && !WriteProcessorPwrScheme(internalProfile,&mach) )
  388.   {
  389.     ReadProcessorPwrScheme( internalProfile, &mach );
  390.  
  391.     if( power )
  392.       SetActivePwrScheme( internalProfile, NULL, NULL );
  393.  
  394.     return -2;
  395.   }
  396.  
  397.   SetActivePwrScheme( internalProfile, NULL, NULL );
  398.   return 0;
  399. }
  400.  
  401. //------------------------------------------------------------------
  402. // check power scheme integrity
  403. //
  404. // check: 0=no consistency check
  405. //        1=check power scheme only
  406. //        2=check processor scheme only
  407. //        3=check both power and processor scheme
  408. //------------------------------------------------------------------
  409. BOOL checkProfile( int check )
  410. {
  411.   log( "Checking power scheme integrity ..." );
  412.  
  413.   POWER_POLICY policyTemp;
  414.   MACHINE_PROCESSOR_POWER_POLICY machTemp;
  415.   static char msg[1024];   // fⁿr diverse Fehlertexte
  416.   BOOL forceActivate = FALSE;
  417.  
  418.   if( !ReadPwrScheme(internalProfile,&policyTemp) )
  419.   {
  420.     log( "Recreating power scheme ..." );
  421.     UINT x = internalProfile;
  422.     if( !WritePwrScheme(&x,char2uc(dummy,PROFILENAME),"\0\0",&internalPolicy) )
  423.     {
  424.       wsprintf( msg, "Can't recreate power scheme (Code %d)", GetLastError() );
  425.       MessageBox( NULL, msg, "SpeedswitchXP error", MB_ICONEXCLAMATION|MB_OK );
  426.       return FALSE;
  427.     }
  428.  
  429.     forceActivate = TRUE;
  430.   }
  431.   else if( check&1 )
  432.   {
  433.     if( !comparePowerProfile(policyTemp,internalPolicy) )
  434.     {
  435.       log( "Restoring power scheme data ..." );
  436.       UINT x = internalProfile;
  437.       if( !WritePwrScheme(&x,char2uc(dummy,PROFILENAME),"\0\0",&internalPolicy) )
  438.       {
  439.         wsprintf( msg, "Can't recreate power scheme (Code %d)", GetLastError() );
  440.         MessageBox( NULL, msg, "SpeedswitchXP error", MB_ICONEXCLAMATION|MB_OK );
  441.         return FALSE;
  442.       }
  443.  
  444.       forceActivate = TRUE;
  445.     }
  446.   }
  447.  
  448.   if( !ReadProcessorPwrScheme(internalProfile,&machTemp) )
  449.   {
  450.     log( "Recreating processor scheme ..." );
  451.     if( !WriteProcessorPwrScheme(internalProfile,&mach) )
  452.     {
  453.       wsprintf( msg, "Can't recreate processor scheme (Code %d)", GetLastError() );
  454.       MessageBox( NULL, msg, "SpeedswitchXP error", MB_ICONEXCLAMATION|MB_OK );
  455.       return FALSE;
  456.     }   
  457.  
  458.     forceActivate = TRUE;
  459.   }
  460.   else if( check&2 )
  461.   {
  462.     if( !compareCPUScheme(machTemp,mach) )
  463.     {
  464.       log( "Restoring processor scheme data ..." );
  465.       if( !WriteProcessorPwrScheme(internalProfile,&mach) )
  466.       {
  467.         wsprintf( msg, "Can't recreate processor scheme (Code %d)", GetLastError() );
  468.         MessageBox( NULL, msg, "SpeedswitchXP error", MB_ICONEXCLAMATION|MB_OK );
  469.         return FALSE;
  470.       }  
  471.  
  472.       forceActivate = TRUE;
  473.     }
  474.   }
  475.  
  476.   UINT profile;
  477.  
  478.   if( !GetActivePwrScheme(&profile) )
  479.   {
  480.     wsprintf( msg, "Error reading active power scheme no (Code %d)", GetLastError() );
  481.     MessageBox( NULL, msg, "SpeedswitchXP error", MB_OK|MB_ICONEXCLAMATION );
  482.     return FALSE;
  483.   }
  484.  
  485.   if( forceActivate || profile!=internalProfile )
  486.   {
  487.     log( "Reactivating power scheme (%d, %d) ...", profile, internalProfile );
  488.     if( !SetActivePwrScheme(internalProfile,NULL,NULL) )
  489.     {
  490.       wsprintf( msg, "Can't reenable internal power scheme (Code %d)", GetLastError() );
  491.       MessageBox( NULL, msg, "SpeedswitchXP error", MB_ICONEXCLAMATION|MB_OK );
  492.       return FALSE;
  493.     }
  494.   }
  495.  
  496.   return TRUE;
  497. }
  498.  
  499. static BOOL comparePowerProfile( POWER_POLICY& pol1, POWER_POLICY& pol2 )
  500. {
  501.   return pol1.user.Revision == pol2.user.Revision
  502.     &&   comparePowerActionPolicy(pol1.user.IdleAc,pol2.user.IdleAc)
  503.     &&   comparePowerActionPolicy(pol1.user.IdleDc,pol2.user.IdleDc)
  504.     &&   pol1.user.IdleTimeoutAc == pol2.user.IdleTimeoutAc
  505.     &&   pol1.user.IdleTimeoutDc == pol2.user.IdleTimeoutDc
  506.     &&   pol1.user.IdleSensitivityAc == pol2.user.IdleSensitivityAc
  507.     &&   pol1.user.IdleSensitivityDc == pol2.user.IdleSensitivityDc
  508.     &&   pol1.user.ThrottlePolicyAc == pol2.user.ThrottlePolicyAc
  509.     &&   pol1.user.ThrottlePolicyDc == pol2.user.ThrottlePolicyDc
  510.     &&   pol1.user.MaxSleepAc == pol2.user.MaxSleepAc
  511.     &&   pol1.user.MaxSleepDc == pol2.user.MaxSleepDc
  512.     &&   pol1.user.VideoTimeoutAc == pol2.user.VideoTimeoutAc
  513.     &&   pol1.user.VideoTimeoutDc == pol2.user.VideoTimeoutDc
  514.     &&   pol1.user.SpindownTimeoutAc == pol2.user.SpindownTimeoutAc
  515.     &&   pol1.user.SpindownTimeoutDc == pol2.user.SpindownTimeoutDc
  516.     &&   pol1.user.OptimizeForPowerAc == pol2.user.OptimizeForPowerAc
  517.     &&   pol1.user.OptimizeForPowerDc == pol2.user.OptimizeForPowerDc
  518.     &&   pol1.user.FanThrottleToleranceAc == pol2.user.FanThrottleToleranceAc
  519.     &&   pol1.user.FanThrottleToleranceDc == pol2.user.FanThrottleToleranceDc
  520.     &&   pol1.user.ForcedThrottleAc == pol2.user.ForcedThrottleAc
  521.     &&   pol1.user.ForcedThrottleDc == pol2.user.ForcedThrottleDc
  522.     &&   pol1.mach.Revision == pol2.mach.Revision
  523.     &&   pol1.mach.MinSleepAc == pol2.mach.MinSleepAc
  524.     &&   pol1.mach.MinSleepDc == pol2.mach.MinSleepDc
  525.     &&   pol1.mach.ReducedLatencySleepAc == pol2.mach.ReducedLatencySleepAc
  526.     &&   pol1.mach.ReducedLatencySleepDc == pol2.mach.ReducedLatencySleepDc
  527.     &&   pol1.mach.DozeTimeoutAc == pol2.mach.DozeTimeoutAc
  528.     &&   pol1.mach.DozeTimeoutDc == pol2.mach.DozeTimeoutDc
  529.     &&   pol1.mach.DozeS4TimeoutAc == pol2.mach.DozeS4TimeoutAc
  530.     &&   pol1.mach.DozeS4TimeoutDc == pol2.mach.DozeS4TimeoutDc
  531.     &&   pol1.mach.MinThrottleAc == pol2.mach.MinThrottleAc
  532.     &&   pol1.mach.MinThrottleDc == pol2.mach.MinThrottleDc
  533.     &&   comparePowerActionPolicy(pol1.mach.OverThrottledAc,pol2.mach.OverThrottledAc)
  534.     &&   comparePowerActionPolicy(pol1.mach.OverThrottledDc,pol2.mach.OverThrottledDc);
  535. }
  536.  
  537. static BOOL comparePowerActionPolicy( POWER_ACTION_POLICY& pol1, POWER_ACTION_POLICY& pol2 )
  538. {
  539.   return pol1.Action == pol2.Action
  540.     &&   pol1.EventCode == pol2.EventCode
  541.     &&   pol1.Flags == pol2.Flags;
  542. }
  543.  
  544. static BOOL compareCPUScheme( MACHINE_PROCESSOR_POWER_POLICY& pol1, MACHINE_PROCESSOR_POWER_POLICY& pol2 )
  545. {
  546.   return pol1.Revision == pol2.Revision
  547.     &&   compareCPUPowerPolicy(pol1.ProcessorPolicyAc,pol2.ProcessorPolicyAc)
  548.     &&   compareCPUPowerPolicy(pol1.ProcessorPolicyDc,pol2.ProcessorPolicyDc);
  549. }
  550.  
  551. static BOOL compareCPUPowerPolicy( PROCESSOR_POWER_POLICY& pol1, PROCESSOR_POWER_POLICY& pol2 )
  552. {
  553.   return pol1.Revision == pol2.Revision
  554.     &&   pol1.DynamicThrottle == pol2.DynamicThrottle
  555.     &&   pol1.PolicyCount == pol2.PolicyCount
  556.     &&   ((pol1.PolicyCount>0) ? compareCPUPowerPolicyInfo(pol1.Policy[0],pol2.Policy[0]) : TRUE)
  557.     &&   ((pol1.PolicyCount>1) ? compareCPUPowerPolicyInfo(pol1.Policy[1],pol2.Policy[1]) : TRUE)
  558.     &&   ((pol1.PolicyCount>2) ? compareCPUPowerPolicyInfo(pol1.Policy[2],pol2.Policy[2]) : TRUE);
  559. }
  560.  
  561. static BOOL compareCPUPowerPolicyInfo( PROCESSOR_POWER_POLICY_INFO& pol1, PROCESSOR_POWER_POLICY_INFO& pol2 )
  562. {
  563.   return pol1.TimeCheck == pol2.TimeCheck
  564.     &&   pol1.DemoteLimit == pol2.DemoteLimit
  565.     &&   pol1.PromoteLimit == pol2.PromoteLimit
  566.     &&   pol1.DemotePercent == pol2.DemotePercent
  567.     &&   pol1.PromotePercent == pol2.PromotePercent
  568.     &&   pol1.AllowDemotion == pol2.AllowDemotion
  569.     &&   pol1.AllowPromotion == pol2.AllowPromotion;
  570. }
  571.  
  572.