976 lines
26 KiB
C
976 lines
26 KiB
C
|
/*******************************************************************************
|
||
|
*
|
||
|
* (C) COPYRIGHT MICROSOFT CORP., 1998
|
||
|
*
|
||
|
* TITLE: NTAPM.C
|
||
|
*
|
||
|
* VERSION: 2.0
|
||
|
*
|
||
|
* AUTHOR: Patrickf
|
||
|
*
|
||
|
* DATE: 09 November, 1998
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
* Implements the "APM" tab of the Power Management CPL Applet.
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
#ifdef WINNT
|
||
|
#include <nt.h>
|
||
|
#include <ntrtl.h>
|
||
|
#include <nturtl.h>
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <mmsystem.h>
|
||
|
#include <commctrl.h>
|
||
|
#include <shlobj.h>
|
||
|
#include <shellapi.h>
|
||
|
#include <shlobjp.h>
|
||
|
#include <help.h>
|
||
|
#include <powercfp.h>
|
||
|
#include "powercfg.h"
|
||
|
#include "pwrresid.h"
|
||
|
#include "PwrMn_cs.h"
|
||
|
#include "ntapm.h"
|
||
|
|
||
|
BOOL g_fDirty = FALSE; // Has state changed since last apply?
|
||
|
|
||
|
CHAR RegPropBuff[MAX_PATH];
|
||
|
TCHAR CharBuffer[MAX_PATH];
|
||
|
|
||
|
TCHAR m_szApmActive[] = TEXT ("Start");
|
||
|
TCHAR m_szApmActiveKey[] = TEXT("System\\CurrentControlSet\\Services\\NtApm");
|
||
|
TCHAR m_szACPIActive[] = TEXT ("Start");
|
||
|
TCHAR m_szACPIActiveKey[] = TEXT("System\\CurrentControlSet\\Services\\ACPI");
|
||
|
|
||
|
extern HINSTANCE g_hInstance; // Global instance handle of this DLL.
|
||
|
|
||
|
const DWORD g_NtApmHelpIDs[]=
|
||
|
{
|
||
|
IDC_APMENABLE, IDH_ENABLE_APM_SUPPORT, // Save Scheme: "Save Name Power scheme"
|
||
|
0, 0
|
||
|
};
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* G L O B A L D A T A
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* NtApmEnableAllPrivileges
|
||
|
*
|
||
|
* DESCRIPTION: This function is used to allow this thread to shudown the
|
||
|
* system.
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL NtApmEnableAllPrivileges()
|
||
|
{
|
||
|
BOOL Result = FALSE;
|
||
|
ULONG ReturnLen;
|
||
|
ULONG Index;
|
||
|
|
||
|
HANDLE Token = NULL;
|
||
|
PTOKEN_PRIVILEGES NewState = NULL;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Open Process Token
|
||
|
//
|
||
|
Result = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &Token);
|
||
|
|
||
|
if (Result) {
|
||
|
ReturnLen = 4096;
|
||
|
NewState = LocalAlloc(LMEM_FIXED, ReturnLen);
|
||
|
|
||
|
if (NewState != NULL) {
|
||
|
Result = GetTokenInformation(Token, TokenPrivileges, NewState, ReturnLen, &ReturnLen);
|
||
|
if (Result) {
|
||
|
if (NewState->PrivilegeCount > 0) {
|
||
|
for (Index=0; Index < NewState->PrivilegeCount; Index++) {
|
||
|
NewState->Privileges[Index].Attributes = SE_PRIVILEGE_ENABLED;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Result = AdjustTokenPrivileges(Token, FALSE, NewState, ReturnLen, NULL, &ReturnLen);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NewState != NULL) {
|
||
|
LocalFree(NewState);
|
||
|
}
|
||
|
|
||
|
if (Token != NULL) {
|
||
|
CloseHandle(Token);
|
||
|
}
|
||
|
|
||
|
return(Result);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* NtApmACPIEnabled
|
||
|
*
|
||
|
* DESCRIPTION: This function gets called to determine if APM is present on
|
||
|
* and started on the machine. If APM is present then the
|
||
|
* tab needs to appear.
|
||
|
*
|
||
|
* This functions check for ACPI, MP and then if APM is actually
|
||
|
* on the machine. If ACPI and MP then APM may be running but is
|
||
|
* disabled.
|
||
|
*
|
||
|
* RETURNS: TRUE if APM is present, FALSE if APM is no present
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL NtApmACPIEnabled()
|
||
|
{
|
||
|
BOOL RetVal;
|
||
|
DWORD CharBufferSize;
|
||
|
DWORD ACPIStarted;
|
||
|
HKEY hPortKey;
|
||
|
|
||
|
//
|
||
|
// Initialize - Assume the machine is not ACPI
|
||
|
//
|
||
|
RetVal = FALSE;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Check if ACPI is Present on the machine.
|
||
|
//
|
||
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||
|
m_szACPIActiveKey,
|
||
|
0,
|
||
|
KEY_ALL_ACCESS,
|
||
|
&hPortKey) != ERROR_SUCCESS) {
|
||
|
|
||
|
} else if (RegQueryValueEx(hPortKey,
|
||
|
m_szACPIActive,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
(PBYTE) CharBuffer,
|
||
|
&CharBufferSize) != ERROR_SUCCESS) {
|
||
|
|
||
|
RegCloseKey(hPortKey);
|
||
|
|
||
|
} else {
|
||
|
ACPIStarted = (DWORD) CharBuffer[0];
|
||
|
|
||
|
if (ACPIStarted == SERVICE_BOOT_START) {
|
||
|
RetVal = TRUE;
|
||
|
}
|
||
|
RegCloseKey(hPortKey);
|
||
|
}
|
||
|
|
||
|
return(RetVal);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* NtApmTurnOnDiFlags
|
||
|
*
|
||
|
* DESCRIPTION: This function sets the DI flags
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL
|
||
|
NtApmTurnOnDiFlags (
|
||
|
HDEVINFO ApmDevInfo,
|
||
|
PSP_DEVINFO_DATA ApmDevInfoData,
|
||
|
DWORD FlagsMask)
|
||
|
{
|
||
|
BOOL RetVal;
|
||
|
SP_DEVINSTALL_PARAMS DevParams;
|
||
|
|
||
|
//
|
||
|
// Turn on Device Interface flags
|
||
|
//
|
||
|
DevParams.cbSize = sizeof(DevParams);
|
||
|
RetVal = SetupDiGetDeviceInstallParams(ApmDevInfo,
|
||
|
ApmDevInfoData, &DevParams);
|
||
|
|
||
|
if (RetVal) {
|
||
|
DevParams.Flags |= FlagsMask;
|
||
|
RetVal = SetupDiSetDeviceInstallParams(ApmDevInfoData,
|
||
|
NULL, &DevParams);
|
||
|
}
|
||
|
|
||
|
return(RetVal);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* NtApmTurnOffDiFlags
|
||
|
*
|
||
|
* DESCRIPTION: This function sets the DI flags
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL
|
||
|
NtApmTurnOffDiFlags (
|
||
|
HDEVINFO ApmDevInfo,
|
||
|
PSP_DEVINFO_DATA ApmDevInfoData,
|
||
|
DWORD FlagsMask)
|
||
|
{
|
||
|
BOOL RetVal;
|
||
|
SP_DEVINSTALL_PARAMS DevParams;
|
||
|
|
||
|
//
|
||
|
// Turn on Device Interface flags
|
||
|
//
|
||
|
DevParams.cbSize = sizeof(DevParams);
|
||
|
RetVal = SetupDiGetDeviceInstallParams(ApmDevInfo,
|
||
|
ApmDevInfoData, &DevParams);
|
||
|
|
||
|
if (RetVal) {
|
||
|
DevParams.Flags &= ~FlagsMask;
|
||
|
RetVal = SetupDiSetDeviceInstallParams(ApmDevInfoData,
|
||
|
NULL, &DevParams);
|
||
|
}
|
||
|
|
||
|
return(RetVal);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* NtApmGetHwProfile
|
||
|
*
|
||
|
* DESCRIPTION: This function is called to retrieve the current H/W Profile
|
||
|
*
|
||
|
* PARAMETERS: Pointer to store HW Profile Info
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL NtApmGetHwProfile(
|
||
|
DWORD ProfIdx,
|
||
|
HWPROFILEINFO *NtApmHwProf)
|
||
|
{
|
||
|
CONFIGRET CmRetVal;
|
||
|
|
||
|
CmRetVal = CM_Get_Hardware_Profile_Info_Ex(ProfIdx, NtApmHwProf, 0, NULL);
|
||
|
|
||
|
if (CmRetVal == CR_SUCCESS) {
|
||
|
return(TRUE);
|
||
|
} else {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* NtApmCleanup
|
||
|
*
|
||
|
* DESCRIPTION: This function is called to Destroy the DevInfo and DevInfoData
|
||
|
* list that were created.
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL NtApmCleanup(
|
||
|
HDEVINFO NtApmDevInfo,
|
||
|
PSP_DEVINFO_DATA NtApmDevInfoData)
|
||
|
{
|
||
|
|
||
|
SetupDiDeleteDeviceInfo(NtApmDevInfo, NtApmDevInfoData);
|
||
|
SetupDiDestroyDeviceInfoList(NtApmDevInfo);
|
||
|
|
||
|
return(TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* NtApmGetDevInfo
|
||
|
*
|
||
|
* DESCRIPTION: This function is called to retrieve the HDEVINFO for NTAPM
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL NtApmGetDevInfo(
|
||
|
HDEVINFO *NtApmDevInfo,
|
||
|
PSP_DEVINFO_DATA NtApmDevInfoData)
|
||
|
{
|
||
|
BOOL RetVal = FALSE; // Assume Failure
|
||
|
|
||
|
*NtApmDevInfo =
|
||
|
SetupDiGetClassDevsEx((LPGUID)&GUID_DEVCLASS_APMSUPPORT, NULL, NULL,
|
||
|
DIGCF_PRESENT, NULL, NULL, NULL);
|
||
|
|
||
|
if(*NtApmDevInfo != INVALID_HANDLE_VALUE) {
|
||
|
|
||
|
//
|
||
|
// Retrieve the DEVINFO_DATA for APM
|
||
|
//
|
||
|
NtApmDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
|
||
|
if (!SetupDiEnumDeviceInfo(*NtApmDevInfo, 0, NtApmDevInfoData)) {
|
||
|
SetupDiDestroyDeviceInfoList(*NtApmDevInfo);
|
||
|
} else {
|
||
|
RetVal = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return(RetVal);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* NtApmDisable
|
||
|
*
|
||
|
* DESCRIPTION: This function is called to Disable NT APM
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL NtApmDisable()
|
||
|
{
|
||
|
DWORD ii;
|
||
|
BOOL Canceled;
|
||
|
SP_PROPCHANGE_PARAMS pcp;
|
||
|
|
||
|
HDEVINFO NtApmDevInfo;
|
||
|
SP_DEVINFO_DATA NtApmDevInfoData;
|
||
|
HWPROFILEINFO NtApmHwProfile;
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Get handles to the device and the device information
|
||
|
// If unable to get Device Info immediately return.
|
||
|
//
|
||
|
if (!NtApmGetDevInfo(&NtApmDevInfo, &NtApmDevInfoData)) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Turn on the Device Interface Flags
|
||
|
//
|
||
|
NtApmTurnOnDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_NODI_DEFAULTACTION);
|
||
|
|
||
|
//
|
||
|
// Ask the class installer if the device can be generally enabled/disabled
|
||
|
//
|
||
|
pcp.StateChange = DICS_DISABLE;
|
||
|
pcp.Scope = DICS_FLAG_CONFIGGENERAL;
|
||
|
|
||
|
pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
|
||
|
pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
|
||
|
|
||
|
if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
|
||
|
(PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
|
||
|
goto NtApmDisableError;
|
||
|
}
|
||
|
|
||
|
if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
|
||
|
NtApmDevInfo, &NtApmDevInfoData)) {
|
||
|
goto NtApmDisableError;
|
||
|
}
|
||
|
|
||
|
Canceled = (ERROR_CANCELLED == GetLastError());
|
||
|
|
||
|
if (!Canceled) {
|
||
|
pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
|
||
|
pcp.StateChange = DICS_DISABLE;
|
||
|
|
||
|
for (ii=0; NtApmGetHwProfile(ii, &NtApmHwProfile); ii++) {
|
||
|
pcp.HwProfile = NtApmHwProfile.HWPI_ulHWProfile;
|
||
|
|
||
|
if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
|
||
|
(PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
|
||
|
goto NtApmDisableError;
|
||
|
}
|
||
|
|
||
|
if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, NtApmDevInfo, &NtApmDevInfoData)) {
|
||
|
goto NtApmDisableError;
|
||
|
}
|
||
|
|
||
|
Canceled = (ERROR_CANCELLED == GetLastError());
|
||
|
|
||
|
if (!Canceled) {
|
||
|
if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
|
||
|
(PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
|
||
|
goto NtApmDisableError;
|
||
|
}
|
||
|
|
||
|
if (!SetupDiChangeState(NtApmDevInfo, &NtApmDevInfoData)) {
|
||
|
goto NtApmDisableError;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Turn off Flags
|
||
|
//
|
||
|
NtApmTurnOnDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_PROPERTIES_CHANGE);
|
||
|
if (!SetupDiSetClassInstallParams(NtApmDevInfo, NULL, NULL, 0)) {
|
||
|
goto NtApmDisableError;
|
||
|
}
|
||
|
NtApmTurnOffDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_NODI_DEFAULTACTION);
|
||
|
NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
|
||
|
return(TRUE);
|
||
|
|
||
|
NtApmDisableError:
|
||
|
NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
|
||
|
return (FALSE);
|
||
|
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* NtApmEnable
|
||
|
*
|
||
|
* DESCRIPTION: This function is called to Enable NT APM
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL NtApmEnable()
|
||
|
{
|
||
|
DWORD ii;
|
||
|
BOOL Canceled;
|
||
|
SP_PROPCHANGE_PARAMS pcp;
|
||
|
|
||
|
HDEVINFO NtApmDevInfo;
|
||
|
SP_DEVINFO_DATA NtApmDevInfoData;
|
||
|
HWPROFILEINFO NtApmHwProfile;
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Get handles to the device and the device information
|
||
|
// (If unable to get Device Info immediately return)
|
||
|
//
|
||
|
if (!NtApmGetDevInfo(&NtApmDevInfo, &NtApmDevInfoData)) {
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Turn on the Device Interface Flags
|
||
|
//
|
||
|
NtApmTurnOnDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_NODI_DEFAULTACTION);
|
||
|
|
||
|
//
|
||
|
// Ask the class installer if the device can be generally enabled/disabled
|
||
|
//
|
||
|
pcp.StateChange = DICS_ENABLE;
|
||
|
pcp.Scope = DICS_FLAG_CONFIGGENERAL;
|
||
|
|
||
|
pcp.ClassInstallHeader.cbSize = sizeof(SP_CLASSINSTALL_HEADER);
|
||
|
pcp.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;
|
||
|
|
||
|
if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
|
||
|
(PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
|
||
|
goto NtApmEnableError;
|
||
|
}
|
||
|
|
||
|
if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE,
|
||
|
NtApmDevInfo, &NtApmDevInfoData)) {
|
||
|
goto NtApmEnableError;
|
||
|
}
|
||
|
|
||
|
Canceled = (ERROR_CANCELLED == GetLastError());
|
||
|
|
||
|
if (!Canceled) {
|
||
|
pcp.Scope = DICS_FLAG_CONFIGSPECIFIC;
|
||
|
pcp.StateChange = DICS_ENABLE;
|
||
|
|
||
|
for (ii=0; NtApmGetHwProfile(ii, &NtApmHwProfile); ii++) {
|
||
|
pcp.HwProfile = NtApmHwProfile.HWPI_ulHWProfile;
|
||
|
|
||
|
if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
|
||
|
(PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
|
||
|
goto NtApmEnableError;
|
||
|
}
|
||
|
|
||
|
if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, NtApmDevInfo, &NtApmDevInfoData)) {
|
||
|
goto NtApmEnableError;
|
||
|
}
|
||
|
|
||
|
Canceled = (ERROR_CANCELLED == GetLastError());
|
||
|
|
||
|
//
|
||
|
// If still good, keep going
|
||
|
//
|
||
|
if (!Canceled) {
|
||
|
if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
|
||
|
(PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
|
||
|
goto NtApmEnableError;
|
||
|
}
|
||
|
|
||
|
if (!SetupDiChangeState(NtApmDevInfo, &NtApmDevInfoData)) {
|
||
|
goto NtApmEnableError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// This call will start the device if it is not started
|
||
|
//
|
||
|
pcp.Scope = DICS_FLAG_GLOBAL;
|
||
|
if (!SetupDiSetClassInstallParams(NtApmDevInfo, &NtApmDevInfoData,
|
||
|
(PSP_CLASSINSTALL_HEADER)&pcp, sizeof(pcp))) {
|
||
|
goto NtApmEnableError;
|
||
|
}
|
||
|
|
||
|
if (!SetupDiChangeState(NtApmDevInfo, &NtApmDevInfoData)) {
|
||
|
goto NtApmEnableError;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NtApmTurnOnDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_PROPERTIES_CHANGE);
|
||
|
SetupDiSetClassInstallParams(NtApmDevInfo, NULL, NULL, 0);
|
||
|
NtApmTurnOffDiFlags(NtApmDevInfo, &NtApmDevInfoData, DI_NODI_DEFAULTACTION);
|
||
|
|
||
|
NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
|
||
|
return(TRUE);
|
||
|
|
||
|
NtApmEnableError:
|
||
|
NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
|
||
|
return (FALSE);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* NtApmEnabled
|
||
|
*
|
||
|
* DESCRIPTION: This function is used to determine if APM is actually
|
||
|
* Enabled or Disabled.
|
||
|
*
|
||
|
* PARAMETERS: hDlg - handle to the dialog box.
|
||
|
* fEnable - TRUE if APM is to be enabled, FALSE if APM is to
|
||
|
* be disabled.
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
NtApmEnabled()
|
||
|
{
|
||
|
DWORD Err;
|
||
|
DWORD HwProf;
|
||
|
DWORD pFlags;
|
||
|
DWORD GlobalConfigFlags;
|
||
|
|
||
|
SP_PROPCHANGE_PARAMS pcp;
|
||
|
HDEVINFO NtApmDevInfo;
|
||
|
SP_DEVINFO_DATA NtApmDevInfoData;
|
||
|
CONFIGRET CmRetVal;
|
||
|
HWPROFILEINFO HwProfileInfo;
|
||
|
TCHAR DeviceId[MAX_DEVICE_ID_LEN + 1];
|
||
|
|
||
|
//
|
||
|
// Registry Property Variables
|
||
|
//
|
||
|
DWORD RegProp;
|
||
|
DWORD RegPropType;
|
||
|
DWORD RegPropBuffSz;
|
||
|
|
||
|
//
|
||
|
// Retrieve the Handle the Device Information for APM.
|
||
|
//
|
||
|
if (!NtApmGetDevInfo(&NtApmDevInfo, &NtApmDevInfoData)) {
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the Global Flags (Just-in-case it is globally enabled)
|
||
|
//
|
||
|
RegProp = SPDRP_CONFIGFLAGS;
|
||
|
RegPropBuffSz = sizeof(RegPropBuff) + 1;
|
||
|
if (SetupDiGetDeviceRegistryProperty(NtApmDevInfo, &NtApmDevInfoData,
|
||
|
RegProp, &RegPropType,
|
||
|
RegPropBuff, RegPropBuffSz, 0))
|
||
|
{
|
||
|
if (RegPropType != REG_DWORD) {
|
||
|
GlobalConfigFlags = 0;
|
||
|
} else {
|
||
|
GlobalConfigFlags = (DWORD) RegPropBuff[0];
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Only Want the disabled bit
|
||
|
//
|
||
|
GlobalConfigFlags = GlobalConfigFlags & CONFIGFLAG_DISABLED;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the current HW Profile
|
||
|
//
|
||
|
if (!NtApmGetHwProfile(0xffffffff, &HwProfileInfo)) {
|
||
|
goto NtApmEnabledError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Get the Device ID for the given profile
|
||
|
//
|
||
|
HwProf = HwProfileInfo.HWPI_ulHWProfile;
|
||
|
CmRetVal = CM_Get_Device_ID_Ex(NtApmDevInfoData.DevInst,
|
||
|
DeviceId, sizeof(DeviceId), 0, NULL);
|
||
|
|
||
|
if (CmRetVal != CR_SUCCESS) {
|
||
|
Err = GetLastError();
|
||
|
goto NtApmEnabledError;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now get the flags
|
||
|
//
|
||
|
CmRetVal = CM_Get_HW_Prof_Flags_Ex((LPTSTR)DeviceId,
|
||
|
HwProf, &pFlags, 0, NULL);
|
||
|
|
||
|
if (CmRetVal != CR_SUCCESS) {
|
||
|
Err = GetLastError();
|
||
|
goto NtApmEnabledError;
|
||
|
}
|
||
|
|
||
|
|
||
|
NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
|
||
|
if (GlobalConfigFlags || (pFlags & CSCONFIGFLAG_DISABLED)) {
|
||
|
return(FALSE);
|
||
|
} else {
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
NtApmEnabledError:
|
||
|
NtApmCleanup(NtApmDevInfo, &NtApmDevInfoData);
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* NtApmToggle
|
||
|
*
|
||
|
* DESCRIPTION: This function gets called when the user clicks OK or Apply
|
||
|
* and does the work of enabling or disabling APM support.
|
||
|
*
|
||
|
* PARAMETERS: fEnable - Indicates if APM is to enabled or disabled
|
||
|
* SilentDisable - Do not put up dialog to reboot machine.
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL
|
||
|
NtApmToggle(
|
||
|
IN BOOL fEnable,
|
||
|
IN BOOL SilentDisable)
|
||
|
{
|
||
|
int MBoxRetVal;
|
||
|
TCHAR Str1[2048];
|
||
|
TCHAR Str2[2048];
|
||
|
|
||
|
if (fEnable == APM_ENABLE) {
|
||
|
NtApmEnable();
|
||
|
} else {
|
||
|
if (NtApmDisable()) {
|
||
|
|
||
|
if (!SilentDisable) {
|
||
|
LoadString(g_hInstance, IDS_DEVCHANGE_RESTART, (LPTSTR) Str1, ARRAYSIZE(Str1));
|
||
|
LoadString(g_hInstance, IDS_DEVCHANGE_CAPTION, (LPTSTR) Str2, ARRAYSIZE(Str2));
|
||
|
|
||
|
MBoxRetVal = MessageBox(NULL, Str1, Str2, MB_ICONQUESTION | MB_YESNO);
|
||
|
|
||
|
if (MBoxRetVal == IDYES) {
|
||
|
NtApmEnableAllPrivileges();
|
||
|
ExitWindowsEx(EWX_REBOOT | EWX_FORCEIFHUNG, 0);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Return TRUE for success, FALSE for failure
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* APMDlgHandleInit
|
||
|
*
|
||
|
* DESCRIPTION: Handles WM_INITDIALOG messages sent to APMDlgProc
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL
|
||
|
APMDlgHandleInit(
|
||
|
IN HWND hDlg,
|
||
|
IN WPARAM wParam,
|
||
|
IN LPARAM lParam)
|
||
|
{
|
||
|
|
||
|
CheckDlgButton( hDlg,
|
||
|
IDC_APMENABLE,
|
||
|
NtApmEnabled() ? BST_CHECKED : BST_UNCHECKED);
|
||
|
return(TRUE);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* APMDlgHandleCommand
|
||
|
*
|
||
|
* DESCRIPTION: Handles WM_COMMAND messages sent to APMDlgProc
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL
|
||
|
APMDlgHandleCommand(
|
||
|
IN HWND hDlg,
|
||
|
IN WPARAM wParam,
|
||
|
IN LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
BOOL RetVal;
|
||
|
WORD idCtl = LOWORD(wParam);
|
||
|
WORD wNotify = HIWORD(wParam);
|
||
|
|
||
|
//
|
||
|
// Assume there is nothing to do and return false;
|
||
|
//
|
||
|
RetVal = FALSE;
|
||
|
|
||
|
switch (idCtl) {
|
||
|
case IDC_APMENABLE:
|
||
|
if (BN_CLICKED == wNotify) {
|
||
|
//
|
||
|
// State changed. Enable the Apply button.
|
||
|
//
|
||
|
g_fDirty = TRUE;
|
||
|
PropSheet_Changed(GetParent(hDlg), hDlg);
|
||
|
}
|
||
|
|
||
|
RetVal = TRUE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return(RetVal);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* APMDlgHandleNotify
|
||
|
*
|
||
|
* DESCRIPTION: Handles WM_NOTIFY messages sent to APMDlgProc
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOL
|
||
|
APMDlgHandleNotify(
|
||
|
IN HWND hDlg,
|
||
|
IN WPARAM wParam,
|
||
|
IN LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
int idCtl = (int) wParam;
|
||
|
LPNMHDR pnmhdr = (LPNMHDR) lParam;
|
||
|
UINT uNotify = pnmhdr->code;
|
||
|
BOOL fResult;
|
||
|
|
||
|
switch (uNotify) {
|
||
|
case PSN_APPLY:
|
||
|
if (g_fDirty) {
|
||
|
if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_APMENABLE)) {
|
||
|
fResult = NtApmToggle(APM_ENABLE, FALSE);
|
||
|
} else {
|
||
|
fResult = NtApmToggle(APM_DISABLE, FALSE);
|
||
|
}
|
||
|
|
||
|
if (fResult) {
|
||
|
g_fDirty = FALSE;
|
||
|
}
|
||
|
|
||
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT,
|
||
|
fResult ? PSNRET_NOERROR : PSNRET_INVALID_NOCHANGEPAGE);
|
||
|
}
|
||
|
|
||
|
return(TRUE);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* IsNtApmPresent
|
||
|
*
|
||
|
* DESCRIPTION: This function gets called to determine if APM is present on
|
||
|
* and started on the machine. If APM is present then the
|
||
|
* tab needs to appear.
|
||
|
*
|
||
|
* This functions check for ACPI, MP and then if APM is actually
|
||
|
* on the machine. If ACPI and MP then APM may be running but is
|
||
|
* disabled.
|
||
|
*
|
||
|
* RETURNS: TRUE if APM is present, FALSE if APM is no present
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
BOOLEAN IsNtApmPresent(PSYSTEM_POWER_CAPABILITIES pspc)
|
||
|
{
|
||
|
BOOLEAN RetVal;
|
||
|
|
||
|
BOOL APMMachine;
|
||
|
BOOL ACPIMachine;
|
||
|
BOOL MPMachine;
|
||
|
|
||
|
DWORD CharBufferSize;
|
||
|
DWORD ApmStarted;
|
||
|
HKEY hPortKey;
|
||
|
SYSTEM_INFO SystemInfo;
|
||
|
|
||
|
//
|
||
|
// Assume nothing about the machine
|
||
|
//
|
||
|
ACPIMachine = FALSE;
|
||
|
MPMachine = FALSE;
|
||
|
APMMachine = FALSE;
|
||
|
CharBufferSize = sizeof(CharBuffer);
|
||
|
|
||
|
//
|
||
|
// We do the following checks:
|
||
|
//
|
||
|
// * check for ACPI
|
||
|
// * check for MP system
|
||
|
//
|
||
|
if (NtApmACPIEnabled()) {
|
||
|
ACPIMachine = TRUE;
|
||
|
|
||
|
} else {
|
||
|
GetSystemInfo(&SystemInfo);
|
||
|
if (SystemInfo.dwNumberOfProcessors > 1) {
|
||
|
MPMachine = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the machine is ACPI or MP we still need to check if APM
|
||
|
// is enabled so that we can disable it. This is a bug in APM
|
||
|
// code, but it is easiest to just fix it up here.
|
||
|
//
|
||
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||
|
m_szApmActiveKey,
|
||
|
0,
|
||
|
KEY_ALL_ACCESS,
|
||
|
&hPortKey) != ERROR_SUCCESS) {
|
||
|
|
||
|
} else if (RegQueryValueEx(hPortKey,
|
||
|
m_szApmActive,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
(PBYTE) CharBuffer,
|
||
|
&CharBufferSize) != ERROR_SUCCESS) {
|
||
|
|
||
|
RegCloseKey(hPortKey);
|
||
|
} else {
|
||
|
if (CharBuffer[0] != (TCHAR) 0) {
|
||
|
ApmStarted = (DWORD) CharBuffer[0];
|
||
|
|
||
|
if (ApmStarted != SERVICE_DISABLED) {
|
||
|
APMMachine = TRUE;
|
||
|
}
|
||
|
}
|
||
|
RegCloseKey(hPortKey);
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
// If APM is Present and Enabled it needs to be
|
||
|
// silently disabled if the machine is ACPI or MP.
|
||
|
//
|
||
|
if (ACPIMachine || MPMachine) {
|
||
|
if (APMMachine && NtApmEnabled()) {
|
||
|
NtApmToggle(APM_DISABLE, TRUE);
|
||
|
}
|
||
|
RetVal = FALSE;
|
||
|
|
||
|
} else if (APMMachine) {
|
||
|
RetVal = TRUE;
|
||
|
|
||
|
} else {
|
||
|
RetVal = FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
return(RetVal);
|
||
|
}
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* P U B L I C E N T R Y P O I N T S
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* APMDlgProc
|
||
|
*
|
||
|
* DESCRIPTION:
|
||
|
*
|
||
|
* PARAMETERS:
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
INT_PTR CALLBACK APMDlgProc(
|
||
|
IN HWND hDlg,
|
||
|
IN UINT uMsg,
|
||
|
IN WPARAM wParam,
|
||
|
IN LPARAM lParam
|
||
|
)
|
||
|
{
|
||
|
switch (uMsg) {
|
||
|
case WM_INITDIALOG:
|
||
|
return(APMDlgHandleInit(hDlg, wParam, lParam));
|
||
|
break;
|
||
|
|
||
|
case WM_COMMAND:
|
||
|
return(APMDlgHandleCommand(hDlg, wParam, lParam));
|
||
|
break;
|
||
|
|
||
|
case WM_NOTIFY:
|
||
|
return(APMDlgHandleNotify(hDlg, wParam, lParam));
|
||
|
break;
|
||
|
|
||
|
|
||
|
case WM_HELP: // F1
|
||
|
WinHelp(((LPHELPINFO)lParam)->hItemHandle, PWRMANHLP,
|
||
|
HELP_WM_HELP, (ULONG_PTR)(LPTSTR)g_NtApmHelpIDs);
|
||
|
return TRUE;
|
||
|
|
||
|
case WM_CONTEXTMENU: // right mouse click
|
||
|
WinHelp((HWND)wParam, PWRMANHLP, HELP_CONTEXTMENU, (ULONG_PTR)(LPTSTR)g_NtApmHelpIDs);
|
||
|
return TRUE;
|
||
|
|
||
|
default:
|
||
|
return(FALSE);
|
||
|
break;
|
||
|
} // switch (uMsg)
|
||
|
|
||
|
return(FALSE);
|
||
|
}
|
||
|
|
||
|
#endif
|