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.

975 lines
26 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1998
  4. *
  5. * TITLE: NTAPM.C
  6. *
  7. * VERSION: 2.0
  8. *
  9. * AUTHOR: Patrickf
  10. *
  11. * DATE: 09 November, 1998
  12. *
  13. * DESCRIPTION:
  14. * Implements the "APM" tab of the Power Management CPL Applet.
  15. *
  16. *******************************************************************************/
  17. #ifdef WINNT
  18. #include <nt.h>
  19. #include <ntrtl.h>
  20. #include <nturtl.h>
  21. #include <windows.h>
  22. #include <mmsystem.h>
  23. #include <commctrl.h>
  24. #include <shlobj.h>
  25. #include <shellapi.h>
  26. #include <shlobjp.h>
  27. #include <help.h>
  28. #include <powercfp.h>
  29. #include "powercfg.h"
  30. #include "pwrresid.h"
  31. #include "PwrMn_cs.h"
  32. #include "ntapm.h"
  33. BOOL g_fDirty = FALSE; // Has state changed since last apply?
  34. CHAR RegPropBuff[MAX_PATH];
  35. TCHAR CharBuffer[MAX_PATH];
  36. TCHAR m_szApmActive[] = TEXT ("Start");
  37. TCHAR m_szApmActiveKey[] = TEXT("System\\CurrentControlSet\\Services\\NtApm");
  38. TCHAR m_szACPIActive[] = TEXT ("Start");
  39. TCHAR m_szACPIActiveKey[] = TEXT("System\\CurrentControlSet\\Services\\ACPI");
  40. extern HINSTANCE g_hInstance; // Global instance handle of this DLL.
  41. const DWORD g_NtApmHelpIDs[]=
  42. {
  43. IDC_APMENABLE, IDH_ENABLE_APM_SUPPORT, // Save Scheme: "Save Name Power scheme"
  44. 0, 0
  45. };
  46. /*******************************************************************************
  47. *
  48. * G L O B A L D A T A
  49. *
  50. *******************************************************************************/
  51. /*******************************************************************************
  52. *
  53. * NtApmEnableAllPrivileges
  54. *
  55. * DESCRIPTION: This function is used to allow this thread to shudown the
  56. * system.
  57. *
  58. * PARAMETERS:
  59. *
  60. *
  61. *******************************************************************************/
  62. BOOL NtApmEnableAllPrivileges()
  63. {
  64. BOOL Result = FALSE;
  65. ULONG ReturnLen;
  66. ULONG Index;
  67. HANDLE Token = NULL;
  68. PTOKEN_PRIVILEGES NewState = NULL;
  69. //
  70. // Open Process Token
  71. //
  72. Result = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &Token);
  73. if (Result) {
  74. ReturnLen = 4096;
  75. NewState = LocalAlloc(LMEM_FIXED, ReturnLen);
  76. if (NewState != NULL) {
  77. Result = GetTokenInformation(Token, TokenPrivileges, NewState, ReturnLen, &ReturnLen);
  78. if (Result) {
  79. if (NewState->PrivilegeCount > 0) {
  80. for (Index=0; Index < NewState->PrivilegeCount; Index++) {
  81. NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
  82. }
  83. }
  84. Result = AdjustTokenPrivileges(Token, FALSE, NewState, ReturnLen, NULL, &ReturnLen);
  85. }
  86. }
  87. }
  88. if (NewState != NULL) {
  89. LocalFree(NewState);
  90. }
  91. if (Token != NULL) {
  92. CloseHandle(Token);
  93. }
  94. return(Result);
  95. }
  96. /*******************************************************************************
  97. *
  98. * NtApmACPIEnabled
  99. *
  100. * DESCRIPTION: This function gets called to determine if APM is present on
  101. * and started on the machine. If APM is present then the
  102. * tab needs to appear.
  103. *
  104. * This functions check for ACPI, MP and then if APM is actually
  105. * on the machine. If ACPI and MP then APM may be running but is
  106. * disabled.
  107. *
  108. * RETURNS: TRUE if APM is present, FALSE if APM is no present
  109. *
  110. *******************************************************************************/
  111. BOOL NtApmACPIEnabled()
  112. {
  113. BOOL RetVal;
  114. DWORD CharBufferSize;
  115. DWORD ACPIStarted;
  116. HKEY hPortKey;
  117. //
  118. // Initialize - Assume the machine is not ACPI
  119. //
  120. RetVal = FALSE;
  121. //
  122. // Check if ACPI is Present on the machine.
  123. //
  124. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  125. m_szACPIActiveKey,
  126. 0,
  127. KEY_ALL_ACCESS,
  128. &hPortKey) != ERROR_SUCCESS) {
  129. } else if (RegQueryValueEx(hPortKey,
  130. m_szACPIActive,
  131. NULL,
  132. NULL,
  133. (PBYTE) CharBuffer,
  134. &CharBufferSize) != ERROR_SUCCESS) {
  135. RegCloseKey(hPortKey);
  136. } else {
  137. ACPIStarted = (DWORD) CharBuffer[0];
  138. if (ACPIStarted == SERVICE_BOOT_START) {
  139. RetVal = TRUE;
  140. }
  141. RegCloseKey(hPortKey);
  142. }
  143. return(RetVal);
  144. }
  145. /*******************************************************************************
  146. *
  147. * NtApmTurnOnDiFlags
  148. *
  149. * DESCRIPTION: This function sets the DI flags
  150. *
  151. * PARAMETERS:
  152. *
  153. *
  154. *******************************************************************************/
  155. BOOL
  156. NtApmTurnOnDiFlags (
  157. HDEVINFO ApmDevInfo,
  158. PSP_DEVINFO_DATA ApmDevInfoData,
  159. DWORD FlagsMask)
  160. {
  161. BOOL RetVal;
  162. SP_DEVINSTALL_PARAMS DevParams;
  163. //
  164. // Turn on Device Interface flags
  165. //
  166. DevParams.cbSize = sizeof(DevParams);
  167. RetVal = SetupDiGetDeviceInstallParams(ApmDevInfo,
  168. ApmDevInfoData, &DevParams);
  169. if (RetVal) {
  170. DevParams.Flags |= FlagsMask;
  171. RetVal = SetupDiSetDeviceInstallParams(ApmDevInfoData,
  172. NULL, &DevParams);
  173. }
  174. return(RetVal);
  175. }
  176. /*******************************************************************************
  177. *
  178. * NtApmTurnOffDiFlags
  179. *
  180. * DESCRIPTION: This function sets the DI flags
  181. *
  182. * PARAMETERS:
  183. *
  184. *
  185. *******************************************************************************/
  186. BOOL
  187. NtApmTurnOffDiFlags (
  188. HDEVINFO ApmDevInfo,
  189. PSP_DEVINFO_DATA ApmDevInfoData,
  190. DWORD FlagsMask)
  191. {
  192. BOOL RetVal;
  193. SP_DEVINSTALL_PARAMS DevParams;
  194. //
  195. // Turn on Device Interface flags
  196. //
  197. DevParams.cbSize = sizeof(DevParams);
  198. RetVal = SetupDiGetDeviceInstallParams(ApmDevInfo,
  199. ApmDevInfoData, &DevParams);
  200. if (RetVal) {
  201. DevParams.Flags &= ~FlagsMask;
  202. RetVal = SetupDiSetDeviceInstallParams(ApmDevInfoData,
  203. NULL, &DevParams);
  204. }
  205. return(RetVal);
  206. }
  207. /*******************************************************************************
  208. *
  209. * NtApmGetHwProfile
  210. *
  211. * DESCRIPTION: This function is called to retrieve the current H/W Profile
  212. *
  213. * PARAMETERS: Pointer to store HW Profile Info
  214. *
  215. *
  216. *******************************************************************************/
  217. BOOL NtApmGetHwProfile(
  218. DWORD ProfIdx,
  219. HWPROFILEINFO *NtApmHwProf)
  220. {
  221. CONFIGRET CmRetVal;
  222. CmRetVal = CM_Get_Hardware_Profile_Info_Ex(ProfIdx, NtApmHwProf, 0, NULL);
  223. if (CmRetVal == CR_SUCCESS) {
  224. return(TRUE);
  225. } else {
  226. return(FALSE);
  227. }
  228. }
  229. /*******************************************************************************
  230. *
  231. * NtApmCleanup
  232. *
  233. * DESCRIPTION: This function is called to Destroy the DevInfo and DevInfoData
  234. * list that were created.
  235. *
  236. * PARAMETERS:
  237. *
  238. *
  239. *******************************************************************************/
  240. BOOL NtApmCleanup(
  241. HDEVINFO NtApmDevInfo,
  242. PSP_DEVINFO_DATA NtApmDevInfoData)
  243. {
  244. SetupDiDeleteDeviceInfo(NtApmDevInfo, NtApmDevInfoData);
  245. SetupDiDestroyDeviceInfoList(NtApmDevInfo);
  246. return(TRUE);
  247. }
  248. /*******************************************************************************
  249. *
  250. * NtApmGetDevInfo
  251. *
  252. * DESCRIPTION: This function is called to retrieve the HDEVINFO for NTAPM
  253. *
  254. * PARAMETERS:
  255. *
  256. *
  257. *******************************************************************************/
  258. BOOL NtApmGetDevInfo(
  259. HDEVINFO *NtApmDevInfo,
  260. PSP_DEVINFO_DATA NtApmDevInfoData)
  261. {
  262. BOOL RetVal = FALSE; // Assume Failure
  263. *NtApmDevInfo =
  264. SetupDiGetClassDevsEx((LPGUID)&GUID_DEVCLASS_APMSUPPORT, NULL, NULL,
  265. DIGCF_PRESENT, NULL, NULL, NULL);
  266. if(*NtApmDevInfo != INVALID_HANDLE_VALUE) {
  267. //
  268. // Retrieve the DEVINFO_DATA for APM
  269. //
  270. NtApmDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
  271. if (!SetupDiEnumDeviceInfo(*NtApmDevInfo, 0, NtApmDevInfoData)) {
  272. SetupDiDestroyDeviceInfoList(*NtApmDevInfo);
  273. } else {
  274. RetVal = TRUE;
  275. }
  276. }
  277. return(RetVal);
  278. }
  279. /*******************************************************************************
  280. *
  281. * NtApmDisable
  282. *
  283. * DESCRIPTION: This function is called to Disable NT APM
  284. *
  285. * PARAMETERS:
  286. *
  287. *
  288. *******************************************************************************/
  289. BOOL NtApmDisable()
  290. {
  291. DWORD ii;
  292. BOOL Canceled;
  293. SP_PROPCHANGE_PARAMS pcp;
  294. HDEVINFO NtApmDevInfo;
  295. SP_DEVINFO_DATA NtApmDevInfoData;
  296. HWPROFILEINFO NtApmHwProfile;
  297. //
  298. // Get handles to the device and the device information
  299. // If unable to get Device Info immediately return.
  300. //
  301. if (!NtApmGetDevInfo(&NtApmDevInfo, &NtApmDevInfoData)) {
  302. return(FALSE);
  303. }
  304. //
  305. // Turn on the Device Interface Flags
  306. //
  307. NtApmTurnOnDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_NODI_DEFAULTACTION);
  308. //
  309. // Ask the class installer if the device can be generally enabled/disabled
  310. //
  311. pcp.StateChange = DICS_DISABLE;
  312. pcp.Scope = DICS_FLAG_CONFIGGENERAL;
  313. pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  314. pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  315. if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
  316. (PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
  317. goto NtApmDisableError;
  318. }
  319. if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
  320. NtApmDevInfo, &NtApmDevInfoData)) {
  321. goto NtApmDisableError;
  322. }
  323. Canceled = (ERROR_CANCELLED == GetLastError());
  324. if (!Canceled) {
  325. pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
  326. pcp.StateChange = DICS_DISABLE;
  327. for (ii=0; NtApmGetHwProfile(ii, &NtApmHwProfile); ii++) {
  328. pcp.HwProfile = NtApmHwProfile.HWPI_ulHWProfile;
  329. if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
  330. (PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
  331. goto NtApmDisableError;
  332. }
  333. if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, NtApmDevInfo, &NtApmDevInfoData)) {
  334. goto NtApmDisableError;
  335. }
  336. Canceled = (ERROR_CANCELLED == GetLastError());
  337. if (!Canceled) {
  338. if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
  339. (PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
  340. goto NtApmDisableError;
  341. }
  342. if (!SetupDiChangeState(NtApmDevInfo, &NtApmDevInfoData)) {
  343. goto NtApmDisableError;
  344. }
  345. }
  346. }
  347. }
  348. //
  349. // Turn off Flags
  350. //
  351. NtApmTurnOnDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_PROPERTIES_CHANGE);
  352. if (!SetupDiSetClassInstallParams(NtApmDevInfo, NULL, NULL, 0)) {
  353. goto NtApmDisableError;
  354. }
  355. NtApmTurnOffDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_NODI_DEFAULTACTION);
  356. NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
  357. return(TRUE);
  358. NtApmDisableError:
  359. NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
  360. return (FALSE);
  361. }
  362. /*******************************************************************************
  363. *
  364. * NtApmEnable
  365. *
  366. * DESCRIPTION: This function is called to Enable NT APM
  367. *
  368. * PARAMETERS:
  369. *
  370. *
  371. *******************************************************************************/
  372. BOOL NtApmEnable()
  373. {
  374. DWORD ii;
  375. BOOL Canceled;
  376. SP_PROPCHANGE_PARAMS pcp;
  377. HDEVINFO NtApmDevInfo;
  378. SP_DEVINFO_DATA NtApmDevInfoData;
  379. HWPROFILEINFO NtApmHwProfile;
  380. //
  381. // Get handles to the device and the device information
  382. // (If unable to get Device Info immediately return)
  383. //
  384. if (!NtApmGetDevInfo(&NtApmDevInfo, &NtApmDevInfoData)) {
  385. return(FALSE);
  386. }
  387. //
  388. // Turn on the Device Interface Flags
  389. //
  390. NtApmTurnOnDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_NODI_DEFAULTACTION);
  391. //
  392. // Ask the class installer if the device can be generally enabled/disabled
  393. //
  394. pcp.StateChange = DICS_ENABLE;
  395. pcp.Scope = DICS_FLAG_CONFIGGENERAL;
  396. pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
  397. pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
  398. if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
  399. (PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
  400. goto NtApmEnableError;
  401. }
  402. if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
  403. NtApmDevInfo, &NtApmDevInfoData)) {
  404. goto NtApmEnableError;
  405. }
  406. Canceled = (ERROR_CANCELLED == GetLastError());
  407. if (!Canceled) {
  408. pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
  409. pcp.StateChange = DICS_ENABLE;
  410. for (ii=0; NtApmGetHwProfile(ii, &NtApmHwProfile); ii++) {
  411. pcp.HwProfile = NtApmHwProfile.HWPI_ulHWProfile;
  412. if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
  413. (PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
  414. goto NtApmEnableError;
  415. }
  416. if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, NtApmDevInfo, &NtApmDevInfoData)) {
  417. goto NtApmEnableError;
  418. }
  419. Canceled = (ERROR_CANCELLED == GetLastError());
  420. //
  421. // If still good, keep going
  422. //
  423. if (!Canceled) {
  424. if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
  425. (PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
  426. goto NtApmEnableError;
  427. }
  428. if (!SetupDiChangeState(NtApmDevInfo, &NtApmDevInfoData)) {
  429. goto NtApmEnableError;
  430. }
  431. //
  432. // This call will start the device if it is not started
  433. //
  434. pcp.Scope = DICS_FLAG_GLOBAL;
  435. if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
  436. (PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
  437. goto NtApmEnableError;
  438. }
  439. if (!SetupDiChangeState(NtApmDevInfo, &NtApmDevInfoData)) {
  440. goto NtApmEnableError;
  441. }
  442. }
  443. }
  444. }
  445. NtApmTurnOnDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_PROPERTIES_CHANGE);
  446. SetupDiSetClassInstallParams(NtApmDevInfo, NULL, NULL, 0);
  447. NtApmTurnOffDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_NODI_DEFAULTACTION);
  448. NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
  449. return(TRUE);
  450. NtApmEnableError:
  451. NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
  452. return (FALSE);
  453. }
  454. /*******************************************************************************
  455. *
  456. * NtApmEnabled
  457. *
  458. * DESCRIPTION: This function is used to determine if APM is actually
  459. * Enabled or Disabled.
  460. *
  461. * PARAMETERS: hDlg - handle to the dialog box.
  462. * fEnable - TRUE if APM is to be enabled, FALSE if APM is to
  463. * be disabled.
  464. *
  465. *
  466. *******************************************************************************/
  467. NtApmEnabled()
  468. {
  469. DWORD Err;
  470. DWORD HwProf;
  471. DWORD pFlags;
  472. DWORD GlobalConfigFlags;
  473. SP_PROPCHANGE_PARAMS pcp;
  474. HDEVINFO NtApmDevInfo;
  475. SP_DEVINFO_DATA NtApmDevInfoData;
  476. CONFIGRET CmRetVal;
  477. HWPROFILEINFO HwProfileInfo;
  478. TCHAR DeviceId[MAX_DEVICE_ID_LEN + 1];
  479. //
  480. // Registry Property Variables
  481. //
  482. DWORD RegProp;
  483. DWORD RegPropType;
  484. DWORD RegPropBuffSz;
  485. //
  486. // Retrieve the Handle the Device Information for APM.
  487. //
  488. if (!NtApmGetDevInfo(&NtApmDevInfo, &NtApmDevInfoData)) {
  489. return (FALSE);
  490. }
  491. //
  492. // Get the Global Flags (Just-in-case it is globally enabled)
  493. //
  494. RegProp = SPDRP_CONFIGFLAGS;
  495. RegPropBuffSz = sizeof(RegPropBuff) + 1;
  496. if (SetupDiGetDeviceRegistryProperty(NtApmDevInfo, &NtApmDevInfoData,
  497. RegProp, &RegPropType,
  498. RegPropBuff, RegPropBuffSz, 0))
  499. {
  500. if (RegPropType != REG_DWORD) {
  501. GlobalConfigFlags = 0;
  502. } else {
  503. GlobalConfigFlags = (DWORD) RegPropBuff[0];
  504. }
  505. //
  506. // Only Want the disabled bit
  507. //
  508. GlobalConfigFlags = GlobalConfigFlags & CONFIGFLAG_DISABLED;
  509. }
  510. //
  511. // Get the current HW Profile
  512. //
  513. if (!NtApmGetHwProfile(0xffffffff, &HwProfileInfo)) {
  514. goto NtApmEnabledError;
  515. }
  516. //
  517. // Get the Device ID for the given profile
  518. //
  519. HwProf = HwProfileInfo.HWPI_ulHWProfile;
  520. CmRetVal = CM_Get_Device_ID_Ex(NtApmDevInfoData.DevInst,
  521. DeviceId, sizeof(DeviceId), 0, NULL);
  522. if (CmRetVal != CR_SUCCESS) {
  523. Err = GetLastError();
  524. goto NtApmEnabledError;
  525. }
  526. //
  527. // Now get the flags
  528. //
  529. CmRetVal = CM_Get_HW_Prof_Flags_Ex((LPTSTR)DeviceId,
  530. HwProf, &pFlags, 0, NULL);
  531. if (CmRetVal != CR_SUCCESS) {
  532. Err = GetLastError();
  533. goto NtApmEnabledError;
  534. }
  535. NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
  536. if (GlobalConfigFlags || (pFlags & CSCONFIGFLAG_DISABLED)) {
  537. return(FALSE);
  538. } else {
  539. return(TRUE);
  540. }
  541. NtApmEnabledError:
  542. NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
  543. return(FALSE);
  544. }
  545. /*******************************************************************************
  546. *
  547. * NtApmToggle
  548. *
  549. * DESCRIPTION: This function gets called when the user clicks OK or Apply
  550. * and does the work of enabling or disabling APM support.
  551. *
  552. * PARAMETERS: fEnable - Indicates if APM is to enabled or disabled
  553. * SilentDisable - Do not put up dialog to reboot machine.
  554. *
  555. *
  556. *******************************************************************************/
  557. BOOL
  558. NtApmToggle(
  559. IN BOOL fEnable,
  560. IN BOOL SilentDisable)
  561. {
  562. int MBoxRetVal;
  563. TCHAR Str1[2048];
  564. TCHAR Str2[2048];
  565. if (fEnable == APM_ENABLE) {
  566. NtApmEnable();
  567. } else {
  568. if (NtApmDisable()) {
  569. if (!SilentDisable) {
  570. LoadString(g_hInstance, IDS_DEVCHANGE_RESTART, (LPTSTR) Str1, ARRAYSIZE(Str1));
  571. LoadString(g_hInstance, IDS_DEVCHANGE_CAPTION, (LPTSTR) Str2, ARRAYSIZE(Str2));
  572. MBoxRetVal = MessageBox(NULL, Str1, Str2, MB_ICONQUESTION | MB_YESNO);
  573. if (MBoxRetVal == IDYES) {
  574. NtApmEnableAllPrivileges();
  575. ExitWindowsEx(EWX_REBOOT | EWX_FORCEIFHUNG, 0);
  576. }
  577. }
  578. }
  579. }
  580. // Return TRUE for success, FALSE for failure
  581. return(TRUE);
  582. }
  583. /*******************************************************************************
  584. *
  585. * APMDlgHandleInit
  586. *
  587. * DESCRIPTION: Handles WM_INITDIALOG messages sent to APMDlgProc
  588. *
  589. * PARAMETERS:
  590. *
  591. *******************************************************************************/
  592. BOOL
  593. APMDlgHandleInit(
  594. IN HWND hDlg,
  595. IN WPARAM wParam,
  596. IN LPARAM lParam)
  597. {
  598. CheckDlgButton( hDlg,
  599. IDC_APMENABLE,
  600. NtApmEnabled() ? BST_CHECKED : BST_UNCHECKED);
  601. return(TRUE);
  602. }
  603. /*******************************************************************************
  604. *
  605. * APMDlgHandleCommand
  606. *
  607. * DESCRIPTION: Handles WM_COMMAND messages sent to APMDlgProc
  608. *
  609. * PARAMETERS:
  610. *
  611. *******************************************************************************/
  612. BOOL
  613. APMDlgHandleCommand(
  614. IN HWND hDlg,
  615. IN WPARAM wParam,
  616. IN LPARAM lParam
  617. )
  618. {
  619. BOOL RetVal;
  620. WORD idCtl = LOWORD(wParam);
  621. WORD wNotify = HIWORD(wParam);
  622. //
  623. // Assume there is nothing to do and return false;
  624. //
  625. RetVal = FALSE;
  626. switch (idCtl) {
  627. case IDC_APMENABLE:
  628. if (BN_CLICKED == wNotify) {
  629. //
  630. // State changed. Enable the Apply button.
  631. //
  632. g_fDirty = TRUE;
  633. PropSheet_Changed(GetParent(hDlg), hDlg);
  634. }
  635. RetVal = TRUE;
  636. break;
  637. default:
  638. break;
  639. }
  640. return(RetVal);
  641. }
  642. /*******************************************************************************
  643. *
  644. * APMDlgHandleNotify
  645. *
  646. * DESCRIPTION: Handles WM_NOTIFY messages sent to APMDlgProc
  647. *
  648. * PARAMETERS:
  649. *
  650. *******************************************************************************/
  651. BOOL
  652. APMDlgHandleNotify(
  653. IN HWND hDlg,
  654. IN WPARAM wParam,
  655. IN LPARAM lParam
  656. )
  657. {
  658. int idCtl = (int) wParam;
  659. LPNMHDR pnmhdr = (LPNMHDR) lParam;
  660. UINT uNotify = pnmhdr->code;
  661. BOOL fResult;
  662. switch (uNotify) {
  663. case PSN_APPLY:
  664. if (g_fDirty) {
  665. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_APMENABLE)) {
  666. fResult = NtApmToggle(APM_ENABLE, FALSE);
  667. } else {
  668. fResult = NtApmToggle(APM_DISABLE, FALSE);
  669. }
  670. if (fResult) {
  671. g_fDirty = FALSE;
  672. }
  673. SetWindowLongPtr(hDlg, DWLP_MSGRESULT,
  674. fResult ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE);
  675. }
  676. return(TRUE);
  677. break;
  678. default:
  679. return(FALSE);
  680. break;
  681. }
  682. return(FALSE);
  683. }
  684. /*******************************************************************************
  685. *
  686. * IsNtApmPresent
  687. *
  688. * DESCRIPTION: This function gets called to determine if APM is present on
  689. * and started on the machine. If APM is present then the
  690. * tab needs to appear.
  691. *
  692. * This functions check for ACPI, MP and then if APM is actually
  693. * on the machine. If ACPI and MP then APM may be running but is
  694. * disabled.
  695. *
  696. * RETURNS: TRUE if APM is present, FALSE if APM is no present
  697. *
  698. *
  699. *******************************************************************************/
  700. BOOLEAN IsNtApmPresent(PSYSTEM_POWER_CAPABILITIES pspc)
  701. {
  702. BOOLEAN RetVal;
  703. BOOL APMMachine;
  704. BOOL ACPIMachine;
  705. BOOL MPMachine;
  706. DWORD CharBufferSize;
  707. DWORD ApmStarted;
  708. HKEY hPortKey;
  709. SYSTEM_INFO SystemInfo;
  710. //
  711. // Assume nothing about the machine
  712. //
  713. ACPIMachine = FALSE;
  714. MPMachine = FALSE;
  715. APMMachine = FALSE;
  716. CharBufferSize = sizeof(CharBuffer);
  717. //
  718. // We do the following checks:
  719. //
  720. // * check for ACPI
  721. // * check for MP system
  722. //
  723. if (NtApmACPIEnabled()) {
  724. ACPIMachine = TRUE;
  725. } else {
  726. GetSystemInfo(&SystemInfo);
  727. if (SystemInfo.dwNumberOfProcessors > 1) {
  728. MPMachine = TRUE;
  729. }
  730. }
  731. //
  732. // If the machine is ACPI or MP we still need to check if APM
  733. // is enabled so that we can disable it. This is a bug in APM
  734. // code, but it is easiest to just fix it up here.
  735. //
  736. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  737. m_szApmActiveKey,
  738. 0,
  739. KEY_ALL_ACCESS,
  740. &hPortKey) != ERROR_SUCCESS) {
  741. } else if (RegQueryValueEx(hPortKey,
  742. m_szApmActive,
  743. NULL,
  744. NULL,
  745. (PBYTE) CharBuffer,
  746. &CharBufferSize) != ERROR_SUCCESS) {
  747. RegCloseKey(hPortKey);
  748. } else {
  749. if (CharBuffer[0] != (TCHAR) 0) {
  750. ApmStarted = (DWORD) CharBuffer[0];
  751. if (ApmStarted != SERVICE_DISABLED) {
  752. APMMachine = TRUE;
  753. }
  754. }
  755. RegCloseKey(hPortKey);
  756. }
  757. //
  758. // If APM is Present and Enabled it needs to be
  759. // silently disabled if the machine is ACPI or MP.
  760. //
  761. if (ACPIMachine || MPMachine) {
  762. if (APMMachine && NtApmEnabled()) {
  763. NtApmToggle(APM_DISABLE, TRUE);
  764. }
  765. RetVal = FALSE;
  766. } else if (APMMachine) {
  767. RetVal = TRUE;
  768. } else {
  769. RetVal = FALSE;
  770. }
  771. return(RetVal);
  772. }
  773. /*******************************************************************************
  774. *
  775. * P U B L I C E N T R Y P O I N T S
  776. *
  777. *******************************************************************************/
  778. /*******************************************************************************
  779. *
  780. * APMDlgProc
  781. *
  782. * DESCRIPTION:
  783. *
  784. * PARAMETERS:
  785. *
  786. *******************************************************************************/
  787. INT_PTR CALLBACK APMDlgProc(
  788. IN HWND hDlg,
  789. IN UINT uMsg,
  790. IN WPARAM wParam,
  791. IN LPARAM lParam
  792. )
  793. {
  794. switch (uMsg) {
  795. case WM_INITDIALOG:
  796. return(APMDlgHandleInit(hDlg, wParam, lParam));
  797. break;
  798. case WM_COMMAND:
  799. return(APMDlgHandleCommand(hDlg, wParam, lParam));
  800. break;
  801. case WM_NOTIFY:
  802. return(APMDlgHandleNotify(hDlg, wParam, lParam));
  803. break;
  804. case WM_HELP: // F1
  805. WinHelp(((LPHELPINFO)lParam)->hItemHandle, PWRMANHLP,
  806. HELP_WM_HELP, (ULONG_PTR)(LPTSTR)g_NtApmHelpIDs);
  807. return TRUE;
  808. case WM_CONTEXTMENU: // right mouse click
  809. WinHelp((HWND)wParam, PWRMANHLP, HELP_CONTEXTMENU, (ULONG_PTR)(LPTSTR)g_NtApmHelpIDs);
  810. return TRUE;
  811. default:
  812. return(FALSE);
  813. break;
  814. } // switch (uMsg)
  815. return(FALSE);
  816. }
  817. #endif