Leaked source code of windows server 2003
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.

480 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 <strsafe.h>
  25. #include "powercfg.h"
  26. #include "pwrresid.h"
  27. #include "PwrMn_cs.h"
  28. // Private functions implemented in HIBERNAT.C
  29. VOID SetNumberMB(LPTSTR, DWORD, DWORD);
  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. MYDBGPRINT(( "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 cch, DWORD dwValue)
  313. {
  314. LPTSTR pszNumber;
  315. TCHAR szBuf[128];
  316. TCHAR szBufNumber[64];
  317. int iRet;
  318. StringCchPrintf(szBufNumber, ARRAYSIZE(szBufNumber), TEXT("%u"), dwValue);
  319. iRet = GetNumberFormat( GetUserDefaultLCID(), 0, szBufNumber, NULL, szBuf, ARRAYSIZE(szBuf));
  320. if ( 0 == iRet )
  321. {
  322. // If it fails, just copy the string without the puntuation.
  323. StringCchCopy( szBuf, ARRAYSIZE(szBuf), szBufNumber );
  324. }
  325. pszNumber = LoadDynamicString(IDS_MBYTES, szBuf);
  326. if (pszNumber) {
  327. StringCchCopy(psz, cch, pszNumber);
  328. LocalFree(pszNumber);
  329. }
  330. }
  331. /*******************************************************************************
  332. *
  333. * UpdateFreeSpace
  334. *
  335. * DESCRIPTION:
  336. *
  337. * PARAMETERS:
  338. *
  339. *******************************************************************************/
  340. UINT UpdateFreeSpace(HWND hWnd, UINT uiRequiredMB)
  341. {
  342. DWORD dwSectorsPerCluster, dwBytesPerSector;
  343. DWORD dwFreeClusters, dwTotalClusters;
  344. ULONGLONG ullFreeBytes = 0;
  345. UINT uiFreeMB = 0;
  346. TCHAR szTmp[MAX_PATH];
  347. // Get the free space on the system drive.
  348. if (GetSystemDirectory(szTmp, sizeof(szTmp)/sizeof(TCHAR))) {
  349. szTmp[3] = '\0';
  350. if (GetDiskFreeSpace(szTmp,
  351. &dwSectorsPerCluster,
  352. &dwBytesPerSector,
  353. &dwFreeClusters,
  354. &dwTotalClusters)) {
  355. ullFreeBytes = dwBytesPerSector * dwSectorsPerCluster;
  356. ullFreeBytes *= dwFreeClusters;
  357. uiFreeMB = (UINT) (ullFreeBytes /= 0x100000);
  358. SetNumberMB(szTmp, ARRAYSIZE(szTmp), uiFreeMB);
  359. SetDlgItemText(hWnd, IDC_FREESPACE, szTmp);
  360. // Logic to enable/disable disk space warning and hibernate time out.
  361. if ((uiFreeMB >= uiRequiredMB) || g_bHibernate) {
  362. g_dwShowHibernate = CONTROL_ENABLE;
  363. g_dwShowNoDiskSpace = CONTROL_HIDE;
  364. } else {
  365. if (g_bHibernate) {
  366. g_dwShowHibernate = CONTROL_ENABLE;
  367. }
  368. else {
  369. g_dwShowHibernate = CONTROL_DISABLE;
  370. }
  371. g_dwShowNoDiskSpace = CONTROL_ENABLE;
  372. }
  373. }
  374. }
  375. return uiFreeMB;
  376. }
  377. /*******************************************************************************
  378. *
  379. * UpdatePhysMem
  380. *
  381. * DESCRIPTION:
  382. *
  383. * PARAMETERS:
  384. *
  385. *******************************************************************************/
  386. UINT UpdatePhysMem(void)
  387. {
  388. UINT uiPhysMemMB;
  389. #ifdef WINNT
  390. MEMORYSTATUSEX msex;
  391. msex.dwLength = sizeof(msex);
  392. GlobalMemoryStatusEx(&msex);
  393. uiPhysMemMB = (UINT) (msex.ullTotalPhys / 0x100000);
  394. if (msex.ullTotalPhys % 0x100000) {
  395. uiPhysMemMB++;
  396. }
  397. #else
  398. MEMORYSTATUS ms;
  399. ms.dwLength = sizeof(ms);
  400. GlobalMemoryStatus(&ms);
  401. uiPhysMemMB = (UINT) (ms.dwTotalPhys / 0x100000);
  402. if (ms.dwTotalPhys % 0x100000) {
  403. uiPhysMemMB++;
  404. }
  405. #endif
  406. SetNumberMB(g_szRequiredSpace, ARRAYSIZE(g_szRequiredSpace), uiPhysMemMB);
  407. return uiPhysMemMB;
  408. }