windows-nt/Source/XPSP1/NT/shell/osshell/cpls/batt/ci.c

406 lines
10 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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);
}