406 lines
10 KiB
C
406 lines
10 KiB
C
|
|
|||
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
ci.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Battery Class Installer
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Scott Brenden
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
|
|||
|
#include "proj.h"
|
|||
|
|
|||
|
#include <initguid.h>
|
|||
|
#include <devguid.h>
|
|||
|
|
|||
|
|
|||
|
BOOL APIENTRY LibMain(
|
|||
|
HANDLE hDll,
|
|||
|
DWORD dwReason,
|
|||
|
LPVOID lpReserved)
|
|||
|
{
|
|||
|
|
|||
|
switch( dwReason ) {
|
|||
|
case DLL_PROCESS_ATTACH:
|
|||
|
|
|||
|
TRACE_MSG (TF_FUNC, "Battery Class Installer Loaded\n");
|
|||
|
DisableThreadLibraryCalls(hDll);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case DLL_PROCESS_DETACH:
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
APIENTRY
|
|||
|
BatteryClassInstall(
|
|||
|
IN DI_FUNCTION DiFunction,
|
|||
|
IN HDEVINFO DevInfoHandle,
|
|||
|
IN PSP_DEVINFO_DATA DevInfoData OPTIONAL
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function is the class installer entry-point.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DiFunction - Requested installation function
|
|||
|
|
|||
|
DevInfoHandle - Handle to a device information set
|
|||
|
|
|||
|
DevInfoData - Pointer to device information about device to install
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD status;
|
|||
|
SP_DEVINSTALL_PARAMS devParams;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Get the DeviceInstallParams, because some of the InstallFunction
|
|||
|
// handlers may find some of its fields useful. Keep in mind not
|
|||
|
// to set the DeviceInstallParams using this same structure at the
|
|||
|
// end. The handlers may have called functions which would change the
|
|||
|
// DeviceInstallParams, and simply calling SetupDiSetDeviceInstallParams
|
|||
|
// with this blanket structure would destroy those settings.
|
|||
|
//
|
|||
|
|
|||
|
devParams.cbSize = sizeof(devParams);
|
|||
|
if (!SetupDiGetDeviceInstallParams(DevInfoHandle, DevInfoData, &devParams))
|
|||
|
{
|
|||
|
status = GetLastError();
|
|||
|
|
|||
|
} else {
|
|||
|
TRACE_MSG (TF_GENERAL, "DiFunction = %x\n", DiFunction);
|
|||
|
|
|||
|
//
|
|||
|
// Dispatch the InstallFunction
|
|||
|
//
|
|||
|
|
|||
|
switch (DiFunction) {
|
|||
|
case DIF_INSTALLDEVICE:
|
|||
|
status = InstallCompositeBattery (DevInfoHandle, DevInfoData, &devParams);
|
|||
|
if (status == ERROR_SUCCESS) {
|
|||
|
//
|
|||
|
// Let the default device installer actually install the battery.
|
|||
|
//
|
|||
|
|
|||
|
status = ERROR_DI_DO_DEFAULT;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
|
|||
|
default:
|
|||
|
status = ERROR_DI_DO_DEFAULT;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
PRIVATE
|
|||
|
InstallCompositeBattery (
|
|||
|
IN HDEVINFO DevInfoHandle,
|
|||
|
IN PSP_DEVINFO_DATA DevInfoData, OPTIONAL
|
|||
|
IN OUT PSP_DEVINSTALL_PARAMS DevInstallParams
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function installs the composite battery if it hasn't already been
|
|||
|
installed.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DevInfoHandle - Handle to a device information set
|
|||
|
|
|||
|
DevInfoData - Pointer to device information about device to install
|
|||
|
|
|||
|
DevInstallParams - Device install parameters associated with device
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD status;
|
|||
|
PSP_DEVINFO_DATA newDevInfoData;
|
|||
|
HDEVINFO newDevInfoHandle;
|
|||
|
SP_DRVINFO_DATA driverInfoData;
|
|||
|
UCHAR tmpBuffer[100];
|
|||
|
DWORD bufferLen;
|
|||
|
|
|||
|
|
|||
|
// DebugBreak();
|
|||
|
|
|||
|
//
|
|||
|
// Allocate local memory for a new device info structure
|
|||
|
//
|
|||
|
|
|||
|
if(!(newDevInfoData = LocalAlloc(LPTR, sizeof(SP_DEVINFO_DATA)))) {
|
|||
|
status = GetLastError();
|
|||
|
TRACE_MSG (TF_ERROR, "Couldn't allocate composite battery device info- %x\n", status);
|
|||
|
goto clean0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Create a new device info list. Since we are "manufacturing" a completely new
|
|||
|
// device with the Composite Battery, we can't use any of the information from
|
|||
|
// the battery device list.
|
|||
|
//
|
|||
|
|
|||
|
newDevInfoHandle = SetupDiCreateDeviceInfoList ((LPGUID)&GUID_DEVCLASS_SYSTEM, DevInstallParams->hwndParent);
|
|||
|
if (newDevInfoHandle == INVALID_HANDLE_VALUE) {
|
|||
|
status = GetLastError();
|
|||
|
TRACE_MSG (TF_ERROR, "Can't create DevInfoList - %x\n", status);
|
|||
|
goto clean1;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Attempt to manufacture a new device information element for the root enumerated
|
|||
|
// composite battery.
|
|||
|
//
|
|||
|
|
|||
|
newDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
|
|||
|
if(!SetupDiCreateDeviceInfo(newDevInfoHandle,
|
|||
|
TEXT("Root\\COMPOSITE_BATTERY\\0000"),
|
|||
|
(LPGUID)&GUID_DEVCLASS_SYSTEM,
|
|||
|
NULL,
|
|||
|
DevInstallParams->hwndParent, // same parent window as enumerated device
|
|||
|
0,
|
|||
|
newDevInfoData)) {
|
|||
|
|
|||
|
status = GetLastError();
|
|||
|
|
|||
|
if (status == ERROR_DEVINST_ALREADY_EXISTS) {
|
|||
|
//
|
|||
|
// The composite battery is already installed. Our work is done.
|
|||
|
//
|
|||
|
|
|||
|
TRACE_MSG (TF_GENERAL, "Composite Battery Already Installed\n");
|
|||
|
status = ERROR_SUCCESS;
|
|||
|
goto clean2;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
TRACE_MSG (TF_ERROR, "Error creating composite battery devinfo - %x\n", status);
|
|||
|
goto clean2;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Register the device so it is not a phantom anymore
|
|||
|
//
|
|||
|
|
|||
|
if (!SetupDiRegisterDeviceInfo(newDevInfoHandle, newDevInfoData, 0, NULL, NULL, NULL)) {
|
|||
|
status = GetLastError();
|
|||
|
TRACE_MSG (TF_ERROR, "Couldn't register device - %x\n", status);
|
|||
|
goto clean3;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Set the hardware ID. For the composite battery it will be COMPOSITE_BATTERY
|
|||
|
//
|
|||
|
|
|||
|
memset (tmpBuffer, 0, sizeof(tmpBuffer));
|
|||
|
lstrcpy (tmpBuffer, TEXT("COMPOSITE_BATTERY"));
|
|||
|
|
|||
|
bufferLen = lstrlen(tmpBuffer) + (2 * sizeof(TCHAR));
|
|||
|
TRACE_MSG (TF_GENERAL, "tmpBuffer - %s\n with strlen = %x\n", tmpBuffer, bufferLen);
|
|||
|
|
|||
|
status = SetupDiSetDeviceRegistryProperty (
|
|||
|
newDevInfoHandle,
|
|||
|
newDevInfoData,
|
|||
|
SPDRP_HARDWAREID,
|
|||
|
tmpBuffer,
|
|||
|
bufferLen
|
|||
|
);
|
|||
|
|
|||
|
if (!status) {
|
|||
|
status = GetLastError();
|
|||
|
TRACE_MSG(TF_ERROR, "Couldn't set the HardwareID - %x\n", status);
|
|||
|
goto clean3;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Build a compatible driver list for this new device...
|
|||
|
//
|
|||
|
|
|||
|
if(!SetupDiBuildDriverInfoList(newDevInfoHandle, newDevInfoData, SPDIT_COMPATDRIVER)) {
|
|||
|
status = GetLastError();
|
|||
|
TRACE_MSG(TF_ERROR, "Couldn't build class driver list - %x\n", status);
|
|||
|
goto clean3;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Select the first driver in the list as this will be the most compatible
|
|||
|
//
|
|||
|
|
|||
|
driverInfoData.cbSize = sizeof (SP_DRVINFO_DATA);
|
|||
|
if (!SetupDiEnumDriverInfo(newDevInfoHandle, newDevInfoData, SPDIT_COMPATDRIVER, 0, &driverInfoData)) {
|
|||
|
status = GetLastError();
|
|||
|
TRACE_MSG(TF_ERROR, "Couldn't get driver list - %x\n", status);
|
|||
|
goto clean3;
|
|||
|
|
|||
|
} else {
|
|||
|
TRACE_MSG(TF_GENERAL, "Driver info - \n"
|
|||
|
"------------- DriverType %x\n"
|
|||
|
"------------- Description %s\n"
|
|||
|
"------------- MfgName %s\n"
|
|||
|
"------------- ProviderName %s\n\n",
|
|||
|
driverInfoData.DriverType,
|
|||
|
driverInfoData.Description,
|
|||
|
driverInfoData.MfgName,
|
|||
|
driverInfoData.ProviderName);
|
|||
|
if (!SetupDiSetSelectedDriver(newDevInfoHandle, newDevInfoData, &driverInfoData)) {
|
|||
|
status = GetLastError();
|
|||
|
TRACE_MSG (TF_ERROR, "Couldn't select driver - %x\n", status);
|
|||
|
goto clean4;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Install the device
|
|||
|
//
|
|||
|
|
|||
|
if (!SetupDiInstallDevice (newDevInfoHandle, newDevInfoData)) {
|
|||
|
status = GetLastError();
|
|||
|
TRACE_MSG (TF_ERROR, "Couldn't install device - %x\n", status);
|
|||
|
goto clean4;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// If we got here we were successful
|
|||
|
//
|
|||
|
|
|||
|
status = ERROR_SUCCESS;
|
|||
|
SetLastError (status);
|
|||
|
goto clean1;
|
|||
|
|
|||
|
|
|||
|
clean4:
|
|||
|
SetupDiDestroyDriverInfoList (newDevInfoHandle, newDevInfoData, SPDIT_COMPATDRIVER);
|
|||
|
|
|||
|
clean3:
|
|||
|
SetupDiDeleteDeviceInfo (newDevInfoHandle, newDevInfoData);
|
|||
|
|
|||
|
clean2:
|
|||
|
SetupDiDestroyDeviceInfoList (newDevInfoHandle);
|
|||
|
|
|||
|
clean1:
|
|||
|
LocalFree (newDevInfoData);
|
|||
|
|
|||
|
clean0:
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
DWORD
|
|||
|
APIENTRY
|
|||
|
BatteryClassCoInstaller (
|
|||
|
IN DI_FUNCTION InstallFunction,
|
|||
|
IN HDEVINFO DeviceInfoSet,
|
|||
|
IN PSP_DEVINFO_DATA DeviceInfoData,
|
|||
|
IN OUT PCOINSTALLER_CONTEXT_DATA Context
|
|||
|
)
|
|||
|
{
|
|||
|
SYSTEM_BATTERY_STATE batteryState;
|
|||
|
GLOBAL_POWER_POLICY powerPolicy;
|
|||
|
int i;
|
|||
|
UINT policyId;
|
|||
|
|
|||
|
if ((InstallFunction != DIF_INSTALLDEVICE) && (InstallFunction != DIF_REMOVE)) {
|
|||
|
//
|
|||
|
// Only handle DIF_INSTALLDEVICE or DIF_REMOVE request
|
|||
|
//
|
|||
|
|
|||
|
return (NO_ERROR);
|
|||
|
}
|
|||
|
|
|||
|
if (!Context->PostProcessing) {
|
|||
|
//
|
|||
|
// Wait until device is installed before Adjusting levels
|
|||
|
//
|
|||
|
|
|||
|
return (ERROR_DI_POSTPROCESSING_REQUIRED);
|
|||
|
}
|
|||
|
|
|||
|
NtPowerInformation (SystemBatteryState, NULL, 0, &batteryState, sizeof(batteryState));
|
|||
|
if ((batteryState.BatteryPresent) && (batteryState.MaxCapacity != 0)) {
|
|||
|
//
|
|||
|
// Don't try to adjust levels if for some reason no battery was installed.
|
|||
|
//
|
|||
|
|
|||
|
ReadGlobalPwrPolicy (&powerPolicy);
|
|||
|
|
|||
|
if (powerPolicy.user.DischargePolicy[DISCHARGE_POLICY_CRITICAL].BatteryLevel <
|
|||
|
(100 * batteryState.DefaultAlert1)/batteryState.MaxCapacity) {
|
|||
|
//
|
|||
|
// If Critical level is less than DefaultAlert1, this idicates the settings
|
|||
|
// are messed up. Reset both the Critical and the Low setting.
|
|||
|
//
|
|||
|
|
|||
|
powerPolicy.user.DischargePolicy[DISCHARGE_POLICY_CRITICAL].BatteryLevel =
|
|||
|
(100 * batteryState.DefaultAlert1)/batteryState.MaxCapacity;
|
|||
|
powerPolicy.user.DischargePolicy[DISCHARGE_POLICY_LOW].BatteryLevel =
|
|||
|
(100 * batteryState.DefaultAlert2)/batteryState.MaxCapacity;
|
|||
|
|
|||
|
WriteGlobalPwrPolicy (&powerPolicy);
|
|||
|
GetActivePwrScheme (&policyId);
|
|||
|
SetActivePwrScheme (policyId, &powerPolicy, NULL);
|
|||
|
}
|
|||
|
}
|
|||
|
return (NO_ERROR);
|
|||
|
}
|