/*++ Copyright (c) 1990 Microsoft Corporation Module Name: ci.c Abstract: Battery Class Installer Author: Scott Brenden Environment: Notes: Revision History: --*/ #include "proj.h" #include #include #ifdef DEBUG DWORD BattDebugPrintLevel = TF_ERROR | TF_WARNING; #endif 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; // // 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 // status = SetupDiSetDeviceRegistryProperty ( newDevInfoHandle, newDevInfoData, SPDRP_HARDWAREID, TEXT("COMPOSITE_BATTERY\0"), sizeof(TEXT("COMPOSITE_BATTERY\0")) ); 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; NTSTATUS Status; int i; UINT policyId; DWORD RetVal; 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); } RetVal = NO_ERROR; Status = NtPowerInformation (SystemBatteryState, NULL, 0, &batteryState, sizeof(batteryState)); if (NT_SUCCESS(Status)) { if ((batteryState.BatteryPresent) && (batteryState.MaxCapacity != 0)) { // // Don't try to adjust levels if for some reason no battery was installed. // if (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; // // commit the fixed settings. // if (!WriteGlobalPwrPolicy (&powerPolicy)) { RetVal = GetLastError(); } // // now make sure we commit these settings to the current policy as well. // if (GetActivePwrScheme (&policyId)) { if (!SetActivePwrScheme (policyId, &powerPolicy, NULL)) { RetVal = GetLastError(); } } else { RetVal = GetLastError(); } } } } } else { RetVal = ERROR_INTERNAL_ERROR; } return(RetVal); }