Source code of Windows XP (NT5)
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.

1012 lines
35 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1996
  4. *
  5. * TITLE: ALARM.C
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 17 Oct, 1996
  12. *
  13. * DESCRIPTION:
  14. * Alarm dialog support.
  15. *
  16. *******************************************************************************/
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #include <mmsystem.h>
  22. #include <commctrl.h>
  23. #include <shlobj.h>
  24. #include <shellapi.h>
  25. #include <shlobjp.h>
  26. #include <help.h>
  27. #include <powercfp.h>
  28. #include <mstask.h>
  29. #include <shfusion.h>
  30. #include <ntpoapi.h>
  31. #include "powercfg.h"
  32. #include "pwrresid.h"
  33. #include "PwrMn_cs.h"
  34. // Private functions implemented in ALARM.C
  35. void EditWorkItem(HWND, LPTSTR);
  36. BOOLEAN SetSliderStatusText(HWND, UINT, UINT);
  37. BOOLEAN SetAlarmStatusText(HWND);
  38. #ifdef WINNT
  39. void HideShowRunProgram(HWND hWnd);
  40. #endif
  41. // Alarm dialog property sheet init data structure:
  42. typedef struct _ALARM_POL_DLG_DATA
  43. {
  44. LPTSTR lpszTitleExt;
  45. WPARAM wParam;
  46. } ALARM_POL_DLG_DATA, *PALARM_POL_DLG_DATA;
  47. /*******************************************************************************
  48. *
  49. * G L O B A L D A T A
  50. *
  51. *******************************************************************************/
  52. extern HINSTANCE g_hInstance; // Global instance handle of this DLL.
  53. // This structure is filled in by the Power Policy Manager at CPL_INIT time.
  54. extern SYSTEM_POWER_CAPABILITIES g_SysPwrCapabilities;
  55. extern DWORD g_dwNumSleepStates;
  56. extern DWORD g_dwSleepStatesMaxMin;
  57. extern DWORD g_dwBattryLevelMaxMin;
  58. SYSTEM_POWER_STATE g_spsMaxSleepState = PowerSystemHibernate;
  59. extern UINT g_uiDisableWakesFlag; // Flag mask value.
  60. extern UINT g_uiOverrideAppsFlag; // Flag mask value.
  61. // A systary change requires PowerSchemeDlgProc re-init.
  62. extern BOOL g_bSystrayChange;
  63. // Machine is currently capable of hibernate, managed by code in hibernat.c.
  64. extern UINT g_uiPwrActIDs[];
  65. // Persistant storage of this data is managed by POWRPROF.DLL API's.
  66. extern GLOBAL_POWER_POLICY g_gpp;
  67. // Indices into g_uiPwrActIDs
  68. #define ID_STANDBY 0
  69. #define ID_SHUTDOWN 1
  70. // Local visable/enabled control state variables.
  71. UINT g_uiSoundState;
  72. UINT g_uiTextState;
  73. UINT g_uiProgState;
  74. UINT g_uiLoChangeEnable;
  75. UINT g_uiLoChangeState;
  76. UINT g_uiAlwaysHide = CONTROL_HIDE;
  77. UINT g_uiNotifySoundFlag = POWER_LEVEL_USER_NOTIFY_SOUND;
  78. UINT g_uiNotifyTextFlag = POWER_LEVEL_USER_NOTIFY_TEXT;
  79. #ifdef WINNT
  80. UINT g_uiNotifyProgFlag = POWER_LEVEL_USER_NOTIFY_EXEC;
  81. CONST LPTSTR g_szAlarmTaskName [NUM_DISCHARGE_POLICIES] = {
  82. TEXT("Critical Battery Alarm Program"),
  83. TEXT("Low Battery Alarm Program"),
  84. NULL,
  85. NULL
  86. };
  87. #endif
  88. // Advanced alarm policies dialog controls descriptions:
  89. #ifdef WINNT
  90. #define NUM_ALARM_ACTIONS_CONTROLS 7
  91. #else
  92. #define NUM_ALARM_ACTIONS_CONTROLS 5
  93. #endif
  94. // Handy indicies into our AlarmActions control arrays
  95. #define ID_NOTIFYWITHSOUND 0
  96. #define ID_NOTIFYWITHTEXT 1
  97. #define ID_ENABLELOWSTATE 2
  98. #define ID_ALARMACTIONPOLICY 3
  99. #define ID_ALARMIGNORENONRESP 4
  100. #ifdef WINNT
  101. #define ID_RUNPROGCHECKBOX 5
  102. #define ID_RUNPROGWORKITEM 6
  103. #endif
  104. POWER_CONTROLS g_pcAlarmActions[NUM_ALARM_ACTIONS_CONTROLS] =
  105. {// Control ID Control Type Data Address Data Size Parameter Pointer EnableVisible State Pointer
  106. IDC_NOTIFYWITHSOUND, CHECK_BOX_ENABLE, NULL, sizeof(DWORD), &g_uiNotifySoundFlag, &g_uiSoundState,
  107. IDC_NOTIFYWITHTEXT, CHECK_BOX, NULL, sizeof(DWORD), &g_uiNotifyTextFlag, &g_uiTextState,
  108. IDC_ENABLELOWSTATE, CHECK_BOX_ENABLE, &g_uiLoChangeEnable,sizeof(DWORD), NULL, &g_uiLoChangeState,
  109. IDC_ALARMACTIONPOLICY, COMBO_BOX, NULL, sizeof(DWORD), NULL, &g_uiLoChangeState,
  110. IDC_ALARMIGNORENONRESP, CHECK_BOX, NULL, sizeof(DWORD), &g_uiOverrideAppsFlag, &g_uiLoChangeState,
  111. #ifdef WINNT
  112. IDC_RUNPROGCHECKBOX, CHECK_BOX_ENABLE, NULL, sizeof(DWORD), &g_uiNotifyProgFlag, &g_uiProgState,
  113. IDC_RUNPROGWORKITEM, PUSHBUTTON, NULL, 0, NULL, &g_uiProgState,
  114. #endif
  115. };
  116. // Alarm policies dialog controls descriptions:
  117. #define NUM_ALARM_CONTROLS 6
  118. // Local visable/enabled control state variables.
  119. UINT g_uiLoState;
  120. UINT g_uiCritState;
  121. UINT g_uiBatteryLevelScale;
  122. POWER_CONTROLS g_pcAlarm[NUM_ALARM_CONTROLS] =
  123. {// Control ID Control Type Data Address Data Size Parameter Pointer Enable/Visible State Pointer
  124. IDC_LOBATALARMENABLE, CHECK_BOX_ENABLE, &(g_gpp.user.DischargePolicy[DISCHARGE_POLICY_LOW].Enable), sizeof(ULONG), NULL, &g_uiLoState,
  125. IDC_LOWACTION, PUSHBUTTON, NULL, 0, NULL, &g_uiLoState,
  126. IDC_LOALARMSLIDER, SLIDER, &(g_gpp.user.DischargePolicy[DISCHARGE_POLICY_LOW].BatteryLevel), sizeof(ULONG), &g_dwBattryLevelMaxMin, &g_uiLoState,
  127. IDC_CRITBATALARMENABLE, CHECK_BOX_ENABLE, &(g_gpp.user.DischargePolicy[DISCHARGE_POLICY_CRITICAL].Enable), sizeof(ULONG), NULL, &g_uiCritState,
  128. IDC_CRITACTION, PUSHBUTTON, NULL, 0, NULL, &g_uiCritState,
  129. IDC_CRITALARMSLIDER, SLIDER, &(g_gpp.user.DischargePolicy[DISCHARGE_POLICY_CRITICAL].BatteryLevel), sizeof(ULONG), &g_dwBattryLevelMaxMin, &g_uiCritState,
  130. };
  131. // "Alarms" Dialog Box (IDD_ALARMPOLICY == 103) help array:
  132. const DWORD g_AlarmHelpIDs[]=
  133. {
  134. IDC_POWERCFGGROUPBOX3, IDH_103_1110, // Alarms: "Low battery alarm groupbox" (Button)
  135. IDC_LOBATALARMENABLE, IDH_103_1106, // Alarms: "Set off &low battery alarm when power level reaches:" (Button)
  136. IDC_LOWALARMLEVEL, IDH_103_1104, // Alarms: "Low alarm level" (Static)
  137. IDC_LOALARMSLIDER, IDH_103_1102, // Alarms: "Low alarm slider" (msctls_trackbar32)
  138. IDC_LOWACTION, IDH_103_1101, // Alarms: "Alar&m Action..." (Button)
  139. IDC_LOALARMNOTIFICATION, IDH_103_1108, // Alarms: "Low alarm status text" (Static)
  140. IDC_LOALARMPOWERMODE, IDH_103_1108, // Alarms: "Low alarm status text" (Static)
  141. #ifdef WINNT
  142. IDC_LOALARMPROGRAM, IDH_103_1108, // Alarms: "Low alarm status text" (Static)
  143. #endif
  144. IDC_POWERCFGGROUPBOX4, IDH_103_1111, // Alarms: "Critical battery alarm groupbox" (Button)
  145. IDC_CRITBATALARMENABLE, IDH_103_1107, // Alarms: "Set off &critical battery alarm when power level reaches:" (Button)
  146. IDC_CRITALARMLEVEL, IDH_103_1105, // Alarms: "Critical alarm level" (Static)
  147. IDC_CRITALARMSLIDER, IDH_103_1103, // Alarms: "Critical alarm slider" (msctls_trackbar32)
  148. IDC_CRITACTION, IDH_103_1100, // Alarms: "Ala&rm Action..." (Button)
  149. IDC_CRITALARMNOTIFICATION,IDH_103_1109, // Alarms: "Critical alarm status text" (Static)
  150. IDC_CRITALARMPOWERMODE, IDH_103_1109, // Alarms: "Critical alarm status text" (Static)
  151. #ifdef WINNT
  152. IDC_CRITALARMPROGRAM, IDH_103_1109, // Alarms: "Critical alarm status text" (Static)
  153. #endif
  154. IDC_NO_HELP_1, NO_HELP,
  155. IDC_NO_HELP_2, NO_HELP,
  156. IDC_NO_HELP_3, NO_HELP,
  157. IDC_NO_HELP_4, NO_HELP,
  158. 0, 0
  159. };
  160. // "Alarm Actions" Dialog Box (IDD_ALARMACTIONS == 106) help array:
  161. const DWORD g_AlarmActHelpIDs[]=
  162. {
  163. IDC_POWERCFGGROUPBOX5, IDH_106_1608, // Alarm Actions: "Notification groupbox" (Button)
  164. IDC_NOTIFYWITHSOUND, IDH_106_1603, // Alarm Actions: "&Sound alarm" (Button)
  165. IDC_NOTIFYWITHTEXT, IDH_106_1605, // Alarm Actions: "&Display message" (Button)
  166. IDC_POWERCFGGROUPBOX6, IDH_106_1609, // Alarm Actions: "Power level groupbox" (Button)
  167. IDC_POWERCFGGROUPBOX7, IDH_106_1609, // Alarm Actions: "Run program groupbox"
  168. IDC_ENABLELOWSTATE, IDH_106_1600, // Alarm Actions: "When the &alarm goes off, the computer will:" (Button)
  169. IDC_ALARMACTIONPOLICY, IDH_106_1601, // Alarm Actions: "Alarm action dropdown" (ComboBox)
  170. IDC_ALARMIGNORENONRESP, IDH_106_1602, // Alarm Actions: "&Force standby or shutdown even if a program stops responding." (Button)
  171. #ifdef WINNT
  172. IDC_RUNPROGCHECKBOX, IDH_106_1620, // Alarm Actions: "Specifies that you want a program to run..."
  173. IDC_RUNPROGWORKITEM, IDH_106_1621, // Alarm Actions: "Displays a dialog box wher the work item is configured..."
  174. #endif
  175. 0, 0
  176. };
  177. /*******************************************************************************
  178. *
  179. * P U B L I C E N T R Y P O I N T S
  180. *
  181. *******************************************************************************/
  182. /*******************************************************************************
  183. *
  184. * AlarmActionsDlgProc
  185. *
  186. * DESCRIPTION:
  187. *
  188. * PARAMETERS:
  189. *
  190. *******************************************************************************/
  191. INT_PTR CALLBACK AlarmActionsDlgProc(
  192. HWND hWnd,
  193. UINT uMsg,
  194. WPARAM wParam,
  195. LPARAM lParam
  196. )
  197. {
  198. static GLOBAL_POWER_POLICY gpp;
  199. static PALARM_POL_DLG_DATA papdd;
  200. static UINT uiIndex;
  201. static UINT uiEventId;
  202. #ifdef WINNT
  203. static LPTSTR lpszTaskName;
  204. HWND hTaskWnd;
  205. #endif
  206. LPTSTR lpszCaption;
  207. UINT ii;
  208. switch (uMsg) {
  209. case WM_INITDIALOG:
  210. // Save a copy of the global policies to restore on cancel.
  211. memcpy(&gpp, &g_gpp, sizeof(gpp));
  212. // Set the pointers to the data of interest.
  213. papdd = (PALARM_POL_DLG_DATA) lParam;
  214. if (papdd->wParam == IDC_LOWACTION) {
  215. uiIndex = DISCHARGE_POLICY_LOW;
  216. uiEventId = IDS_LOWSOUNDEVENT;
  217. }
  218. else {
  219. uiIndex = DISCHARGE_POLICY_CRITICAL;
  220. uiEventId = IDS_CRITSOUNDEVENT;
  221. }
  222. #ifdef WINNT
  223. lpszTaskName = g_szAlarmTaskName [uiIndex];
  224. #endif
  225. // Set up the data pointers in g_pcAlarmActions.
  226. g_pcAlarmActions[ID_NOTIFYWITHSOUND].lpvData =
  227. &(g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.EventCode);
  228. g_pcAlarmActions[ID_NOTIFYWITHTEXT].lpvData =
  229. &(g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.EventCode);
  230. #ifdef WINNT
  231. g_pcAlarmActions[ID_RUNPROGCHECKBOX].lpvData =
  232. &(g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.EventCode);
  233. #endif
  234. g_pcAlarmActions[ID_ALARMACTIONPOLICY].lpdwParam =
  235. (LPDWORD)&(g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.Action);
  236. g_pcAlarmActions[ID_ALARMIGNORENONRESP].lpvData =
  237. &(g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.Flags);
  238. //
  239. // Set the appropriate choices for the Alarms
  240. //
  241. ii=0;
  242. if (g_SysPwrCapabilities.SystemS1 ||
  243. g_SysPwrCapabilities.SystemS2 || g_SysPwrCapabilities.SystemS3) {
  244. g_uiPwrActIDs[ii++] = IDS_STANDBY;
  245. g_uiPwrActIDs[ii++] = PowerActionSleep;
  246. }
  247. if (g_SysPwrCapabilities.HiberFilePresent) {
  248. g_uiPwrActIDs[ii++] = IDS_HIBERNATE;
  249. g_uiPwrActIDs[ii++] = PowerActionHibernate;
  250. }
  251. g_uiPwrActIDs[ii++] = IDS_POWEROFF;
  252. g_uiPwrActIDs[ii++] = PowerActionShutdownOff;
  253. g_uiPwrActIDs[ii++] = 0;
  254. g_uiPwrActIDs[ii++] = 0;
  255. g_pcAlarmActions[ID_ALARMACTIONPOLICY].lpvData = g_uiPwrActIDs;
  256. if (g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.Action == PowerActionNone) {
  257. g_uiLoChangeEnable = FALSE;
  258. }
  259. else {
  260. g_uiLoChangeEnable = TRUE;
  261. }
  262. MapPwrAct(&(g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.Action), FALSE);
  263. // Set the dialog caption.
  264. lpszCaption = LoadDynamicString(IDS_ALARMACTIONS,
  265. papdd->lpszTitleExt);
  266. if (lpszCaption) {
  267. SetWindowText(hWnd, lpszCaption);
  268. LocalFree(lpszCaption);
  269. }
  270. // Initialize the controls.
  271. SetControls(hWnd, NUM_ALARM_ACTIONS_CONTROLS, g_pcAlarmActions);
  272. #ifdef WINNT
  273. HideShowRunProgram(hWnd);
  274. #endif
  275. return (INT_PTR) TRUE;
  276. case WM_COMMAND:
  277. switch (wParam) {
  278. #ifdef WINNT
  279. case IDC_RUNPROGWORKITEM:
  280. hTaskWnd = FindWindow( NULL, lpszTaskName);
  281. if (hTaskWnd) {
  282. BringWindowToTop(hTaskWnd);
  283. } else {
  284. EditWorkItem(hWnd, lpszTaskName);
  285. }
  286. break;
  287. case IDC_RUNPROGCHECKBOX:
  288. hTaskWnd = FindWindow( NULL, lpszTaskName);
  289. if (hTaskWnd)
  290. {
  291. DestroyWindow(hTaskWnd);
  292. }
  293. // No break: Fall through to update grayed status of controls.
  294. #endif
  295. case IDC_ENABLELOWSTATE:
  296. GetControls(hWnd, NUM_ALARM_ACTIONS_CONTROLS, g_pcAlarmActions);
  297. SetControls(hWnd, NUM_ALARM_ACTIONS_CONTROLS, g_pcAlarmActions);
  298. #ifdef WINNT
  299. HideShowRunProgram(hWnd);
  300. #endif
  301. break;
  302. case IDOK:
  303. #ifdef WINNT
  304. hTaskWnd = FindWindow( NULL, lpszTaskName);
  305. if (hTaskWnd) {
  306. BringWindowToTop(hTaskWnd);
  307. } else {
  308. #endif
  309. GetControls(hWnd, NUM_ALARM_ACTIONS_CONTROLS, g_pcAlarmActions);
  310. if (!g_uiLoChangeEnable) {
  311. g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.Action =
  312. PowerActionNone;
  313. }
  314. g_gpp.user.DischargePolicy[uiIndex].MinSystemState = g_spsMaxSleepState;
  315. EndDialog(hWnd, wParam);
  316. #ifdef WINNT
  317. }
  318. #endif
  319. break;
  320. case IDCANCEL:
  321. #ifdef WINNT
  322. hTaskWnd = FindWindow( NULL, lpszTaskName);
  323. if (hTaskWnd)
  324. {
  325. DestroyWindow(hTaskWnd);
  326. }
  327. #endif
  328. // Restore the original global policies.
  329. memcpy(&g_gpp, &gpp, sizeof(gpp));
  330. EndDialog(hWnd, wParam);
  331. break;
  332. }
  333. break;
  334. case PCWM_NOTIFYPOWER:
  335. // Notification from systray, user has changed a PM UI setting.
  336. g_bSystrayChange = TRUE;
  337. break;
  338. case WM_HELP: // F1
  339. WinHelp(((LPHELPINFO)lParam)->hItemHandle, PWRMANHLP, HELP_WM_HELP, (ULONG_PTR)(LPTSTR)g_AlarmActHelpIDs);
  340. return TRUE;
  341. case WM_CONTEXTMENU: // right mouse click
  342. WinHelp((HWND)wParam, PWRMANHLP, HELP_CONTEXTMENU, (ULONG_PTR)(LPTSTR)g_AlarmActHelpIDs);
  343. return TRUE;
  344. }
  345. return FALSE;
  346. }
  347. /*******************************************************************************
  348. *
  349. * AlarmDlgProc
  350. *
  351. * DESCRIPTION:
  352. *
  353. * PARAMETERS:
  354. *
  355. *******************************************************************************/
  356. INT_PTR CALLBACK AlarmDlgProc(
  357. HWND hWnd,
  358. UINT uMsg,
  359. WPARAM wParam,
  360. LPARAM lParam
  361. )
  362. {
  363. NMHDR FAR *lpnm;
  364. ALARM_POL_DLG_DATA apdd;
  365. PUINT puiPos, puiPosVar, puiOtherPosVar, puiOtherPos, puiEnableState;
  366. UINT uiEnable, uiSliderStatusId, uiID;
  367. SYSTEM_BATTERY_STATE sbsBatteryState;
  368. BOOL bAdjust;
  369. static HWND hWndLoSlider, hWndCritSlider;
  370. static UINT uiDefaultAlert1, uiLoPos, uiCritPos, uiLoPosSave, uiCritPosSave;
  371. static BOOL bDirty = FALSE;
  372. switch (uMsg) {
  373. case WM_INITDIALOG:
  374. // If we can't read the global power policies hide
  375. // the controls on this page.
  376. if (!GetGlobalPwrPolicy(&g_gpp)) {
  377. HideControls(hWnd, NUM_ALARM_CONTROLS, g_pcAlarm);
  378. return TRUE;
  379. }
  380. g_uiTextState = g_uiSoundState = CONTROL_ENABLE;
  381. // Set the scale value.
  382. if (!HIWORD(g_dwBattryLevelMaxMin)) {
  383. g_uiBatteryLevelScale = 1;
  384. }
  385. else {
  386. g_uiBatteryLevelScale = 100 / HIWORD(g_dwBattryLevelMaxMin);
  387. }
  388. g_gpp.user.DischargePolicy[DISCHARGE_POLICY_LOW].BatteryLevel /=
  389. g_uiBatteryLevelScale;
  390. g_gpp.user.DischargePolicy[DISCHARGE_POLICY_CRITICAL].BatteryLevel /=
  391. g_uiBatteryLevelScale;
  392. // Read DefaultAlert1 from composite battery
  393. NtPowerInformation (SystemBatteryState, NULL, 0, &sbsBatteryState, sizeof(sbsBatteryState));
  394. if (sbsBatteryState.MaxCapacity == 0) {
  395. uiDefaultAlert1 = 0;
  396. } else {
  397. uiDefaultAlert1 = (100 * sbsBatteryState.DefaultAlert1)/sbsBatteryState.MaxCapacity;
  398. }
  399. // Cache the low alarm slider window handle.
  400. hWndLoSlider = GetDlgItem(hWnd, IDC_LOALARMSLIDER);
  401. hWndCritSlider = GetDlgItem(hWnd, IDC_CRITALARMSLIDER);
  402. // Initialize the local enable and position variables.
  403. uiLoPosSave = uiLoPos =
  404. g_gpp.user.DischargePolicy[DISCHARGE_POLICY_LOW].BatteryLevel;
  405. uiCritPosSave = uiCritPos =
  406. g_gpp.user.DischargePolicy[DISCHARGE_POLICY_CRITICAL].BatteryLevel;
  407. // Initialize the dialog controls
  408. SendDlgItemMessage(hWnd, IDC_LOALARMSLIDER, TBM_SETTICFREQ, 25, 0);
  409. SendDlgItemMessage(hWnd, IDC_CRITALARMSLIDER, TBM_SETTICFREQ, 25, 0);
  410. SetControls(hWnd, NUM_ALARM_CONTROLS, g_pcAlarm);
  411. SetSliderStatusText(hWnd, IDC_LOWALARMLEVEL, uiLoPos);
  412. SetSliderStatusText(hWnd, IDC_CRITALARMLEVEL, uiCritPos);
  413. SetAlarmStatusText(hWnd);
  414. // If we can't write the global policies disable the controls.
  415. if (!WriteGlobalPwrPolicyReport(hWnd, &g_gpp, FALSE)) {
  416. DisableControls(hWnd, NUM_ALARM_CONTROLS, g_pcAlarm);
  417. }
  418. return TRUE;
  419. case WM_NOTIFY:
  420. lpnm = (NMHDR FAR *)lParam;
  421. switch(lpnm->code)
  422. {
  423. case PSN_APPLY:
  424. if (bDirty)
  425. {
  426. GetControls(hWnd, NUM_ALARM_CONTROLS, g_pcAlarm);
  427. g_gpp.user.DischargePolicy[DISCHARGE_POLICY_LOW].BatteryLevel *=
  428. g_uiBatteryLevelScale;
  429. g_gpp.user.DischargePolicy[DISCHARGE_POLICY_CRITICAL].BatteryLevel *=
  430. g_uiBatteryLevelScale;
  431. WriteGlobalPwrPolicyReport(hWnd, &g_gpp, TRUE);
  432. GetActivePwrScheme(&uiID);
  433. SetActivePwrSchemeReport(hWnd, uiID, &g_gpp, NULL);
  434. bDirty = FALSE;
  435. }
  436. break;
  437. }
  438. break;
  439. case WM_COMMAND:
  440. switch (wParam) {
  441. case IDC_CRITACTION:
  442. apdd.lpszTitleExt = LoadDynamicString(IDS_CRITBAT);
  443. goto do_config_alarm_act;
  444. case IDC_LOWACTION:
  445. apdd.lpszTitleExt = LoadDynamicString(IDS_LOWBAT);
  446. do_config_alarm_act:
  447. apdd.wParam = wParam;
  448. if (IDOK == DialogBoxParam(g_hInstance,
  449. MAKEINTRESOURCE(IDD_ALARMACTIONS),
  450. hWnd,
  451. AlarmActionsDlgProc,
  452. (LPARAM)&apdd)) {
  453. // Enable the parent dialog Apply button on change.
  454. MarkSheetDirty(hWnd, &bDirty);
  455. }
  456. if (apdd.lpszTitleExt) {
  457. LocalFree(apdd.lpszTitleExt);
  458. }
  459. SetAlarmStatusText(hWnd);
  460. break;
  461. case IDC_LOBATALARMENABLE:
  462. puiPosVar = &(g_gpp.user.DischargePolicy[DISCHARGE_POLICY_LOW].BatteryLevel);
  463. puiOtherPosVar = &(g_gpp.user.DischargePolicy[DISCHARGE_POLICY_CRITICAL].BatteryLevel);
  464. uiSliderStatusId = IDC_LOWALARMLEVEL;
  465. goto do_sheet_dirty;
  466. case IDC_CRITBATALARMENABLE:
  467. puiPosVar = &(g_gpp.user.DischargePolicy[DISCHARGE_POLICY_CRITICAL].BatteryLevel);
  468. puiOtherPosVar = &(g_gpp.user.DischargePolicy[DISCHARGE_POLICY_LOW].BatteryLevel);
  469. uiSliderStatusId = IDC_CRITALARMLEVEL;
  470. do_sheet_dirty:
  471. GetControls(hWnd, NUM_ALARM_CONTROLS, g_pcAlarm);
  472. if ((uiEnable = IsDlgButtonChecked(hWnd, (int) wParam)) ==
  473. BST_CHECKED) {
  474. if (uiLoPos < uiCritPos) {
  475. uiLoPos = uiCritPos = *puiPosVar = *puiOtherPosVar;
  476. SetSliderStatusText(hWnd, uiSliderStatusId, uiCritPos);
  477. }
  478. }
  479. SetControls(hWnd, NUM_ALARM_CONTROLS, g_pcAlarm);
  480. SetAlarmStatusText(hWnd);
  481. MarkSheetDirty(hWnd, &bDirty);
  482. break;
  483. }
  484. break;
  485. case WM_HSCROLL:
  486. // Only handle slider controls.
  487. if (((HWND)lParam != hWndLoSlider) &&
  488. ((HWND)lParam != hWndCritSlider)) {
  489. break;
  490. }
  491. // Don't allow the low slider to be set lower than the critical
  492. // slider. Reset position on TB_ENDTRACK for this case.
  493. if (hWndLoSlider == (HWND)lParam) {
  494. puiPos = &uiLoPos;
  495. puiOtherPos = &uiCritPos;
  496. puiEnableState = &g_uiCritState;
  497. uiSliderStatusId = IDC_LOWALARMLEVEL;
  498. }
  499. else {
  500. puiPos = &uiCritPos;
  501. puiOtherPos = &uiLoPos;
  502. puiEnableState = &g_uiLoState;
  503. uiSliderStatusId = IDC_CRITALARMLEVEL;
  504. }
  505. switch (LOWORD(wParam)) {
  506. case TB_ENDTRACK:
  507. bAdjust = FALSE;
  508. if (*puiEnableState & CONTROL_ENABLE) {
  509. if (uiLoPos < uiCritPos) {
  510. *puiPos = *puiOtherPos;
  511. bAdjust = TRUE;
  512. }
  513. }
  514. if (*puiPos < uiDefaultAlert1) {
  515. *puiPos = uiDefaultAlert1;
  516. bAdjust = TRUE;
  517. }
  518. if (bAdjust) {
  519. SendMessage((HWND)lParam, TBM_SETPOS, TRUE,
  520. (LPARAM)*puiPos);
  521. }
  522. break;
  523. case TB_THUMBPOSITION:
  524. case TB_THUMBTRACK:
  525. // New position comes with these messages.
  526. *puiPos = HIWORD(wParam);
  527. break;
  528. default:
  529. // New position must be fetched for the rest.
  530. *puiPos = (UINT) SendMessage((HWND)lParam, TBM_GETPOS, 0, 0);
  531. }
  532. // Update the current slider position text.
  533. SetSliderStatusText(hWnd, uiSliderStatusId, *puiPos);
  534. // Enable the parent dialog Apply button on any change.
  535. MarkSheetDirty(hWnd, &bDirty);
  536. break;
  537. case WM_HELP: // F1
  538. WinHelp(((LPHELPINFO)lParam)->hItemHandle, PWRMANHLP, HELP_WM_HELP, (ULONG_PTR)(LPTSTR)g_AlarmHelpIDs);
  539. return TRUE;
  540. case WM_CONTEXTMENU: // right mouse click
  541. WinHelp((HWND)wParam, PWRMANHLP, HELP_CONTEXTMENU, (ULONG_PTR)(LPTSTR)g_AlarmHelpIDs);
  542. return TRUE;
  543. }
  544. return FALSE;
  545. }
  546. /*******************************************************************************
  547. *
  548. * P R I V A T E F U N C T I O N S
  549. *
  550. *******************************************************************************/
  551. /*******************************************************************************
  552. *
  553. * PathOnly
  554. *
  555. * DESCRIPTION:
  556. *
  557. * PARAMETERS:
  558. *
  559. *******************************************************************************/
  560. BOOL PathOnly(LPTSTR sz)
  561. {
  562. LPTSTR p = sz;
  563. LPTSTR s = NULL;
  564. while ( *p ) {
  565. if ( *p == TEXT('\\') ) {
  566. s = p;
  567. } else if ( *p == TEXT(':') ) {
  568. s = p + 1;
  569. }
  570. #if defined(DBCS) || (defined(FE_SB) && !defined(UNICODE))
  571. p = AnsiNext(p);
  572. #else
  573. p++;
  574. #endif
  575. }
  576. if ( s ) {
  577. if ( s == sz )
  578. s++;
  579. *s = TEXT('\0');
  580. return TRUE;
  581. }
  582. return FALSE;
  583. }
  584. #ifdef WINNT
  585. /*******************************************************************************
  586. *
  587. * FileNameOnly
  588. *
  589. * DESCRIPTION: Returns a pointer to the first character after the last
  590. * backslash in a string
  591. *
  592. * PARAMETERS:
  593. *
  594. *******************************************************************************/
  595. LPTSTR FileNameOnly(LPTSTR sz)
  596. {
  597. LPTSTR next = sz;
  598. LPTSTR prev;
  599. LPTSTR begin = next;
  600. if (next == NULL) {
  601. return NULL;
  602. }
  603. while ( *next ) {
  604. prev = next;
  605. #if defined(DBCS) || (defined(FE_SB) && !defined(UNICODE))
  606. next = AnsiNext(next);
  607. #else
  608. next++;
  609. #endif
  610. if ( (*prev == TEXT('\\')) || (*prev == TEXT(':')) ) {
  611. begin = next;
  612. }
  613. }
  614. return begin;
  615. }
  616. /*******************************************************************************
  617. *
  618. * EditWorkItem
  619. *
  620. * DESCRIPTION: Opens the specified task.
  621. *
  622. * PARAMETERS:
  623. *
  624. *******************************************************************************/
  625. void EditWorkItem(HWND hWnd, LPTSTR pszTaskName)
  626. {
  627. ITaskScheduler *pISchedAgent = NULL;
  628. ITask *pITask;
  629. IPersistFile *pIPersistFile;
  630. HRESULT hr;
  631. hr = CoInitialize(NULL);
  632. if (FAILED(hr)) {
  633. DebugPrint( "EditWorkItem: CoInitialize returned hr = %08x\n", hr);
  634. return;
  635. }
  636. hr = CoCreateInstance( &CLSID_CSchedulingAgent,
  637. NULL,
  638. CLSCTX_INPROC_SERVER,
  639. &IID_ISchedulingAgent,
  640. (LPVOID*)&pISchedAgent);
  641. if (SUCCEEDED(hr)) {
  642. hr = pISchedAgent->lpVtbl->Activate(pISchedAgent,
  643. pszTaskName,
  644. &IID_ITask,
  645. &(IUnknown *)pITask);
  646. if (SUCCEEDED(hr)) {
  647. pITask->lpVtbl->EditWorkItem(pITask, hWnd, 0);
  648. pITask->lpVtbl->Release(pITask);
  649. }
  650. else if (HRESULT_CODE (hr) == ERROR_FILE_NOT_FOUND){
  651. hr = pISchedAgent->lpVtbl->NewWorkItem(
  652. pISchedAgent,
  653. pszTaskName,
  654. &CLSID_CTask,
  655. &IID_ITask,
  656. &(IUnknown *)pITask);
  657. if (SUCCEEDED(hr)) {
  658. hr = pITask->lpVtbl->QueryInterface(pITask, &IID_IPersistFile,
  659. (void **)&pIPersistFile);
  660. if (SUCCEEDED(hr)) {
  661. hr = pIPersistFile->lpVtbl->Save(pIPersistFile, NULL, TRUE);
  662. if (SUCCEEDED(hr)) {
  663. pITask->lpVtbl->EditWorkItem(pITask, hWnd, 0);
  664. }
  665. else {
  666. DebugPrint( "EditWorkItem: Save filed hr = %08x\n", hr);
  667. }
  668. pIPersistFile->lpVtbl->Release(pIPersistFile);
  669. }
  670. else {
  671. DebugPrint( "EditWorkItem: QueryInterface for IPersistFile hr = %08x\n", hr);
  672. }
  673. pITask->lpVtbl->Release(pITask);
  674. }
  675. else {
  676. DebugPrint( "EditWorkItem: Activate returned hr = %08x\n", hr);
  677. }
  678. }
  679. else {
  680. DebugPrint( "EditWorkItem: NewWorkItem returned hr = %08x\n", hr);
  681. }
  682. pISchedAgent->lpVtbl->Release(pISchedAgent);
  683. }
  684. else {
  685. DebugPrint( "EditWorkItem: CoCreateInstance returned hr = %08x\n", hr);
  686. }
  687. CoUninitialize();
  688. }
  689. #endif
  690. /*******************************************************************************
  691. *
  692. * SetSliderStatusText
  693. *
  694. * DESCRIPTION:
  695. * Update the current slider position text.
  696. *
  697. * PARAMETERS:
  698. *
  699. *******************************************************************************/
  700. BOOLEAN SetSliderStatusText(HWND hWnd, UINT uiStatusId, UINT uiLevel)
  701. {
  702. LPTSTR pString;
  703. pString = LoadDynamicString(IDS_ALARMLEVELFORMAT,
  704. uiLevel * g_uiBatteryLevelScale);
  705. DisplayFreeStr(hWnd, uiStatusId, pString, FREE_STR);
  706. return TRUE;
  707. }
  708. /*******************************************************************************
  709. *
  710. * SetAlarmStatusText
  711. *
  712. * DESCRIPTION:
  713. *
  714. * PARAMETERS:
  715. *
  716. *******************************************************************************/
  717. BOOLEAN SetAlarmStatusText(HWND hWnd)
  718. {
  719. TCHAR szStatus[MAX_UI_STR_LEN];
  720. LPTSTR lpsz;
  721. UINT uiActionId, uiStatusId, uiIndex, uiAction;
  722. PUINT puiState;
  723. #ifdef WINNT
  724. LPTSTR lpszRunProg;
  725. #endif
  726. puiState = &g_uiCritState;
  727. uiStatusId = IDC_CRITALARMNOTIFICATION;
  728. for (uiIndex = DISCHARGE_POLICY_CRITICAL; uiIndex <= DISCHARGE_POLICY_LOW; uiIndex++) {
  729. // Format the alarm action notification status string.
  730. szStatus[0] = '\0';
  731. if (g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.EventCode &
  732. POWER_LEVEL_USER_NOTIFY_SOUND) {
  733. if ((lpsz = LoadDynamicString(IDS_ALARMSTATUSSOUND)) != NULL) {
  734. lstrcat(szStatus, lpsz);
  735. LocalFree(lpsz);
  736. }
  737. }
  738. if (g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.EventCode &
  739. POWER_LEVEL_USER_NOTIFY_TEXT) {
  740. if (szStatus[0] != '\0') {
  741. lstrcat(szStatus, TEXT(", "));
  742. }
  743. if ((lpsz = LoadDynamicString(IDS_ALARMSTATUSTEXT)) != NULL) {
  744. lstrcat(szStatus, lpsz);
  745. LocalFree(lpsz);
  746. }
  747. }
  748. if (szStatus[0] == '\0') {
  749. if ((lpsz = LoadDynamicString(IDS_NOACTION)) != NULL) {
  750. lstrcat(szStatus, lpsz);
  751. LocalFree(lpsz);
  752. }
  753. }
  754. DisplayFreeStr(hWnd, uiStatusId, szStatus, NO_FREE_STR);
  755. ShowWindow(GetDlgItem(hWnd, uiStatusId),
  756. (*puiState & CONTROL_ENABLE) ? SW_SHOW:SW_HIDE);
  757. uiStatusId++;
  758. // Format the alarm action power mode status string.
  759. uiAction = g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.Action;
  760. switch (uiAction) {
  761. case PowerActionNone:
  762. uiActionId = IDS_NOACTION;
  763. break;
  764. case PowerActionSleep:
  765. uiActionId = IDS_STANDBY;
  766. break;
  767. case PowerActionHibernate:
  768. uiActionId = IDS_HIBERNATE;
  769. break;
  770. case PowerActionShutdown:
  771. case PowerActionShutdownReset:
  772. case PowerActionShutdownOff:
  773. uiActionId = IDS_POWEROFF;
  774. break;
  775. case PowerActionReserved:
  776. default:
  777. DebugPrint( "SetAlarmStatusText, unable to map power action: %X", uiAction);
  778. uiActionId = IDS_NOACTION;
  779. }
  780. lpsz = LoadDynamicString(uiActionId);
  781. DisplayFreeStr(hWnd, uiStatusId, lpsz, FREE_STR);
  782. ShowWindow(GetDlgItem(hWnd, uiStatusId),
  783. (*puiState & CONTROL_ENABLE) ? SW_SHOW:SW_HIDE);
  784. uiStatusId++;
  785. // Format the alarm action run program status string.
  786. #ifdef WINNT
  787. lpszRunProg = NULL;
  788. if (g_gpp.user.DischargePolicy[uiIndex].PowerPolicy.EventCode &
  789. POWER_LEVEL_USER_NOTIFY_EXEC) {
  790. {
  791. //
  792. // Open up the alarm action task and read the program name.
  793. //
  794. ITaskScheduler *pISchedAgent = NULL;
  795. ITask *pITask;
  796. HRESULT hr;
  797. hr = CoInitialize(NULL);
  798. if (SUCCEEDED(hr)) {
  799. hr = CoCreateInstance( &CLSID_CSchedulingAgent,
  800. NULL,
  801. CLSCTX_INPROC_SERVER,
  802. &IID_ISchedulingAgent,
  803. (LPVOID*)&pISchedAgent);
  804. if (SUCCEEDED(hr)) {
  805. hr = pISchedAgent->lpVtbl->Activate(pISchedAgent,
  806. g_szAlarmTaskName [uiIndex],
  807. &IID_ITask,
  808. &(IUnknown *)pITask);
  809. if (SUCCEEDED(hr)) {
  810. pITask->lpVtbl->GetApplicationName(pITask, &lpszRunProg);
  811. pITask->lpVtbl->Release(pITask);
  812. }
  813. pISchedAgent->lpVtbl->Release(pISchedAgent);
  814. }
  815. else {
  816. DebugPrint( "SetAlarmStatusText: CoCreateInstance returned hr = %08x\n", hr);
  817. }
  818. CoUninitialize();
  819. }
  820. }
  821. }
  822. if (lpszRunProg != NULL) {
  823. DisplayFreeStr(hWnd, uiStatusId, FileNameOnly(lpszRunProg), NO_FREE_STR);
  824. CoTaskMemFree (lpszRunProg);
  825. lpszRunProg = NULL;
  826. }
  827. else {
  828. lpsz = LoadDynamicString(IDS_NONE);
  829. DisplayFreeStr(hWnd, uiStatusId, lpsz, FREE_STR);
  830. }
  831. ShowWindow(GetDlgItem(hWnd, uiStatusId),
  832. (*puiState & CONTROL_ENABLE) ? SW_SHOW:SW_HIDE);
  833. #endif
  834. uiStatusId++;
  835. puiState = &g_uiLoState;
  836. uiStatusId = IDC_LOALARMNOTIFICATION;
  837. }
  838. return TRUE;
  839. }
  840. #ifdef WINNT
  841. /*******************************************************************************
  842. *
  843. * HideShowRunProgram
  844. *
  845. * DESCRIPTION:
  846. *
  847. * PARAMETERS:
  848. * On WINNT, only power users may set the run program.
  849. * The run program is stored under HKLM.
  850. *
  851. *******************************************************************************/
  852. void HideShowRunProgram(HWND hWnd)
  853. {
  854. if (CanUserWritePwrScheme()) {
  855. ShowWindow(GetDlgItem(hWnd, IDC_POWERCFGGROUPBOX7), SW_SHOW);
  856. ShowWindow(GetDlgItem(hWnd, IDC_RUNPROGCHECKBOX), SW_SHOW);
  857. ShowWindow(GetDlgItem(hWnd, IDC_RUNPROGWORKITEM), SW_SHOW);
  858. }
  859. else {
  860. ShowWindow(GetDlgItem(hWnd, IDC_POWERCFGGROUPBOX7), SW_HIDE);
  861. ShowWindow(GetDlgItem(hWnd, IDC_RUNPROGCHECKBOX), SW_HIDE);
  862. ShowWindow(GetDlgItem(hWnd, IDC_RUNPROGWORKITEM), SW_HIDE);
  863. }
  864. }
  865. #endif