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.

513 lines
15 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1996
  4. *
  5. * TITLE: HIBERNAT.C
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: ReedB
  10. *
  11. * DATE: 17 Oct, 1996
  12. *
  13. * DESCRIPTION:
  14. * Support for hibernate page of PowerCfg.Cpl.
  15. *
  16. *******************************************************************************/
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #include <commctrl.h>
  22. #include <help.h>
  23. #include <powercfp.h>
  24. #include "powercfg.h"
  25. #include "pwrresid.h"
  26. #include "PwrMn_cs.h"
  27. // Private functions implemented in HIBERNAT.C
  28. VOID SetNumberMB(LPTSTR, DWORD);
  29. VOID InsertSeparators(LPTSTR);
  30. UINT UpdateFreeSpace(HWND, UINT);
  31. UINT UpdatePhysMem(void);
  32. /*******************************************************************************
  33. *
  34. * G L O B A L D A T A
  35. *
  36. *******************************************************************************/
  37. // This structure is filled in by the Power Policy Manager at CPL_INIT time.
  38. extern SYSTEM_POWER_CAPABILITIES g_SysPwrCapabilities;
  39. extern BOOL g_bRunningUnderNT;
  40. // A systary change requires PowerSchemeDlgProc re-init.
  41. extern BOOL g_bSystrayChange;
  42. // Persistant storage of this data is managed by POWRPROF.DLL API's.
  43. extern GLOBAL_POWER_POLICY g_gpp;
  44. // Power button power action string ID's. With and without hibernate.
  45. UINT g_uiPwrActIDs[] =
  46. {
  47. IDS_NONE, PowerActionNone,
  48. IDS_PROMPT, PowerActionNone,
  49. IDS_STANDBY, PowerActionSleep,
  50. IDS_HIBERNATE, PowerActionHibernate,
  51. IDS_POWEROFF, PowerActionShutdownOff,
  52. 0, 0
  53. };
  54. // Lid action string ID's. With and without hibernate.
  55. UINT g_uiLidActIDs[] =
  56. {
  57. IDS_NONE, PowerActionNone,
  58. IDS_STANDBY, PowerActionSleep,
  59. IDS_HIBERNATE, PowerActionHibernate,
  60. IDS_POWEROFF, PowerActionShutdownOff,
  61. 0, 0
  62. };
  63. // UI state variables
  64. TCHAR g_szRequiredSpace[128];
  65. DWORD g_dwShowHibernate;
  66. DWORD g_dwShowNoDiskSpace;
  67. DWORD g_dwShowDiskSpace;
  68. DWORD g_dwTrueFlag = (DWORD) TRUE;
  69. BOOLEAN g_bHibernate;
  70. // Globals for DoHibernateApply:
  71. BOOL g_bHibernateDirty;
  72. HWND g_hwndHibernateDlg;
  73. UINT g_uiRequiredMB;
  74. // Hibernate policies dialog controls descriptions:
  75. #define NUM_HIBERNATE_POL_CONTROLS 7
  76. // Handy indicies into our g_pcHibernatePol array:
  77. #define ID_REQUIREDSPACE 0
  78. #define ID_NOTENOUGHSPACE 1
  79. #define ID_HIBERNATE 2
  80. POWER_CONTROLS g_pcHibernatePol[NUM_HIBERNATE_POL_CONTROLS] =
  81. {// Control ID Control Type Data Address Data Size Parameter Pointer Enable/Visible State Pointer
  82. IDC_REQUIREDSPACE, EDIT_TEXT_RO, &g_szRequiredSpace, 0, NULL, &g_dwShowDiskSpace,
  83. IDC_NOTENOUGHSPACE, STATIC_TEXT, NULL, 0, NULL, &g_dwShowNoDiskSpace,
  84. IDC_HIBERNATE, CHECK_BOX, &g_bHibernate, sizeof(g_bHibernate), &g_dwTrueFlag, &g_dwShowHibernate,
  85. IDC_DISKSPACEGROUPBOX, STATIC_TEXT, NULL, 0, NULL, &g_dwShowDiskSpace,
  86. IDC_FREESPACETEXT, STATIC_TEXT, NULL, 0, NULL, &g_dwShowDiskSpace,
  87. IDC_REQUIREDSPACETEXT, STATIC_TEXT, NULL, 0, NULL, &g_dwShowDiskSpace,
  88. IDC_FREESPACE, STATIC_TEXT, NULL, 0, NULL, &g_dwShowDiskSpace,
  89. };
  90. // "Hibernate" Dialog Box (IDD_HIBERNATE == 105) help array:
  91. const DWORD g_HibernateHelpIDs[]=
  92. {
  93. IDC_HIBERNATE, IDH_105_1400, // Hibernate: "After going on standby, &hibernate." (Button)
  94. IDC_FREESPACE, IDH_105_1401, // Hibernate: "Free space" (Static)
  95. IDC_REQUIREDSPACE, IDH_105_1402, // Hibernate: "Required space to hibernate" (Static)
  96. IDC_NOTENOUGHSPACE, IDH_105_1403, // Hibernate: "You must free up some disk space before your computer can hibernate." (Static)
  97. IDC_DISKSPACEGROUPBOX, IDH_105_1402,
  98. IDC_FREESPACETEXT, IDH_105_1401,
  99. IDC_REQUIREDSPACETEXT, IDH_105_1402,
  100. IDC_HIBERNATEGROUPBOX, IDH_105_1400,
  101. IDI_HIBERNATE, NO_HELP,
  102. IDC_NO_HELP_6, NO_HELP,
  103. IDI_PWRMNG, NO_HELP,
  104. 0, 0
  105. };
  106. /*******************************************************************************
  107. *
  108. * P U B L I C E N T R Y P O I N T S
  109. *
  110. *******************************************************************************/
  111. /*******************************************************************************
  112. *
  113. * MapPwrAct
  114. *
  115. * DESCRIPTION:
  116. * Map power action to one of a lesser number of UI supported actions.
  117. * Depends on state of hibernate so implemented here.
  118. *
  119. * PARAMETERS:
  120. *
  121. *******************************************************************************/
  122. BOOL MapPwrAct(
  123. PPOWER_ACTION ppa,
  124. BOOL bNone
  125. )
  126. {
  127. switch (*ppa) {
  128. case PowerActionNone:
  129. if (bNone) {
  130. *ppa = PowerActionNone;
  131. break;
  132. }
  133. case PowerActionReserved:
  134. case PowerActionSleep:
  135. *ppa = PowerActionSleep;
  136. break;
  137. case PowerActionHibernate:
  138. if (g_SysPwrCapabilities.HiberFilePresent) {
  139. *ppa = PowerActionHibernate;
  140. }
  141. else {
  142. *ppa = PowerActionSleep;
  143. }
  144. break;
  145. case PowerActionShutdown:
  146. case PowerActionShutdownReset:
  147. case PowerActionShutdownOff:
  148. *ppa = PowerActionShutdownOff;
  149. break;
  150. default:
  151. DebugPrint( "MapPwrAct, unknown power action: %X", *ppa);
  152. *ppa = PowerActionShutdownOff;
  153. return FALSE;
  154. }
  155. return TRUE;
  156. }
  157. /*******************************************************************************
  158. *
  159. * DoHibernateApply
  160. *
  161. * DESCRIPTION:
  162. * Handle the WM_NOTIFY, PSN_APPLY message for HibernateDlgProc. Updates
  163. * global hibernate state.
  164. *
  165. * PARAMETERS:
  166. *
  167. *******************************************************************************/
  168. void DoHibernateApply(void)
  169. {
  170. NTSTATUS status;
  171. // Only handle if hibernate page is dirty.
  172. if (g_bHibernateDirty) {
  173. // Fetch data from dialog controls.
  174. GetControls(g_hwndHibernateDlg,
  175. NUM_HIBERNATE_POL_CONTROLS,
  176. g_pcHibernatePol);
  177. status = CallNtPowerInformation(SystemReserveHiberFile,
  178. &g_bHibernate,
  179. sizeof(g_bHibernate),
  180. NULL,
  181. 0);
  182. if (status != STATUS_SUCCESS) {
  183. ErrorMsgBox(g_hwndHibernateDlg,
  184. #ifdef WINNT
  185. RtlNtStatusToDosError(status),
  186. #else
  187. NO_ERROR,
  188. #endif
  189. IDS_UNABLETOSETHIBER);
  190. }
  191. // Get the current hibernate state from the PPM.
  192. if (GetPwrCapabilities(&g_SysPwrCapabilities)) {
  193. g_bHibernate = g_SysPwrCapabilities.HiberFilePresent;
  194. // Map power actions to allowed UI values.
  195. MapPwrAct(&g_gpp.user.LidCloseDc.Action, TRUE);
  196. MapPwrAct(&g_gpp.user.PowerButtonDc.Action, FALSE);
  197. MapPwrAct(&g_gpp.user.SleepButtonDc.Action, FALSE);
  198. }
  199. SetControls(g_hwndHibernateDlg, 1, &g_pcHibernatePol[ID_HIBERNATE]);
  200. UpdateFreeSpace(g_hwndHibernateDlg, g_uiRequiredMB);
  201. g_bHibernateDirty = FALSE;
  202. }
  203. }
  204. /*******************************************************************************
  205. *
  206. * HibernateDlgProc
  207. *
  208. * DESCRIPTION:
  209. *
  210. * PARAMETERS:
  211. *
  212. *******************************************************************************/
  213. INT_PTR CALLBACK HibernateDlgProc(
  214. HWND hWnd,
  215. UINT uMsg,
  216. WPARAM wParam,
  217. LPARAM lParam
  218. )
  219. {
  220. NMHDR FAR *lpnm;
  221. LPTSTR pszUPS;
  222. switch (uMsg) {
  223. case WM_INITDIALOG:
  224. // Save the hibernate dialog hwnd for use by DoHibernateApply.
  225. g_hwndHibernateDlg = hWnd;
  226. // Get the current hibernate state from the PPM.
  227. if (GetPwrCapabilities(&g_SysPwrCapabilities)) {
  228. g_bHibernate = g_SysPwrCapabilities.HiberFilePresent;
  229. }
  230. // Get the disk free and required space only under NT.
  231. if (g_bRunningUnderNT) {
  232. g_dwShowDiskSpace = CONTROL_ENABLE;
  233. // Get the required space from the power capabilities.
  234. g_uiRequiredMB = UpdatePhysMem();
  235. // Update the disk free space and enable/disable
  236. // disk space warning and hibernate time out.
  237. UpdateFreeSpace(hWnd, g_uiRequiredMB);
  238. } else {
  239. g_dwShowHibernate = CONTROL_ENABLE;
  240. g_dwShowDiskSpace = CONTROL_HIDE;
  241. g_dwShowNoDiskSpace = CONTROL_HIDE;
  242. }
  243. SetControls(hWnd, NUM_HIBERNATE_POL_CONTROLS, g_pcHibernatePol);
  244. //
  245. // Disable the checkbox is the user doesn't have permission to
  246. // change it. We do this by trying to set the same value we
  247. // retrieved earlier.
  248. //
  249. {
  250. NTSTATUS status;
  251. status = CallNtPowerInformation(SystemReserveHiberFile,
  252. &g_bHibernate,
  253. sizeof(g_bHibernate),
  254. NULL,
  255. 0);
  256. if ( ERROR_SUCCESS != status )
  257. {
  258. EnableWindow( GetDlgItem( hWnd, IDC_HIBERNATE ), FALSE );
  259. }
  260. }
  261. return TRUE;
  262. case WM_ACTIVATE:
  263. // If user switches away, check the disk space when they come back.
  264. if (g_bRunningUnderNT) {
  265. GetControls(hWnd, NUM_HIBERNATE_POL_CONTROLS, g_pcHibernatePol);
  266. UpdateFreeSpace(hWnd, g_uiRequiredMB);
  267. SetControls(hWnd, NUM_HIBERNATE_POL_CONTROLS-1, g_pcHibernatePol);
  268. }
  269. break;
  270. case WM_NOTIFY:
  271. lpnm = (NMHDR FAR *)lParam;
  272. switch (lpnm->code) {
  273. case PSN_APPLY:
  274. DoHibernateApply();
  275. break;
  276. }
  277. break;
  278. case WM_COMMAND:
  279. switch (LOWORD(wParam)) {
  280. case IDC_HIBERNATE:
  281. MarkSheetDirty(hWnd, &g_bHibernateDirty);
  282. break;
  283. }
  284. break;
  285. case PCWM_NOTIFYPOWER:
  286. // Notification from systray, user has changed a PM UI setting.
  287. g_bSystrayChange = TRUE;
  288. break;
  289. case WM_HELP: // F1
  290. WinHelp(((LPHELPINFO)lParam)->hItemHandle, PWRMANHLP, HELP_WM_HELP, (ULONG_PTR)(LPTSTR)g_HibernateHelpIDs);
  291. return TRUE;
  292. case WM_CONTEXTMENU: // right mouse click
  293. WinHelp((HWND)wParam, PWRMANHLP, HELP_CONTEXTMENU, (ULONG_PTR)(LPTSTR)g_HibernateHelpIDs);
  294. return TRUE;
  295. }
  296. return FALSE;
  297. }
  298. /*******************************************************************************
  299. *
  300. * P R I V A T E F U N C T I O N S
  301. *
  302. *******************************************************************************/
  303. /*******************************************************************************
  304. *
  305. * SetNumberMB
  306. *
  307. * DESCRIPTION:
  308. *
  309. * PARAMETERS:
  310. *
  311. *******************************************************************************/
  312. VOID SetNumberMB(LPTSTR psz, DWORD dwValue)
  313. {
  314. LPTSTR pszNumber;
  315. TCHAR szBuf[128];
  316. TCHAR szBufLow[64];
  317. wsprintf(szBuf, TEXT("%u"), dwValue);
  318. InsertSeparators(szBuf);
  319. pszNumber = LoadDynamicString(IDS_MBYTES, szBuf);
  320. if (pszNumber) {
  321. lstrcpy(psz, pszNumber);
  322. LocalFree(pszNumber);
  323. }
  324. }
  325. /*******************************************************************************
  326. *
  327. * InsertSeparators
  328. *
  329. * DESCRIPTION:
  330. * Passed string must be large enough to hold seperators.
  331. *
  332. * PARAMETERS:
  333. *
  334. *******************************************************************************/
  335. VOID InsertSeparators(LPTSTR pszNumber)
  336. {
  337. TCHAR szSeparator[10];
  338. TCHAR Separator;
  339. TCHAR szBuf[128];
  340. ULONG cchNumber;
  341. UINT Triples;
  342. LPTSTR pch;
  343. if (GetLocaleInfo(GetUserDefaultLCID(),
  344. LOCALE_STHOUSAND,
  345. szSeparator,
  346. sizeof(szSeparator)/sizeof(TCHAR))) {
  347. Separator = szSeparator[0];
  348. cchNumber = lstrlen(pszNumber);
  349. Triples = 0;
  350. szBuf[127] = '\0';
  351. pch = &szBuf[126];
  352. while (cchNumber > 0) {
  353. *pch-- = pszNumber[--cchNumber];
  354. ++Triples;
  355. if ((0 == (Triples % 3)) && (cchNumber > 0)) {
  356. *pch-- = Separator;
  357. }
  358. }
  359. lstrcpy(pszNumber, pch + 1);
  360. }
  361. }
  362. /*******************************************************************************
  363. *
  364. * UpdateFreeSpace
  365. *
  366. * DESCRIPTION:
  367. *
  368. * PARAMETERS:
  369. *
  370. *******************************************************************************/
  371. UINT UpdateFreeSpace(HWND hWnd, UINT uiRequiredMB)
  372. {
  373. DWORD dwSectorsPerCluster, dwBytesPerSector;
  374. DWORD dwFreeClusters, dwTotalClusters;
  375. ULONGLONG ullFreeBytes = 0;
  376. UINT uiFreeMB = 0;
  377. TCHAR szTmp[MAX_PATH];
  378. // Get the free space on the system drive.
  379. if (GetSystemDirectory(szTmp, sizeof(szTmp)/sizeof(TCHAR))) {
  380. szTmp[3] = '\0';
  381. if (GetDiskFreeSpace(szTmp,
  382. &dwSectorsPerCluster,
  383. &dwBytesPerSector,
  384. &dwFreeClusters,
  385. &dwTotalClusters)) {
  386. ullFreeBytes = dwBytesPerSector * dwSectorsPerCluster;
  387. ullFreeBytes *= dwFreeClusters;
  388. uiFreeMB = (UINT) (ullFreeBytes /= 0x100000);
  389. SetNumberMB(szTmp, uiFreeMB);
  390. SetDlgItemText(hWnd, IDC_FREESPACE, szTmp);
  391. // Logic to enable/disable disk space warning and hibernate time out.
  392. if ((uiFreeMB >= uiRequiredMB) || g_bHibernate) {
  393. g_dwShowHibernate = CONTROL_ENABLE;
  394. g_dwShowNoDiskSpace = CONTROL_HIDE;
  395. } else {
  396. if (g_bHibernate) {
  397. g_dwShowHibernate = CONTROL_ENABLE;
  398. }
  399. else {
  400. g_dwShowHibernate = CONTROL_DISABLE;
  401. }
  402. g_dwShowNoDiskSpace = CONTROL_ENABLE;
  403. }
  404. }
  405. }
  406. return uiFreeMB;
  407. }
  408. /*******************************************************************************
  409. *
  410. * UpdatePhysMem
  411. *
  412. * DESCRIPTION:
  413. *
  414. * PARAMETERS:
  415. *
  416. *******************************************************************************/
  417. UINT UpdatePhysMem(void)
  418. {
  419. UINT uiPhysMemMB;
  420. #ifdef WINNT
  421. MEMORYSTATUSEX msex;
  422. msex.dwLength = sizeof(msex);
  423. GlobalMemoryStatusEx(&msex);
  424. uiPhysMemMB = (UINT) (msex.ullTotalPhys / 0x100000);
  425. if (msex.ullTotalPhys % 0x100000) {
  426. uiPhysMemMB++;
  427. }
  428. #else
  429. MEMORYSTATUS ms;
  430. ms.dwLength = sizeof(ms);
  431. GlobalMemoryStatus(&ms);
  432. uiPhysMemMB = (UINT) (ms.dwTotalPhys / 0x100000);
  433. if (ms.dwTotalPhys % 0x100000) {
  434. uiPhysMemMB++;
  435. }
  436. #endif
  437. SetNumberMB(g_szRequiredSpace, uiPhysMemMB);
  438. return uiPhysMemMB;
  439. }