/******************************************************************************* * * (C) COPYRIGHT MICROSOFT CORP., 1996 * * TITLE: PWRSCHEM.C * * VERSION: 2.0 * * AUTHOR: ReedB * * DATE: 17 Oct, 1996 * * DESCRIPTION: * Support for power scheme page (front page) of PowerCfg.Cpl. * *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include "powercfg.h" #include "pwrresid.h" #include "PwrMn_cs.h" #include // Structure to manage the scheme list information. typedef struct _SCHEME_LIST { LIST_ENTRY leSchemeList; UINT uiID; LPTSTR lpszName; LPTSTR lpszDesc; PPOWER_POLICY ppp; } SCHEME_LIST, *PSCHEME_LIST; // Structure to manage the power scheme dialog proc info. typedef struct _POWER_SCHEME_DLG_INFO { HWND hwndSchemeList; } POWER_SCHEME_DLG_INFO, *PPOWER_SCHEME_DLG_INFO; // Private functions implemented in PWRSCHEM.C: UINT StripBlanks(LPTSTR, DWORD); UINT RangeLimitHiberTimeOuts(UINT uiIdleTimeout, UINT *uiHiberToIDs); VOID RefreshSchemes(HWND, PSCHEME_LIST); VOID HandleIdleTimeOutChanged(HWND hWnd, UINT uMsg, WPARAM wParam, BOOL *pbDirty); LONG MsgBoxId(HWND, UINT, UINT, LPTSTR, UINT); BOOLEAN DoDeleteScheme(HWND, LPTSTR); BOOLEAN DoSaveScheme(HWND); BOOLEAN ClearSchemeList(VOID); BOOLEAN RemoveScheme(PSCHEME_LIST, LPTSTR); BOOLEAN PowerSchemeDlgInit(HWND, PPOWER_SCHEME_DLG_INFO); BOOLEAN CALLBACK PowerSchemeEnumProc(UINT, DWORD, LPTSTR, DWORD, LPTSTR, PPOWER_POLICY, LPARAM); BOOLEAN HandleCurSchemeChanged(HWND hWnd); BOOLEAN MapHiberTimer(PPOWER_POLICY ppp, BOOLEAN Get); PSCHEME_LIST GetCurSchemeFromCombo(HWND hWnd); PSCHEME_LIST FindScheme(LPTSTR, BOOLEAN); PSCHEME_LIST AddScheme(UINT, LPTSTR, UINT, LPTSTR, UINT, PPOWER_POLICY); PSCHEME_LIST FindNextScheme(LPTSTR); /******************************************************************************* * * G L O B A L D A T A * *******************************************************************************/ extern HINSTANCE g_hInstance; // Global instance handle of this DLL. // This structure is filled in by the Power Policy Manager at CPL_INIT time. extern SYSTEM_POWER_CAPABILITIES g_SysPwrCapabilities; extern BOOLEAN g_bVideoLowPowerSupported; extern DWORD g_dwNumSleepStates; extern UINT g_uiSpindownMaxMin; extern BOOL g_bRunningUnderNT; UINT g_uiTimeoutIDs[] = // Timeout string ID's. { IDS_01_MIN, 60 * 1, // 1 Min. IDS_02_MIN, 60 * 2, IDS_03_MIN, 60 * 3, IDS_05_MIN, 60 * 5, IDS_10_MIN, 60 * 10, IDS_15_MIN, 60 * 15, IDS_20_MIN, 60 * 20, IDS_25_MIN, 60 * 25, IDS_30_MIN, 60 * 30, IDS_45_MIN, 60 * 45, IDS_01_HOUR, 60 * 60 * 1, // 1 Hour IDS_02_HOUR, 60 * 60 * 2, IDS_03_HOUR, 60 * 60 * 3, IDS_04_HOUR, 60 * 60 * 4, IDS_05_HOUR, 60 * 60 * 5, IDS_NEVER, 0, 0, 0 }; UINT g_uiHiberToIDs[] = // Hiber timeout string ID's. { IDS_01_MIN, 60 * 1, // 1 Min. IDS_02_MIN, 60 * 2, IDS_03_MIN, 60 * 3, IDS_05_MIN, 60 * 5, IDS_10_MIN, 60 * 10, IDS_15_MIN, 60 * 15, IDS_20_MIN, 60 * 20, IDS_25_MIN, 60 * 25, IDS_30_MIN, 60 * 30, IDS_45_MIN, 60 * 45, IDS_01_HOUR, 60 * 60 * 1, // 1 Hour IDS_02_HOUR, 60 * 60 * 2, IDS_03_HOUR, 60 * 60 * 3, IDS_04_HOUR, 60 * 60 * 4, IDS_05_HOUR, 60 * 60 * 5, IDS_06_HOUR, 60 * 60 * 6, IDS_NEVER, 0, 0, 0 }; UINT g_uiHiberToAcIDs[sizeof(g_uiHiberToIDs)]; // Hibernate AC timeout string ID's. UINT g_uiHiberToDcIDs[sizeof(g_uiHiberToIDs)]; // Hibernate DC timeout string ID's. UINT g_uiSpinDownIDs[] = // Disk spin down timeout string ID's. { IDS_01_MIN, 60 * 1, // 1 Min. IDS_02_MIN, 60 * 2, IDS_03_MIN, 60 * 3, IDS_05_MIN, 60 * 5, IDS_10_MIN, 60 * 10, IDS_15_MIN, 60 * 15, IDS_20_MIN, 60 * 20, IDS_25_MIN, 60 * 25, IDS_30_MIN, 60 * 30, IDS_45_MIN, 60 * 45, IDS_01_HOUR, 60 * 60 * 1, // 1 Hour IDS_02_HOUR, 60 * 60 * 2, IDS_03_HOUR, 60 * 60 * 3, IDS_04_HOUR, 60 * 60 * 4, IDS_05_HOUR, 60 * 60 * 5, IDS_NEVER, 0, 0, 0 }; // Show/hide UI state variables for power schemes dialog. UINT g_uiWhenComputerIsState; UINT g_uiStandbyState; UINT g_uiMonitorState; UINT g_uiDiskState; UINT g_uiHiberState; UINT g_uiHiberTimeoutAc; UINT g_uiHiberTimeoutDc; UINT g_uiIdleTimeoutAc; UINT g_uiIdleTimeoutDc; // Power schemes dialog controls descriptions: UINT g_uiNumPwrSchemeCntrls; #define NUM_POWER_SCHEME_CONTROLS 17 #define NUM_POWER_SCHEME_CONTROLS_NOBAT 8 // Handy indicies into our g_pcPowerScheme control array #define ID_GOONSTANDBY 0 #define ID_STANDBYACCOMBO 1 #define ID_TURNOFFMONITOR 2 #define ID_MONITORACCOMBO 3 #define ID_TURNOFFHARDDISKS 4 #define ID_DISKACCOMBO 5 #define ID_SYSTEMHIBERNATES 6 #define ID_HIBERACCOMBO 7 #define ID_STANDBYDCCOMBO 8 #define ID_MONITORDCCOMBO 9 #define ID_DISKDCCOMBO 10 #define ID_HIBERDCCOMBO 11 #define ID_WHENCOMPUTERIS 12 #define ID_PLUGGEDIN 13 #define ID_RUNNINGONBAT 14 #define ID_PLUG 15 #define ID_BATTERY 16 POWER_CONTROLS g_pcPowerScheme[NUM_POWER_SCHEME_CONTROLS] = {// Control ID Control Type Data Address Data Size Parameter Pointer EnableVisible State Pointer IDC_GOONSTANDBY, STATIC_TEXT, NULL, 0, NULL, &g_uiStandbyState, IDC_STANDBYACCOMBO, COMBO_BOX, &g_uiTimeoutIDs, sizeof(DWORD), &g_uiIdleTimeoutAc, &g_uiStandbyState, IDC_TURNOFFMONITOR, STATIC_TEXT, NULL, 0, NULL, &g_uiMonitorState, IDC_MONITORACCOMBO, COMBO_BOX, &g_uiTimeoutIDs, sizeof(DWORD), NULL, &g_uiMonitorState, IDC_TURNOFFHARDDISKS, STATIC_TEXT, NULL, 0, NULL, &g_uiDiskState, IDC_DISKACCOMBO, COMBO_BOX, &g_uiSpinDownIDs, sizeof(DWORD), NULL, &g_uiDiskState, IDC_SYSTEMHIBERNATES, STATIC_TEXT, NULL, 0, NULL, &g_uiHiberState, IDC_HIBERACCOMBO, COMBO_BOX, &g_uiHiberToAcIDs, sizeof(DWORD), &g_uiHiberTimeoutAc, &g_uiHiberState, IDC_STANDBYDCCOMBO, COMBO_BOX, &g_uiTimeoutIDs, sizeof(DWORD), &g_uiIdleTimeoutDc, &g_uiStandbyState, IDC_MONITORDCCOMBO, COMBO_BOX, &g_uiTimeoutIDs, sizeof(DWORD), NULL, &g_uiMonitorState, IDC_DISKDCCOMBO, COMBO_BOX, &g_uiSpinDownIDs, sizeof(DWORD), NULL, &g_uiDiskState, IDC_HIBERDCCOMBO, COMBO_BOX, &g_uiHiberToDcIDs, sizeof(DWORD), &g_uiHiberTimeoutDc, &g_uiHiberState, IDC_WHENCOMPUTERIS, STATIC_TEXT, NULL, 0, NULL, &g_uiWhenComputerIsState, IDC_PLUGGEDIN, STATIC_TEXT, NULL, 0, NULL, &g_uiWhenComputerIsState, IDC_RUNNINGONBAT, STATIC_TEXT, NULL, 0, NULL, &g_uiWhenComputerIsState, IDI_PLUG, STATIC_TEXT, NULL, 0, NULL, &g_uiWhenComputerIsState, IDI_BATTERY, STATIC_TEXT, NULL, 0, NULL, &g_uiWhenComputerIsState, }; // Show/hide UI state variables for advanced power schemes dialog. UINT g_uiAdvWhenComputerIsState; UINT g_uiOptimizeState; // Globals to manage the power schemes list: SCHEME_LIST g_sl; // Head of the power schemes list. PSCHEME_LIST g_pslCurActive; // Currently active power scheme. PSCHEME_LIST g_pslCurSel; // Currently selected power scheme. PSCHEME_LIST g_pslValid; // A valid scheme for error recovery. UINT g_uiSchemeCount; // Number of power schemes. LIST_ENTRY g_leSchemeList; // Head of the power schemes list. BOOL g_bSystrayChange; // A systary change requires PowerSchemeDlgProc re-init. // "Power Schemes" Dialog Box (IDD_POWERSCHEME == 100) help arrays: const DWORD g_PowerSchemeHelpIDs[]= { IDC_SCHEMECOMBO, IDH_100_1000, // Power Schemes: "Power schemes" (ComboBox) IDC_POWERSCHEMESTEXT, IDH_COMM_GROUPBOX, IDC_SAVEAS, IDH_100_1001, // Power Schemes: "&Save As..." (Button) IDC_DELETE, IDH_100_1002, // Power Schemes: "&Delete" (Button) IDC_SETTINGSFOR, IDH_COMM_GROUPBOX, // Power Schemes: "Settings for groupbox" (Button) IDC_GOONSTANDBY, IDH_100_1009, // Power Schemes: "Go on s&tandby:" (Static) IDC_STANDBYACCOMBO, IDH_100_1005, // Power Schemes: "Standby AC time" (ComboBox) IDC_STANDBYDCCOMBO, IDH_100_1006, // Power Schemes: "Standby DC time" (ComboBox) IDC_SYSTEMHIBERNATES, IDH_SYSTEMHIBERNATES, IDC_HIBERACCOMBO, IDH_HIBERACCOMBO, IDC_HIBERDCCOMBO, IDH_HIBERDCCOMBO, IDC_TURNOFFMONITOR, IDH_100_1010, // Power Schemes: "Turn off &monitor:" (Static) IDC_MONITORACCOMBO, IDH_100_1007, // Power Schemes: "Monitor AC time" (ComboBox) IDC_MONITORDCCOMBO, IDH_100_1008, // Power Schemes: "Monitor DC time" (ComboBox) IDC_TURNOFFHARDDISKS, IDH_107_1509, // Advanced Power Scheme Settings: "Turn off hard &disks:" (Static) IDC_DISKACCOMBO, IDH_107_1505, // Advanced Power Scheme Settings: "Disk off time AC" (ComboBox) IDC_DISKDCCOMBO, IDH_107_1506, // Advanced Power Scheme Settings: "Disk off time DC" (ComboBox) IDC_PLUGGEDIN, NO_HELP, IDC_NO_HELP_0, NO_HELP, IDC_NO_HELP_7, NO_HELP, IDI_PWRMNG, NO_HELP, IDI_PLUG, NO_HELP, IDI_BATTERY, NO_HELP, IDC_WHENCOMPUTERIS, NO_HELP, IDC_PLUGGEDIN, NO_HELP, IDC_RUNNINGONBAT, NO_HELP, 0, 0 }; // "Save Scheme" Dialog Box (IDD_SAVE == 109) help ID's: #define IDH_109_1700 111411309 // Save Scheme: "Save name power scheme" (Edit) // "Save Scheme" Dialog Box (IDD_SAVE == 109) help array: const DWORD g_SaveAsHelpIDs[]= { IDC_SAVENAMEEDIT, IDH_109_1700, // Save Scheme: "Save name power scheme" (Edit) IDC_SAVETEXT, IDH_109_1700, 0, 0 }; /******************************************************************************* * * P U B L I C E N T R Y P O I N T S * *******************************************************************************/ /******************************************************************************* * * InitSchemesList * * DESCRIPTION: * Called once at DLL initialization time. * * PARAMETERS: * *******************************************************************************/ VOID InitSchemesList(VOID) { InitializeListHead(&g_leSchemeList); } /******************************************************************************* * * SaveAsDlgProc * * DESCRIPTION: * * PARAMETERS: * Dialog procedure for the advanced power scheme dialog. * *******************************************************************************/ INT_PTR CALLBACK SaveAsDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { TCHAR szBuf[2 * MAX_FRIENDLY_NAME_LEN]; // Leave room for DBCS PSCHEME_LIST pslNew; static PBOOLEAN pbSavedCurrent; switch (uMsg) { case WM_INITDIALOG: SetDlgItemText(hWnd, IDC_SAVENAMEEDIT, g_pslCurSel->lpszName); SendDlgItemMessage(hWnd, IDC_SAVENAMEEDIT, EM_SETSEL, 0, -1); SendDlgItemMessage(hWnd, IDC_SAVENAMEEDIT, EM_LIMITTEXT, MAX_FRIENDLY_NAME_LEN-2, 0L); EnableWindow(GetDlgItem(hWnd, IDOK), (g_pslCurSel->lpszName[0] != TEXT('\0'))); pbSavedCurrent = (PBOOLEAN) lParam; *pbSavedCurrent = FALSE; return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_SAVENAMEEDIT: if (HIWORD(wParam) == EN_CHANGE) { GetDlgItemText(hWnd, IDC_SAVENAMEEDIT, szBuf, 2); if (*szBuf) { EnableWindow(GetDlgItem(hWnd, IDOK), TRUE); } } break; case IDOK: GetDlgItemText(hWnd, IDC_SAVENAMEEDIT, szBuf, MAX_FRIENDLY_NAME_LEN-1); // Strip trailing blanks, don't allow blank scheme name. if (!StripBlanks(szBuf, ARRAYSIZE(szBuf))) { MsgBoxId(hWnd, IDS_SAVESCHEME, IDS_BLANKNAME, NULL, MB_OK | MB_ICONEXCLAMATION); return TRUE; } // Insert a new policies element in the policies list. pslNew = AddScheme(NEWSCHEME, szBuf, STRSIZE(szBuf), TEXT(""), sizeof(TCHAR), g_pslCurSel->ppp); // Write out the Scheme. if (pslNew) { if ( WritePwrSchemeReport(hWnd, &(pslNew->uiID), pslNew->lpszName, pslNew->lpszDesc, pslNew->ppp) ) { if ( g_pslCurSel == pslNew ) { *pbSavedCurrent = TRUE; } else { g_pslCurSel = pslNew; } } } // fall thru to IDCANCEL case IDCANCEL: EndDialog(hWnd, wParam); break; } break; case WM_HELP: // F1 WinHelp(((LPHELPINFO)lParam)->hItemHandle, PWRMANHLP, HELP_WM_HELP, (ULONG_PTR)(LPTSTR)g_SaveAsHelpIDs); return TRUE; case WM_CONTEXTMENU: // right mouse click WinHelp((HWND)wParam, PWRMANHLP, HELP_CONTEXTMENU, (ULONG_PTR)(LPTSTR)g_SaveAsHelpIDs); return TRUE; } return FALSE; } /******************************************************************************* * * PowerSchemeDlgProc * * DESCRIPTION: * Dialog procedure for power scheme page. * * PARAMETERS: * *******************************************************************************/ INT_PTR CALLBACK PowerSchemeDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { NMHDR FAR *lpnm; UINT uiNewSel, uiNewState; LPTSTR pszUPS; static POWER_SCHEME_DLG_INFO psdi; static BOOL bDirty = FALSE; static BOOL bInitFailed = FALSE; if (bInitFailed) { return FALSE; } switch (uMsg) { case WM_INITDIALOG: // Set the control count to match the dialog template we're using. if (g_SysPwrCapabilities.SystemBatteriesPresent) { g_uiNumPwrSchemeCntrls = NUM_POWER_SCHEME_CONTROLS; if (g_SysPwrCapabilities.BatteriesAreShortTerm) { pszUPS = LoadDynamicString(IDS_POWEREDBYUPS); DisplayFreeStr(hWnd, IDC_RUNNINGONBAT, pszUPS, FREE_STR); } } else { g_uiNumPwrSchemeCntrls = NUM_POWER_SCHEME_CONTROLS_NOBAT; } if (!PowerSchemeDlgInit(hWnd, &psdi)) { bInitFailed = TRUE; } return TRUE; case WM_CHILDACTIVATE: // If Systray changed something while another property page (dialog) // had the focus reinitialize the dialog. if (g_bSystrayChange) { PowerSchemeDlgInit(hWnd, &psdi); g_bSystrayChange = FALSE; } // Reinitialize hibernate timer since the hibernate tab // may have changed it's state. if (GetPwrCapabilities(&g_SysPwrCapabilities)) { if (g_bRunningUnderNT && g_SysPwrCapabilities.SystemS4 && g_SysPwrCapabilities.SystemS5 && g_SysPwrCapabilities.HiberFilePresent) { uiNewState = CONTROL_ENABLE; } else { uiNewState = CONTROL_HIDE; } if (g_bRunningUnderNT && (g_uiStandbyState == CONTROL_HIDE) && (g_SysPwrCapabilities.SystemS1 || g_SysPwrCapabilities.SystemS2 || g_SysPwrCapabilities.SystemS3)) { g_uiStandbyState = CONTROL_ENABLE; } } if (g_uiHiberState != uiNewState) { g_uiHiberState = uiNewState; MapHiberTimer(g_pslCurSel->ppp, FALSE); SetControls(hWnd, g_uiNumPwrSchemeCntrls, g_pcPowerScheme); } break; case WM_NOTIFY: lpnm = (NMHDR FAR *)lParam; switch(lpnm->code) { case PSN_APPLY: if (bDirty) { // Do the hibernate PSN_APPLY since the // PowerSchemeDlgProc PSN_APPLY logic depends // on hibernate state. DoHibernateApply(); GetControls(hWnd, g_uiNumPwrSchemeCntrls, g_pcPowerScheme); MapHiberTimer(g_pslCurSel->ppp, TRUE); // Set active scheme. if (SetActivePwrSchemeReport(hWnd, g_pslCurSel->uiID, NULL, g_pslCurSel->ppp)) { if (g_pslCurSel != g_pslCurActive) { g_pslCurActive = g_pslCurSel; RefreshSchemes(hWnd, g_pslCurSel); } } bDirty = FALSE; // The Power Policy Manager may have changed // the scheme during validation. MapHiberTimer(g_pslCurSel->ppp, FALSE); SetControls(hWnd, g_uiNumPwrSchemeCntrls, g_pcPowerScheme); } break; } break; case WM_COMMAND: switch (LOWORD(wParam)) { case IDC_SCHEMECOMBO: if (HIWORD(wParam) == CBN_SELCHANGE) { if (g_pslCurSel = GetCurSchemeFromCombo(hWnd)) { HandleCurSchemeChanged(hWnd); MarkSheetDirty(hWnd, &bDirty); } } break; case IDC_STANDBYACCOMBO: case IDC_STANDBYDCCOMBO: HandleIdleTimeOutChanged(hWnd, uMsg, wParam, &bDirty); break; case IDC_MONITORACCOMBO: case IDC_MONITORDCCOMBO: case IDC_DISKACCOMBO: case IDC_DISKDCCOMBO: case IDC_HIBERACCOMBO: case IDC_HIBERDCCOMBO: if (HIWORD(wParam) == CBN_SELCHANGE) { MarkSheetDirty(hWnd, &bDirty); } break; case IDC_SAVEAS: if (DoSaveScheme(hWnd)) { HandleCurSchemeChanged(hWnd); MarkSheetDirty(hWnd, &bDirty); } break; case IDC_DELETE: if (DoDeleteScheme(hWnd, g_pslCurSel->lpszName)) { HandleCurSchemeChanged(hWnd); } break; default: return FALSE; } break; case PCWM_NOTIFYPOWER: // Notification from systray, user has changed a PM UI setting. PowerSchemeDlgInit(hWnd, &psdi); break; case WM_HELP: // F1 WinHelp(((LPHELPINFO)lParam)->hItemHandle, PWRMANHLP, HELP_WM_HELP, (ULONG_PTR)(LPTSTR)g_PowerSchemeHelpIDs); return TRUE; case WM_CONTEXTMENU: // right mouse click WinHelp((HWND)wParam, PWRMANHLP, HELP_CONTEXTMENU, (ULONG_PTR)(LPTSTR)g_PowerSchemeHelpIDs); return TRUE; } return FALSE; } /******************************************************************************* * * P R I V A T E F U N C T I O N S * *******************************************************************************/ /******************************************************************************* * * HandleIdleTimeOutChanged * * DESCRIPTION: * Range limit the hibernate timeout combo boxes based on the value of the * idle timeouts. * * PARAMETERS: * *******************************************************************************/ VOID HandleIdleTimeOutChanged(HWND hWnd, UINT uMsg, WPARAM wParam, BOOL *pbDirty) { UINT uiIdleTo, uiLimitedTo; if (HIWORD(wParam) == CBN_SELCHANGE) { MarkSheetDirty(hWnd, pbDirty); if (LOWORD(wParam) == IDC_STANDBYACCOMBO) { GetControls(hWnd, 1, &g_pcPowerScheme[ID_STANDBYACCOMBO]); GetControls(hWnd, 1, &g_pcPowerScheme[ID_HIBERACCOMBO]); uiIdleTo = g_uiIdleTimeoutAc; uiLimitedTo = RangeLimitHiberTimeOuts(uiIdleTo, g_uiHiberToAcIDs); if (g_uiHiberTimeoutAc && (uiIdleTo >= g_uiHiberTimeoutAc)) { g_uiHiberTimeoutAc = uiLimitedTo; } SetControls(hWnd, 1, &g_pcPowerScheme[ID_HIBERACCOMBO]); } else { GetControls(hWnd, 1, &g_pcPowerScheme[ID_STANDBYDCCOMBO]); GetControls(hWnd, 1, &g_pcPowerScheme[ID_HIBERDCCOMBO]); uiIdleTo = g_uiIdleTimeoutDc; uiLimitedTo = RangeLimitHiberTimeOuts(uiIdleTo, g_uiHiberToDcIDs); if (g_uiHiberTimeoutDc && (uiIdleTo >= g_uiHiberTimeoutDc)) { g_uiHiberTimeoutDc = uiLimitedTo; } SetControls(hWnd, 1, &g_pcPowerScheme[ID_HIBERDCCOMBO]); } } } /******************************************************************************* * * RangeLimitHiberTimeOuts * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/ UINT RangeLimitHiberTimeOuts(UINT uiIdleTimeout, UINT *uiHiberToIDs) { UINT i, uiNewMin; // Initialize the hiber timout ID's to full range. memcpy(uiHiberToIDs, g_uiHiberToIDs, sizeof(g_uiHiberToIDs)); if (uiIdleTimeout) { i = 0; while (uiHiberToIDs[i++]) { if (uiHiberToIDs[i] >= uiIdleTimeout) { i += 2; uiNewMin = uiHiberToIDs[i]; RangeLimitIDarray(uiHiberToIDs, uiNewMin, (UINT) -1); return uiNewMin; } i++; } MYDBGPRINT(( "RangeLimitHiberTimeOuts: couldn't find value larger than: %d", uiIdleTimeout)); } return (UINT) -1; } /******************************************************************************* * * MapHiberTimer * * DESCRIPTION: * Displayed hibernate timeout may never be less than the idle timeout. This * function handles the mapping. The following table (per KenR) specifies the * Idle action to be set by the UI for different combinations of Idle and * Hibernate timeouts. It is understood that the Hibernate timeout UI only * appears when HiberFilePresent is TRUE. For case E, the HiberTimeout will be * set in the IdleTimeout member. For case F, the UI will adjust the * DozeS4Timeout member to be the displayed HiberTimeout plus the IdleTimeout. * * Case HiberFilePresent UiHiberTimeout UiIdleTimeout IdleAction DozeS4Timeout IdleTimeout * --------------------------------------------------------------------------------------------------------------- * A. FALSE N/A 0 (Never) PowerActionNone 0 0 * B. FALSE N/A !0 PowerActionSleep 0 UiIdleTimeout * C. TRUE 0 (Never) 0 (Never) PowerActionNone 0 0 * D. TRUE 0 (Never) !0 PowerActionSleep 0 UiIdleTimeout * E. TRUE !0 0 (Never) PowerActionHibernate 0 UiHiberTimeout * F. TRUE !0 !0 PowerActionSleep UiHiber-UiIdle UiIdleTimeout * * PARAMETERS: * *******************************************************************************/ BOOLEAN MapHiberTimer(PPOWER_POLICY ppp, BOOLEAN Get) { if (Get) { // Get values from the UI. AC. ppp->mach.DozeS4TimeoutAc = 0; ppp->user.IdleTimeoutAc = g_uiIdleTimeoutAc; if (g_uiHiberTimeoutAc) { if (g_uiIdleTimeoutAc) { ppp->mach.DozeS4TimeoutAc = g_uiHiberTimeoutAc - g_uiIdleTimeoutAc; } else { ppp->user.IdleTimeoutAc = g_uiHiberTimeoutAc; } } // DC. ppp->mach.DozeS4TimeoutDc = 0; ppp->user.IdleTimeoutDc = g_uiIdleTimeoutDc; if (g_uiHiberTimeoutDc) { if (g_uiIdleTimeoutDc) { ppp->mach.DozeS4TimeoutDc = g_uiHiberTimeoutDc - g_uiIdleTimeoutDc; } else { ppp->user.IdleTimeoutDc = g_uiHiberTimeoutDc; } } // Set the correct idle action. AC. ppp->user.IdleAc.Action = PowerActionNone; if (g_uiIdleTimeoutAc) { ppp->user.IdleAc.Action = PowerActionSleep; } else { if (g_SysPwrCapabilities.HiberFilePresent) { if (g_uiHiberTimeoutAc) { ppp->user.IdleAc.Action = PowerActionHibernate; } } } // DC. ppp->user.IdleDc.Action = PowerActionNone; if (g_uiIdleTimeoutDc) { ppp->user.IdleDc.Action = PowerActionSleep; } else { if (g_SysPwrCapabilities.HiberFilePresent) { if (g_uiHiberTimeoutDc) { ppp->user.IdleDc.Action = PowerActionHibernate; } } } } else { // Set values to the UI. AC. if (ppp->user.IdleAc.Action == PowerActionHibernate) { g_uiHiberTimeoutAc = ppp->user.IdleTimeoutAc; g_uiIdleTimeoutAc = 0; } else { g_uiIdleTimeoutAc = ppp->user.IdleTimeoutAc; if (ppp->mach.DozeS4TimeoutAc && g_SysPwrCapabilities.HiberFilePresent) { g_uiHiberTimeoutAc = ppp->user.IdleTimeoutAc + ppp->mach.DozeS4TimeoutAc; } else { g_uiHiberTimeoutAc = 0; } } // DC. if (ppp->user.IdleDc.Action == PowerActionHibernate) { g_uiHiberTimeoutDc = ppp->user.IdleTimeoutDc; g_uiIdleTimeoutDc = 0; } else { g_uiIdleTimeoutDc = ppp->user.IdleTimeoutDc; if (ppp->mach.DozeS4TimeoutDc && g_SysPwrCapabilities.HiberFilePresent) { g_uiHiberTimeoutDc = ppp->user.IdleTimeoutDc + ppp->mach.DozeS4TimeoutDc; } else { g_uiHiberTimeoutDc = 0; } } // Range limit the hibernate timeout combo boxes based // on the value of the idle timeouts. RangeLimitHiberTimeOuts(g_uiIdleTimeoutAc, g_uiHiberToAcIDs); RangeLimitHiberTimeOuts(g_uiIdleTimeoutDc, g_uiHiberToDcIDs); } return TRUE; } /******************************************************************************* * * HandleCurSchemeChanged * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/ BOOLEAN HandleCurSchemeChanged(HWND hWnd) { LPTSTR pString; BOOL bEnable; // Update the group box text if enabled. if ((g_uiStandbyState != CONTROL_HIDE) || (g_uiMonitorState != CONTROL_HIDE) || (g_uiDiskState != CONTROL_HIDE) || (g_uiHiberState != CONTROL_HIDE)) { pString = LoadDynamicString(IDS_SETTINGSFORMAT, g_pslCurSel->lpszName); DisplayFreeStr(hWnd, IDC_SETTINGSFOR, pString, FREE_STR); } else { ShowWindow(GetDlgItem(hWnd, IDC_SETTINGSFOR), SW_HIDE); } // Update the power schemes combobox list. RefreshSchemes(hWnd, g_pslCurSel); // Setup the data pointers in the g_pcPowerScheme array. g_pcPowerScheme[ID_MONITORACCOMBO].lpdwParam = &(g_pslCurSel->ppp->user.VideoTimeoutAc); g_pcPowerScheme[ID_MONITORDCCOMBO].lpdwParam = &(g_pslCurSel->ppp->user.VideoTimeoutDc); g_pcPowerScheme[ID_DISKACCOMBO].lpdwParam = &(g_pslCurSel->ppp->user.SpindownTimeoutAc); g_pcPowerScheme[ID_DISKDCCOMBO].lpdwParam = &(g_pslCurSel->ppp->user.SpindownTimeoutDc); // Update the rest of the controls. MapHiberTimer(g_pslCurSel->ppp, FALSE); SetControls(hWnd, g_uiNumPwrSchemeCntrls, g_pcPowerScheme); // Set the delete push button state. if (g_uiSchemeCount < 2) { bEnable = FALSE; } else { bEnable = TRUE; } EnableWindow(GetDlgItem(hWnd, IDC_DELETE), bEnable); return TRUE; } /******************************************************************************* * * GetCurSchemeFromCombo * * DESCRIPTION: * Get the current selection from the power schemes combobox list. * * PARAMETERS: * *******************************************************************************/ PSCHEME_LIST GetCurSchemeFromCombo(HWND hWnd) { UINT uiCBRet; PSCHEME_LIST psl; uiCBRet = (UINT) SendDlgItemMessage(hWnd, IDC_SCHEMECOMBO, CB_GETCURSEL, 0, 0); if (uiCBRet != CB_ERR) { psl = (PSCHEME_LIST) SendDlgItemMessage(hWnd, IDC_SCHEMECOMBO, CB_GETITEMDATA, uiCBRet, 0); if (psl != (PSCHEME_LIST) CB_ERR) { return FindScheme(psl->lpszName, TRUE); } } MYDBGPRINT(( "GetCurSchemeFromCombo, CB_GETITEMDATA or CB_GETCURSEL failed")); return FALSE; } /******************************************************************************* * * ClearSchemeList * * DESCRIPTION: * Clear the scheme list if it's not already empty. Return TRUE if there's * a change to the contents of power scheme list. * * PARAMETERS: * *******************************************************************************/ BOOLEAN ClearSchemeList(VOID) { PSCHEME_LIST psl, pslNext; if (IsListEmpty(&g_leSchemeList)) { return FALSE; } for (psl = (PSCHEME_LIST)g_leSchemeList.Flink; psl != (PSCHEME_LIST)&g_leSchemeList; psl = pslNext) { pslNext = (PSCHEME_LIST) psl->leSchemeList.Flink; RemoveScheme(psl, NULL); } g_pslCurActive = NULL; g_pslCurSel = NULL; g_uiSchemeCount = 0; return TRUE; } /******************************************************************************* * * RemoveScheme * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/ BOOLEAN RemoveScheme(PSCHEME_LIST psl, LPTSTR lpszName) { if (lpszName) { psl = FindScheme(lpszName, TRUE); } if (psl == &g_sl) { MYDBGPRINT(( "RemoveScheme, Attempted to delete head!")); return FALSE; } if (psl) { LocalFree(psl->lpszName); LocalFree(psl->lpszDesc); RemoveEntryList(&psl->leSchemeList); LocalFree(psl); g_uiSchemeCount--; return TRUE; } return FALSE; } /******************************************************************************* * * FindScheme * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/ PSCHEME_LIST FindScheme(LPTSTR lpszName, BOOLEAN bShouldExist) { PSCHEME_LIST psl, pslNext; if (!lpszName) { MYDBGPRINT(( "FindScheme, invalid parameters")); return NULL; } // Search by name. for (psl = (PSCHEME_LIST)g_leSchemeList.Flink; psl != (PSCHEME_LIST)&g_leSchemeList; psl = pslNext) { pslNext = (PSCHEME_LIST) psl->leSchemeList.Flink; if (!lstrcmpi(lpszName, psl->lpszName)) { return psl; } } if (bShouldExist) { MYDBGPRINT(( "FindScheme, couldn't find: %s", lpszName)); } return NULL; } /******************************************************************************* * * AddScheme * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/ PSCHEME_LIST AddScheme( UINT uiID, LPTSTR lpszName, UINT uiNameSize, LPTSTR lpszDesc, UINT uiDescSize, PPOWER_POLICY ppp ) { PSCHEME_LIST psl; if (!lpszName || !lpszDesc) { MYDBGPRINT(( "AddScheme, invalid parameters")); return NULL; } // If a scheme of this name already exists just return a pointer to it. psl = FindScheme(lpszName, FALSE); if ( NULL == psl ) { // Allocate and initalize a Scheme element for the scheme list. psl = LocalAlloc(0, sizeof(SCHEME_LIST) ); if ( NULL == psl ) return psl; // out of memory } else { // remove the entry from the list and free allocated memory RemoveEntryList(&psl->leSchemeList); g_uiSchemeCount --; LocalFree( psl->lpszName ); LocalFree( psl->lpszDesc ); LocalFree( psl->ppp ); } // Update the Scheme psl->uiID = uiID; psl->lpszName = LocalAlloc(0, uiNameSize); psl->lpszDesc = LocalAlloc(0, uiDescSize); psl->ppp = LocalAlloc(0, sizeof(*psl->ppp)); if (psl->lpszName && psl->lpszDesc && psl->ppp) { StringCbCopy(psl->lpszName, uiNameSize, lpszName); StringCbCopy(psl->lpszDesc, uiDescSize, lpszDesc); memcpy(psl->ppp, ppp, sizeof(*psl->ppp)); InsertTailList(&g_leSchemeList, &psl->leSchemeList); g_uiSchemeCount++; return psl; } LocalFree(psl->lpszName); LocalFree(psl->lpszDesc); LocalFree(psl->ppp); LocalFree(psl); psl = NULL; return psl; } /******************************************************************************* * * PowerSchemeEnumProc * Builds the policies list. * * DESCRIPTION: * * PARAMETERS: * lParam - Is the ID of the currently active power scheme. * *******************************************************************************/ BOOLEAN CALLBACK PowerSchemeEnumProc( UINT uiID, DWORD dwNameSize, LPTSTR lpszName, DWORD dwDescSize, LPTSTR lpszDesc, PPOWER_POLICY ppp, LPARAM lParam ) { PSCHEME_LIST psl; // Validate the new scheme. if (ValidateUISchemeFields(ppp)) { // Allocate and initalize a policies element. if ((psl = AddScheme(uiID, lpszName, dwNameSize, lpszDesc, dwDescSize, ppp)) != NULL) { // Save a valid entry for error recovery. g_pslValid = psl; // Setup currently active policies pointer. if ((UINT)lParam == uiID) { g_pslCurActive = psl; } return TRUE; } } return FALSE; } /******************************************************************************* * * PowerSchemeDlgInit * * DESCRIPTION: * Initialize the power scheme dialog. * * PARAMETERS: * *******************************************************************************/ BOOLEAN PowerSchemeDlgInit( HWND hWnd, PPOWER_SCHEME_DLG_INFO ppsdi ) { UINT uiCurrentSchemeID; UINT i; // On WINNT, only power users may add new power schemes. if (CanUserWritePwrScheme()) { ShowWindow(GetDlgItem(hWnd, IDC_SAVEAS), SW_SHOW); ShowWindow(GetDlgItem(hWnd, IDC_DELETE), SW_SHOW); } else { ShowWindow(GetDlgItem(hWnd, IDC_SAVEAS), SW_HIDE); ShowWindow(GetDlgItem(hWnd, IDC_DELETE), SW_HIDE); } ppsdi->hwndSchemeList = GetDlgItem(hWnd, IDC_SCHEMECOMBO); ClearSchemeList(); // Get the currently active power scheme. if (GetActivePwrScheme(&uiCurrentSchemeID)) { // Get the Policies list from PowrProf. for (i = 0; i < 2; i++) { if (EnumPwrSchemes(PowerSchemeEnumProc, (LPARAM)uiCurrentSchemeID) && g_pslCurActive) { g_pslCurSel = g_pslCurActive; // Setup UI show/hide state variables. g_uiWhenComputerIsState = CONTROL_HIDE; if (g_SysPwrCapabilities.SystemS1 || g_SysPwrCapabilities.SystemS2 || g_SysPwrCapabilities.SystemS3) { g_uiStandbyState = CONTROL_ENABLE; g_uiWhenComputerIsState = CONTROL_ENABLE; } else { g_uiStandbyState = CONTROL_HIDE; } if (g_bVideoLowPowerSupported) { g_uiMonitorState = CONTROL_ENABLE; g_uiWhenComputerIsState = CONTROL_ENABLE; } else { g_uiMonitorState = CONTROL_HIDE; } if (g_SysPwrCapabilities.DiskSpinDown) { g_uiDiskState = CONTROL_ENABLE; RangeLimitIDarray(g_uiSpinDownIDs, HIWORD(g_uiSpindownMaxMin)*60, LOWORD(g_uiSpindownMaxMin)*60); } else { g_uiDiskState = CONTROL_HIDE; } if (g_bRunningUnderNT && g_SysPwrCapabilities.SystemS4 && g_SysPwrCapabilities.SystemS5 && g_SysPwrCapabilities.HiberFilePresent) { g_uiHiberState = CONTROL_ENABLE; } else { g_uiHiberState = CONTROL_HIDE; } // Update the UI. HandleCurSchemeChanged(hWnd); return TRUE; } else { MYDBGPRINT(( "PowerSchemeDlgInit, failure enumerating schemes. g_pslCurActive: %X", g_pslCurActive)); if (g_pslValid) { if (SetActivePwrScheme(g_pslValid->uiID, NULL, g_pslValid->ppp)) { uiCurrentSchemeID = g_pslValid->uiID; ClearSchemeList(); } else { MYDBGPRINT(( "PowerSchemeDlgInit, unable to set valid scheme")); } } else { MYDBGPRINT(( "PowerSchemeDlgInit, no valid schemes")); break; } } } } DisableControls(hWnd, g_uiNumPwrSchemeCntrls, g_pcPowerScheme); return FALSE; } /******************************************************************************* * * RefreshSchemes * * DESCRIPTION: * Update the power schemes combobox list. * * PARAMETERS: * hWnd - Power schemes dialog hWnd. * pslSel - Power scheme to leave selected on exit. * *******************************************************************************/ VOID RefreshSchemes( HWND hWnd, PSCHEME_LIST pslSel ) { PSCHEME_LIST psl, pslNext; UINT uiIndex; SendDlgItemMessage(hWnd, IDC_SCHEMECOMBO, CB_RESETCONTENT, FALSE, 0L); for (psl = (PSCHEME_LIST)g_leSchemeList.Flink; psl != (PSCHEME_LIST)&g_leSchemeList; psl = pslNext) { pslNext = (PSCHEME_LIST) psl->leSchemeList.Flink; // Add the schemes to the combo list box. uiIndex = (UINT) SendDlgItemMessage(hWnd, IDC_SCHEMECOMBO, CB_ADDSTRING, 0, (LPARAM) psl->lpszName); if (uiIndex != CB_ERR) { SendDlgItemMessage(hWnd, IDC_SCHEMECOMBO, CB_SETITEMDATA, uiIndex, (LPARAM) psl); } else { MYDBGPRINT(( "RefreshSchemes, CB_ADDSTRING failed: %s", psl->lpszName)); } } // Select the passed entry. if (pslSel) { uiIndex = (UINT) SendDlgItemMessage(hWnd, IDC_SCHEMECOMBO, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)pslSel->lpszName); if (uiIndex != CB_ERR) { uiIndex = (UINT) SendDlgItemMessage(hWnd, IDC_SCHEMECOMBO, CB_SETCURSEL, (WPARAM)uiIndex, 0); if (uiIndex == CB_ERR) { MYDBGPRINT(( "RefreshSchemes, CB_SETCURSEL failed: %s, index: %d", psl->lpszName, uiIndex)); } } else { MYDBGPRINT(( "RefreshSchemes, CB_FINDSTRINGEXACT failed: %s", psl->lpszName)); } } } /******************************************************************************* * * StripBlanks * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/ UINT StripBlanks(LPTSTR lpszString, DWORD cchIn) { LPTSTR lpszPosn, lpszSrc; /* strip leading blanks */ lpszPosn = lpszString; while(*lpszPosn == TEXT(' ')) { lpszPosn++; } if (lpszPosn != lpszString) { StringCchCopy(lpszString, cchIn, lpszPosn); } /* strip trailing blanks */ if ((lpszPosn=lpszString+lstrlen(lpszString)) != lpszString) { lpszPosn = CharPrev(lpszString, lpszPosn); while(*lpszPosn == TEXT(' ')) { lpszPosn = CharPrev(lpszString, lpszPosn); } lpszPosn = CharNext(lpszPosn); *lpszPosn = TEXT('\0'); } return lstrlen(lpszString); } /******************************************************************************* * * MsgBoxId * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/ LONG MsgBoxId( HWND hWnd, UINT uiCaption, UINT uiFormat, LPTSTR lpszParam, UINT uiFlags ) { LPTSTR lpszCaption; LPTSTR lpszText; LONG lRet = 0; lpszCaption = LoadDynamicString(uiCaption); if (lpszCaption) { lpszText = LoadDynamicString(uiFormat, lpszParam); if (lpszText) { lRet = MessageBox(hWnd, lpszText, lpszCaption, uiFlags); LocalFree(lpszText); } LocalFree(lpszCaption); } return lRet; } /******************************************************************************* * * DoDeleteScheme * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/ BOOLEAN DoDeleteScheme(HWND hWnd, LPTSTR lpszName) { LPTSTR lpszCaption; LPTSTR lpszText; PSCHEME_LIST psl, pslDelete; // Dont't allow delete unless we have at least two schemes. if ((g_uiSchemeCount < 2) || !(pslDelete = FindScheme(lpszName, TRUE))) { return FALSE; } // Get confirmation from the user. if (IDYES == MsgBoxId(hWnd, IDS_CONFIRMDELETECAPTION, IDS_CONFIRMDELETE, lpszName, MB_YESNO | MB_ICONQUESTION)) { // If we deleted the currently active scheme set the next scheme active. if (pslDelete == g_pslCurActive) { if ((psl = FindNextScheme(lpszName)) && (SetActivePwrSchemeReport(hWnd, psl->uiID, NULL, psl->ppp))) { g_pslCurActive = psl; } else { return FALSE; } } // Remove requested scheme. if (DeletePwrScheme(pslDelete->uiID)) { RemoveScheme(NULL, lpszName); g_pslCurSel = g_pslCurActive; return TRUE; } } return FALSE; } /******************************************************************************* * * FindNextScheme * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/ PSCHEME_LIST FindNextScheme(LPTSTR lpszName) { PSCHEME_LIST psl, pslFirst, pslNext; for (pslFirst = psl = (PSCHEME_LIST)g_leSchemeList.Flink; psl != (PSCHEME_LIST)&g_leSchemeList; psl = pslNext) { pslNext = (PSCHEME_LIST) psl->leSchemeList.Flink; if (!lstrcmpi(lpszName, psl->lpszName)) { if (pslNext != (PSCHEME_LIST)&g_leSchemeList) { return pslNext; } else { return pslFirst; } } } MYDBGPRINT(( "FindNextScheme, unable to find: %s", lpszName)); return NULL; } /******************************************************************************* * * DoSaveScheme * * DESCRIPTION: * * PARAMETERS: * *******************************************************************************/ BOOLEAN DoSaveScheme(HWND hWnd) { POWER_POLICY ppSave; BOOLEAN bSavedCurrent; PSCHEME_LIST pslTemplateScheme = g_pslCurSel; // Make a copy of the template scheme to restore after the save. memcpy(&ppSave, pslTemplateScheme->ppp, sizeof(ppSave)); // Get any changes the user might have made for the new scheme. GetControls(hWnd, g_uiNumPwrSchemeCntrls, g_pcPowerScheme); MapHiberTimer(g_pslCurSel->ppp, TRUE); if (IDOK != DialogBoxParam(g_hInstance, MAKEINTRESOURCE(IDD_SAVE), hWnd, SaveAsDlgProc, (LPARAM)&bSavedCurrent)) { return FALSE; } // Restore the template scheme if we didn't save the current scheme. if (!bSavedCurrent) { memcpy(pslTemplateScheme->ppp, &ppSave, sizeof(*pslTemplateScheme->ppp)); return TRUE; } return TRUE; }