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.

405 lines
10 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. ci.c
  5. Abstract:
  6. Battery Class Installer
  7. Author:
  8. Scott Brenden
  9. Environment:
  10. Notes:
  11. Revision History:
  12. --*/
  13. #include "proj.h"
  14. #include <initguid.h>
  15. #include <devguid.h>
  16. BOOL APIENTRY LibMain(
  17. HANDLE hDll,
  18. DWORD dwReason,
  19. LPVOID lpReserved)
  20. {
  21. switch( dwReason ) {
  22. case DLL_PROCESS_ATTACH:
  23. TRACE_MSG (TF_FUNC, "Battery Class Installer Loaded\n");
  24. DisableThreadLibraryCalls(hDll);
  25. break;
  26. case DLL_PROCESS_DETACH:
  27. break;
  28. default:
  29. break;
  30. }
  31. return TRUE;
  32. }
  33. DWORD
  34. APIENTRY
  35. BatteryClassInstall(
  36. IN DI_FUNCTION DiFunction,
  37. IN HDEVINFO DevInfoHandle,
  38. IN PSP_DEVINFO_DATA DevInfoData OPTIONAL
  39. )
  40. /*++
  41. Routine Description:
  42. This function is the class installer entry-point.
  43. Arguments:
  44. DiFunction - Requested installation function
  45. DevInfoHandle - Handle to a device information set
  46. DevInfoData - Pointer to device information about device to install
  47. Return Value:
  48. --*/
  49. {
  50. DWORD status;
  51. SP_DEVINSTALL_PARAMS devParams;
  52. //
  53. // Get the DeviceInstallParams, because some of the InstallFunction
  54. // handlers may find some of its fields useful. Keep in mind not
  55. // to set the DeviceInstallParams using this same structure at the
  56. // end. The handlers may have called functions which would change the
  57. // DeviceInstallParams, and simply calling SetupDiSetDeviceInstallParams
  58. // with this blanket structure would destroy those settings.
  59. //
  60. devParams.cbSize = sizeof(devParams);
  61. if (!SetupDiGetDeviceInstallParams(DevInfoHandle, DevInfoData, &devParams))
  62. {
  63. status = GetLastError();
  64. } else {
  65. TRACE_MSG (TF_GENERAL, "DiFunction = %x\n", DiFunction);
  66. //
  67. // Dispatch the InstallFunction
  68. //
  69. switch (DiFunction) {
  70. case DIF_INSTALLDEVICE:
  71. status = InstallCompositeBattery (DevInfoHandle, DevInfoData, &devParams);
  72. if (status == ERROR_SUCCESS) {
  73. //
  74. // Let the default device installer actually install the battery.
  75. //
  76. status = ERROR_DI_DO_DEFAULT;
  77. }
  78. break;
  79. default:
  80. status = ERROR_DI_DO_DEFAULT;
  81. break;
  82. }
  83. }
  84. return status;
  85. }
  86. DWORD
  87. PRIVATE
  88. InstallCompositeBattery (
  89. IN HDEVINFO DevInfoHandle,
  90. IN PSP_DEVINFO_DATA DevInfoData, OPTIONAL
  91. IN OUT PSP_DEVINSTALL_PARAMS DevInstallParams
  92. )
  93. /*++
  94. Routine Description:
  95. This function installs the composite battery if it hasn't already been
  96. installed.
  97. Arguments:
  98. DevInfoHandle - Handle to a device information set
  99. DevInfoData - Pointer to device information about device to install
  100. DevInstallParams - Device install parameters associated with device
  101. Return Value:
  102. --*/
  103. {
  104. DWORD status;
  105. PSP_DEVINFO_DATA newDevInfoData;
  106. HDEVINFO newDevInfoHandle;
  107. SP_DRVINFO_DATA driverInfoData;
  108. UCHAR tmpBuffer[100];
  109. DWORD bufferLen;
  110. // DebugBreak();
  111. //
  112. // Allocate local memory for a new device info structure
  113. //
  114. if(!(newDevInfoData = LocalAlloc(LPTR, sizeof(SP_DEVINFO_DATA)))) {
  115. status = GetLastError();
  116. TRACE_MSG (TF_ERROR, "Couldn't allocate composite battery device info- %x\n", status);
  117. goto clean0;
  118. }
  119. //
  120. // Create a new device info list. Since we are "manufacturing" a completely new
  121. // device with the Composite Battery, we can't use any of the information from
  122. // the battery device list.
  123. //
  124. newDevInfoHandle = SetupDiCreateDeviceInfoList ((LPGUID)&GUID_DEVCLASS_SYSTEM, DevInstallParams->hwndParent);
  125. if (newDevInfoHandle == INVALID_HANDLE_VALUE) {
  126. status = GetLastError();
  127. TRACE_MSG (TF_ERROR, "Can't create DevInfoList - %x\n", status);
  128. goto clean1;
  129. }
  130. //
  131. // Attempt to manufacture a new device information element for the root enumerated
  132. // composite battery.
  133. //
  134. newDevInfoData->cbSize = sizeof(SP_DEVINFO_DATA);
  135. if(!SetupDiCreateDeviceInfo(newDevInfoHandle,
  136. TEXT("Root\\COMPOSITE_BATTERY\\0000"),
  137. (LPGUID)&GUID_DEVCLASS_SYSTEM,
  138. NULL,
  139. DevInstallParams->hwndParent, // same parent window as enumerated device
  140. 0,
  141. newDevInfoData)) {
  142. status = GetLastError();
  143. if (status == ERROR_DEVINST_ALREADY_EXISTS) {
  144. //
  145. // The composite battery is already installed. Our work is done.
  146. //
  147. TRACE_MSG (TF_GENERAL, "Composite Battery Already Installed\n");
  148. status = ERROR_SUCCESS;
  149. goto clean2;
  150. } else {
  151. TRACE_MSG (TF_ERROR, "Error creating composite battery devinfo - %x\n", status);
  152. goto clean2;
  153. }
  154. }
  155. //
  156. // Register the device so it is not a phantom anymore
  157. //
  158. if (!SetupDiRegisterDeviceInfo(newDevInfoHandle, newDevInfoData, 0, NULL, NULL, NULL)) {
  159. status = GetLastError();
  160. TRACE_MSG (TF_ERROR, "Couldn't register device - %x\n", status);
  161. goto clean3;
  162. }
  163. //
  164. // Set the hardware ID. For the composite battery it will be COMPOSITE_BATTERY
  165. //
  166. memset (tmpBuffer, 0, sizeof(tmpBuffer));
  167. lstrcpy (tmpBuffer, TEXT("COMPOSITE_BATTERY"));
  168. bufferLen = lstrlen(tmpBuffer) + (2 * sizeof(TCHAR));
  169. TRACE_MSG (TF_GENERAL, "tmpBuffer - %s\n with strlen = %x\n", tmpBuffer, bufferLen);
  170. status = SetupDiSetDeviceRegistryProperty (
  171. newDevInfoHandle,
  172. newDevInfoData,
  173. SPDRP_HARDWAREID,
  174. tmpBuffer,
  175. bufferLen
  176. );
  177. if (!status) {
  178. status = GetLastError();
  179. TRACE_MSG(TF_ERROR, "Couldn't set the HardwareID - %x\n", status);
  180. goto clean3;
  181. }
  182. //
  183. // Build a compatible driver list for this new device...
  184. //
  185. if(!SetupDiBuildDriverInfoList(newDevInfoHandle, newDevInfoData, SPDIT_COMPATDRIVER)) {
  186. status = GetLastError();
  187. TRACE_MSG(TF_ERROR, "Couldn't build class driver list - %x\n", status);
  188. goto clean3;
  189. }
  190. //
  191. // Select the first driver in the list as this will be the most compatible
  192. //
  193. driverInfoData.cbSize = sizeof (SP_DRVINFO_DATA);
  194. if (!SetupDiEnumDriverInfo(newDevInfoHandle, newDevInfoData, SPDIT_COMPATDRIVER, 0, &driverInfoData)) {
  195. status = GetLastError();
  196. TRACE_MSG(TF_ERROR, "Couldn't get driver list - %x\n", status);
  197. goto clean3;
  198. } else {
  199. TRACE_MSG(TF_GENERAL, "Driver info - \n"
  200. "------------- DriverType %x\n"
  201. "------------- Description %s\n"
  202. "------------- MfgName %s\n"
  203. "------------- ProviderName %s\n\n",
  204. driverInfoData.DriverType,
  205. driverInfoData.Description,
  206. driverInfoData.MfgName,
  207. driverInfoData.ProviderName);
  208. if (!SetupDiSetSelectedDriver(newDevInfoHandle, newDevInfoData, &driverInfoData)) {
  209. status = GetLastError();
  210. TRACE_MSG (TF_ERROR, "Couldn't select driver - %x\n", status);
  211. goto clean4;
  212. }
  213. }
  214. //
  215. // Install the device
  216. //
  217. if (!SetupDiInstallDevice (newDevInfoHandle, newDevInfoData)) {
  218. status = GetLastError();
  219. TRACE_MSG (TF_ERROR, "Couldn't install device - %x\n", status);
  220. goto clean4;
  221. }
  222. //
  223. // If we got here we were successful
  224. //
  225. status = ERROR_SUCCESS;
  226. SetLastError (status);
  227. goto clean1;
  228. clean4:
  229. SetupDiDestroyDriverInfoList (newDevInfoHandle, newDevInfoData, SPDIT_COMPATDRIVER);
  230. clean3:
  231. SetupDiDeleteDeviceInfo (newDevInfoHandle, newDevInfoData);
  232. clean2:
  233. SetupDiDestroyDeviceInfoList (newDevInfoHandle);
  234. clean1:
  235. LocalFree (newDevInfoData);
  236. clean0:
  237. return status;
  238. }
  239. DWORD
  240. APIENTRY
  241. BatteryClassCoInstaller (
  242. IN DI_FUNCTION InstallFunction,
  243. IN HDEVINFO DeviceInfoSet,
  244. IN PSP_DEVINFO_DATA DeviceInfoData,
  245. IN OUT PCOINSTALLER_CONTEXT_DATA Context
  246. )
  247. {
  248. SYSTEM_BATTERY_STATE batteryState;
  249. GLOBAL_POWER_POLICY powerPolicy;
  250. int i;
  251. UINT policyId;
  252. if ((InstallFunction != DIF_INSTALLDEVICE) && (InstallFunction != DIF_REMOVE)) {
  253. //
  254. // Only handle DIF_INSTALLDEVICE or DIF_REMOVE request
  255. //
  256. return (NO_ERROR);
  257. }
  258. if (!Context->PostProcessing) {
  259. //
  260. // Wait until device is installed before Adjusting levels
  261. //
  262. return (ERROR_DI_POSTPROCESSING_REQUIRED);
  263. }
  264. NtPowerInformation (SystemBatteryState, NULL, 0, &batteryState, sizeof(batteryState));
  265. if ((batteryState.BatteryPresent) && (batteryState.MaxCapacity != 0)) {
  266. //
  267. // Don't try to adjust levels if for some reason no battery was installed.
  268. //
  269. ReadGlobalPwrPolicy (&powerPolicy);
  270. if (powerPolicy.user.DischargePolicy[DISCHARGE_POLICY_CRITICAL].BatteryLevel <
  271. (100 * batteryState.DefaultAlert1)/batteryState.MaxCapacity) {
  272. //
  273. // If Critical level is less than DefaultAlert1, this idicates the settings
  274. // are messed up. Reset both the Critical and the Low setting.
  275. //
  276. powerPolicy.user.DischargePolicy[DISCHARGE_POLICY_CRITICAL].BatteryLevel =
  277. (100 * batteryState.DefaultAlert1)/batteryState.MaxCapacity;
  278. powerPolicy.user.DischargePolicy[DISCHARGE_POLICY_LOW].BatteryLevel =
  279. (100 * batteryState.DefaultAlert2)/batteryState.MaxCapacity;
  280. WriteGlobalPwrPolicy (&powerPolicy);
  281. GetActivePwrScheme (&policyId);
  282. SetActivePwrScheme (policyId, &powerPolicy, NULL);
  283. }
  284. }
  285. return (NO_ERROR);
  286. }