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.

607 lines
21 KiB

  1. /*
  2. * title: HidBattIOCT.cpp
  3. *
  4. * purpose: Contains misc ioctl handlers for status and query info mainly
  5. *
  6. * Initial checkin for the hid to battery class driver. This should be
  7. * the same for both Win 98 and NT 5. Alpha level source. Requires
  8. * modified composite battery driver and modified battery class driver for
  9. * Windows 98 support
  10. *
  11. */
  12. #include "hidbatt.h"
  13. /*++
  14. Routine Description:
  15. IOCTL handler. As this is an exclusive battery device, send the
  16. Irp to the battery class driver to handle battery IOCTLs.
  17. Arguments:
  18. DeviceObject - Battery for request
  19. Irp - IO request
  20. Return Value:
  21. Status of request
  22. --*/
  23. NTSTATUS
  24. HidBattIoControl(
  25. IN PDEVICE_OBJECT pDeviceObject,
  26. IN PIRP pIrp
  27. )
  28. {
  29. NTSTATUS ntStatus = STATUS_NOT_SUPPORTED;
  30. CBatteryDevExt * pDevExt;
  31. PIO_STACK_LOCATION irpSp;
  32. HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
  33. irpSp = IoGetCurrentIrpStackLocation(pIrp);
  34. HidBattPrint (HIDBATT_TRACE, ("HidBattIoctl = %x\n", irpSp->Parameters.DeviceIoControl.IoControlCode));
  35. // PrintIoctl(irpSp->Parameters.DeviceIoControl.IoControlCode);
  36. pDevExt = (CBatteryDevExt *) pDeviceObject->DeviceExtension;
  37. if (NT_SUCCESS(IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag)))
  38. {
  39. if (pDevExt->m_pBattery &&
  40. pDevExt->m_pBattery->m_pBatteryClass) {
  41. ntStatus = BatteryClassIoctl (pDevExt->m_pBattery->m_pBatteryClass, pIrp);
  42. }
  43. IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
  44. } else {
  45. ntStatus = STATUS_DEVICE_REMOVED;
  46. pIrp->IoStatus.Status = ntStatus;
  47. IoCompleteRequest(pIrp,IO_NO_INCREMENT);
  48. }
  49. if (ntStatus == STATUS_NOT_SUPPORTED)
  50. {
  51. HidBattCallLowerDriver(ntStatus, pDevExt->m_pLowerDeviceObject, pIrp);
  52. }
  53. return ntStatus;
  54. }
  55. VOID
  56. HidBattNotifyHandler (
  57. IN PVOID pContext,
  58. IN CUsage * pUsage
  59. )
  60. {
  61. HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
  62. NTSTATUS ntStatus;
  63. ULONG ulCapacityLimit = BATTERY_UNKNOWN_CAPACITY;
  64. BOOL bResult;
  65. HidBattPrint (HIDBATT_TRACE, ("HidBattNotifyHandler\n"));
  66. // called by input routine whenever a value change is noted to
  67. // a notificable usage
  68. CBatteryDevExt * pDevExt = (CBatteryDevExt *) pContext;
  69. HidBattPrint (HIDBATT_DATA, ("HidBattNotifyHandler: Usage: %x\n", pUsage->m_pProperties->m_Usage));
  70. switch (pUsage->m_pProperties->m_Usage)
  71. {
  72. case REMAINING_CAPACITY_ID:
  73. bResult = pDevExt->m_pBattery->GetSetValue(REMAINING_CAPACITY_LIMIT_INDEX,&ulCapacityLimit,FALSE);
  74. // Only send notification when capacity drops below notify level.
  75. if ((bResult) && (ulCapacityLimit != BATTERY_UNKNOWN_CAPACITY) && (pUsage->m_Value != BATTERY_UNKNOWN_CAPACITY)
  76. && (pUsage->m_Value > ulCapacityLimit)) {
  77. HidBattPrint (HIDBATT_TRACE, ("HidBattNotifyHandler:Suppressing notify\n"));
  78. break;
  79. }
  80. case AC_PRESENT_ID: // check for battery off/on line
  81. case DISCHARGING_ID:
  82. case CHARGING_ID:
  83. case BELOW_REMAINING_CAPACITY_ID:
  84. case SHUTDOWN_IMMINENT_ID:
  85. {
  86. pDevExt->m_pBattery->m_bIsCacheValid=FALSE;
  87. if (NT_SUCCESS (IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag))) {
  88. ntStatus = BatteryClassStatusNotify(
  89. pDevExt->m_pBattery->m_pBatteryClass);
  90. IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
  91. }
  92. break;
  93. }
  94. default: // nothing to notify
  95. break;
  96. }
  97. return;
  98. }
  99. NTSTATUS
  100. HidBattQueryTag (
  101. IN PVOID pContext,
  102. OUT PULONG pulBatteryTag
  103. )
  104. {
  105. HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
  106. CBatteryDevExt * pDevExt = (CBatteryDevExt *) pContext;
  107. if (!NT_SUCCESS(IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag)) )
  108. {
  109. return STATUS_NO_SUCH_DEVICE;
  110. }
  111. *pulBatteryTag = pDevExt->m_pBattery->m_Tag;
  112. IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
  113. return STATUS_SUCCESS;
  114. }
  115. NTSTATUS
  116. HidBattSetStatusNotify (
  117. IN PVOID pContext,
  118. IN ULONG BatteryTag,
  119. IN PBATTERY_NOTIFY pBatteryNotify
  120. )
  121. {
  122. bool bResult;
  123. ULONG CentiAmpSec;
  124. ULONG ulValue;
  125. HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
  126. HidBattPrint (HIDBATT_TRACE, ("HidBattSetStatusNotify \n"));
  127. CBatteryDevExt * pDevExt = (CBatteryDevExt *) pContext;
  128. CBattery * pBattery = pDevExt->m_pBattery;
  129. HidBattPrint (HIDBATT_DEBUG, ("HidBattSetStatusNotify->PowerState = %x\n", pBatteryNotify->PowerState));
  130. HidBattPrint (HIDBATT_DEBUG, ("HidBattSetStatusNotify->LowCapacity = %x\n", pBatteryNotify->LowCapacity));
  131. HidBattPrint (HIDBATT_DEBUG, ("HidBattSetStatusNotify->HighCapacity = %x\n", pBatteryNotify->HighCapacity));
  132. if (!NT_SUCCESS(IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag)))
  133. {
  134. return STATUS_NO_SUCH_DEVICE;
  135. }
  136. if (pBattery->m_Tag != BatteryTag) {
  137. IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
  138. return STATUS_NO_SUCH_DEVICE;
  139. }
  140. if ((pBatteryNotify->HighCapacity == BATTERY_UNKNOWN_CAPACITY) ||
  141. (pBatteryNotify->LowCapacity == BATTERY_UNKNOWN_CAPACITY)) {
  142. HidBattPrint (HIDBATT_DEBUG, ("HidBattSetStatusNotify failing because of BATTERY_UNKNOWN_CAPACITY.\n"));
  143. IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
  144. return STATUS_NOT_SUPPORTED;
  145. }
  146. // first check for relative or absolute
  147. if(pBattery->m_bRelative)
  148. {
  149. ulValue = pBatteryNotify->LowCapacity; // done
  150. } else
  151. {
  152. // first check if setting to zero so that can skip below formula
  153. if(pBatteryNotify->LowCapacity == 0)
  154. {
  155. ulValue = 0;
  156. } else
  157. {
  158. // first must covert value to whatever is being used by this HID device.
  159. // currently we assume either MilliVolts consistant with battery class or
  160. // AmpSecs consistant with power spec
  161. ULONG ulUnit = pBattery->GetUnit(REMAINING_CAPACITY_INDEX);
  162. if(ulUnit)
  163. {
  164. short sExponent;
  165. ULONG lMilliVolts;
  166. long milliWattHours,CentiWattHours,CentiWattSecs;
  167. sExponent = pBattery->GetExponent(REMAINING_CAPACITY_INDEX);
  168. // conversion from millWattHours to AmpSecs
  169. // formula = mWHs / 1000 / 3600 / volts ^ exponent correction
  170. lMilliVolts = pBattery->m_BatteryStatus.Voltage; // stored as MilliVolts
  171. if (lMilliVolts == 0) {
  172. HidBattPrint (HIDBATT_ERROR,
  173. ("HidBattSetStatusNotify: Error: voltage = 0, fudging with 24V.\n"));
  174. lMilliVolts = 24000;
  175. }
  176. milliWattHours = pBatteryNotify->LowCapacity;
  177. CentiWattHours = milliWattHours /10;
  178. CentiWattSecs = CentiWattHours / 3600;
  179. CentiAmpSec = (CentiWattSecs *1000)/ lMilliVolts;
  180. ulValue = CorrectExponent(CentiAmpSec,-2,sExponent);
  181. } else
  182. {
  183. ulValue = pBatteryNotify->LowCapacity;
  184. }
  185. } // end if LowCapacity
  186. } // end if relative
  187. // now set low
  188. bResult = pBattery->GetSetValue(REMAINING_CAPACITY_LIMIT_INDEX,&ulValue,TRUE);
  189. IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
  190. return bResult ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
  191. }
  192. NTSTATUS
  193. HidBattDisableStatusNotify (
  194. IN PVOID pContext
  195. )
  196. {
  197. HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
  198. CBatteryDevExt * pDevExt = (CBatteryDevExt *) pContext;
  199. pDevExt->m_pBattery->m_pBatteryNotify = NULL; // remove notify procedure
  200. return STATUS_SUCCESS;
  201. }
  202. /*++
  203. Routine Description:
  204. Called by the class driver to retrieve the batteries current status
  205. The battery class driver will serialize all requests it issues to
  206. the miniport for a given battery.
  207. Arguments:
  208. Context - Miniport context value for battery
  209. BatteryTag - Tag of current battery
  210. BatteryStatus - Pointer to structure to return the current battery status
  211. Return Value:
  212. Success if there is a battery currently installed, else no such device.
  213. --*/
  214. NTSTATUS
  215. HidBattQueryStatus (
  216. IN PVOID pContext,
  217. IN ULONG BatteryTag,
  218. OUT PBATTERY_STATUS pBatteryStatus
  219. )
  220. {
  221. HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
  222. CBatteryDevExt * pDevExt = (CBatteryDevExt *) pContext;
  223. NTSTATUS ntStatus;
  224. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryStatus - Tag (%d)\n",
  225. BatteryTag));
  226. if (!NT_SUCCESS(IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag)) )
  227. {
  228. return STATUS_NO_SUCH_DEVICE;
  229. }
  230. if ((BatteryTag == BATTERY_TAG_INVALID) || (pDevExt->m_pBattery->m_Tag == BATTERY_TAG_INVALID)) {
  231. ntStatus = STATUS_NO_SUCH_DEVICE;
  232. } else {
  233. RtlZeroMemory (pBatteryStatus, sizeof(BATTERY_STATUS));
  234. ntStatus = pDevExt->m_pBattery->RefreshStatus();
  235. if (NT_SUCCESS(ntStatus)) {
  236. RtlCopyMemory (pBatteryStatus, &pDevExt->m_pBattery->m_BatteryStatus, sizeof(BATTERY_STATUS));
  237. HidBattPrint (HIDBATT_DATA, ("HidBattQueryStatus - Data (%08x)(%08x)(%08x)(%08x)\n",
  238. pBatteryStatus->PowerState,
  239. pBatteryStatus->Capacity,
  240. pBatteryStatus->Rate,
  241. pBatteryStatus->Voltage ));
  242. } else {
  243. ntStatus = STATUS_NO_SUCH_DEVICE;
  244. HidBattPrint (HIDBATT_DATA, ("HidBattQueryStatus - Error\n" ));
  245. }
  246. }
  247. IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
  248. return ntStatus;
  249. }
  250. /*++
  251. Routine Description:
  252. Called by the class driver to retrieve battery information
  253. The battery class driver will serialize all requests it issues to
  254. the miniport for a given battery.
  255. We return invalid parameter when we can't handle a request for a
  256. specific level of information. This is defined in the battery class spec.
  257. Arguments:
  258. Context - Miniport context value for battery
  259. BatteryTag - Tag of current battery
  260. Level - type of information required
  261. AtRate - Optional Parameter
  262. Buffer - Location for the information
  263. BufferLength - Length in bytes of the buffer
  264. ReturnedLength - Length in bytes of the returned data
  265. Return Value:
  266. Success if there is a battery currently installed, else no such device.
  267. --*/
  268. NTSTATUS
  269. HidBattQueryInformation (
  270. IN PVOID Context,
  271. IN ULONG BatteryTag,
  272. IN BATTERY_QUERY_INFORMATION_LEVEL Level,
  273. IN LONG AtRate OPTIONAL,
  274. OUT PVOID Buffer,
  275. IN ULONG BufferLength,
  276. OUT PULONG ReturnedLength
  277. )
  278. {
  279. CBatteryDevExt * pDevExt = (CBatteryDevExt *) Context;
  280. ULONG ulResult;
  281. NTSTATUS ntStatus;
  282. PVOID pReturnBuffer;
  283. ULONG ulReturnBufferLength;
  284. WCHAR scratchBuffer[MAX_BATTERY_STRING_SIZE];
  285. WCHAR buffer2[MAX_BATTERY_STRING_SIZE];
  286. UNICODE_STRING tmpUnicodeString;
  287. UNICODE_STRING unicodeString;
  288. ANSI_STRING ansiString;
  289. bool bResult;
  290. BATTERY_REMAINING_SCALE ScalePtr[2];
  291. ULONG ulReturn,ulNewValue;
  292. ULONG ulEstTimeStub = 5;
  293. HIDDebugBreak(HIDBATT_BREAK_ALWAYS);
  294. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Tag (%d)\n",
  295. BatteryTag));
  296. if (!NT_SUCCESS(IoAcquireRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag)) )
  297. {
  298. return STATUS_NO_SUCH_DEVICE;
  299. }
  300. //
  301. // If caller has the wrong ID give an error
  302. //
  303. if (BatteryTag == BATTERY_TAG_INVALID ||
  304. pDevExt->m_pBattery->m_Tag == BATTERY_TAG_INVALID ||
  305. BatteryTag != pDevExt->m_pBattery->m_Tag)
  306. {
  307. IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
  308. return STATUS_NO_SUCH_DEVICE;
  309. }
  310. ulResult = 0;
  311. pReturnBuffer = NULL;
  312. ulReturnBufferLength = 0;
  313. ntStatus = STATUS_SUCCESS;
  314. CUString cUniqueID;
  315. SHORT sExponent;
  316. char * pTemp;
  317. //
  318. // Get the info requested
  319. //
  320. switch (Level) {
  321. case BatteryInformation:
  322. //
  323. // This data structure is populated by CmBattVerifyStaticInfo
  324. //
  325. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Battery Info\n"));
  326. pReturnBuffer = (PVOID) &pDevExt->m_pBattery->m_BatteryInfo;
  327. ulReturnBufferLength = sizeof (pDevExt->m_pBattery->m_BatteryInfo);
  328. break;
  329. case BatteryGranularityInformation:
  330. //
  331. // Get the granularity from the static info structure
  332. // This data structure is populated by CmBattVerifyStaticInfo
  333. //
  334. {
  335. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Granularity\n"));
  336. bResult = pDevExt->m_pBattery->GetSetValue(GRANULARITY1_INDEX, &ulReturn,FALSE);
  337. if(!pDevExt->m_pBattery->m_bRelative)
  338. {
  339. // convert from amps to watts
  340. sExponent = pDevExt->m_pBattery->GetExponent(GRANULARITY1_INDEX);
  341. ulNewValue = CorrectExponent(ulReturn,sExponent,-2);
  342. ulReturn= CentiAmpSecsToMilliWattHours(ulNewValue,pDevExt->m_pBattery->m_BatteryStatus.Voltage);
  343. }
  344. ScalePtr[0].Granularity = bResult ? ulReturn : 0;
  345. bResult = pDevExt->m_pBattery->GetSetValue(GRANULARITY2_INDEX, &ulReturn,FALSE);
  346. if(!pDevExt->m_pBattery->m_bRelative)
  347. {
  348. // convert from amps to watts
  349. sExponent = pDevExt->m_pBattery->GetExponent(GRANULARITY2_INDEX);
  350. ulNewValue = CorrectExponent(ulReturn,sExponent,-2);
  351. ulReturn= CentiAmpSecsToMilliWattHours(ulNewValue,pDevExt->m_pBattery->m_BatteryStatus.Voltage);
  352. }
  353. ScalePtr[1].Granularity = bResult ? ulReturn : 0;
  354. bResult = pDevExt->m_pBattery->GetSetValue(WARNING_CAPACITY_LIMIT_INDEX, &ulReturn,FALSE);
  355. if(!pDevExt->m_pBattery->m_bRelative)
  356. {
  357. // convert from amps to watts
  358. sExponent = pDevExt->m_pBattery->GetExponent(WARNING_CAPACITY_LIMIT_INDEX);
  359. ulNewValue = CorrectExponent(ulReturn,sExponent,-2);
  360. ulReturn= CentiAmpSecsToMilliWattHours(ulNewValue,pDevExt->m_pBattery->m_BatteryStatus.Voltage);
  361. }
  362. ScalePtr[0].Capacity = bResult ? ulReturn : 0;
  363. bResult = pDevExt->m_pBattery->GetSetValue(DESIGN_CAPACITY_INDEX, &ulReturn,FALSE);
  364. if(!pDevExt->m_pBattery->m_bRelative)
  365. {
  366. // convert from amps to watts
  367. sExponent = pDevExt->m_pBattery->GetExponent(DESIGN_CAPACITY_INDEX);
  368. ulNewValue = CorrectExponent(ulReturn,sExponent,-2);
  369. ulReturn= CentiAmpSecsToMilliWattHours(ulNewValue,pDevExt->m_pBattery->m_BatteryStatus.Voltage);
  370. }
  371. ScalePtr[1].Capacity = bResult ? ulReturn : 0;
  372. pReturnBuffer = ScalePtr;
  373. ulReturnBufferLength = 2 * sizeof (BATTERY_REMAINING_SCALE);
  374. }
  375. break;
  376. case BatteryTemperature:
  377. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Temperature\n"));
  378. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  379. break;
  380. case BatteryEstimatedTime:
  381. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Estimated time\n"));
  382. bResult = pDevExt->m_pBattery->GetSetValue(RUNTIME_TO_EMPTY_INDEX, &ulReturn,FALSE);
  383. if(!bResult)
  384. {
  385. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  386. } else
  387. {
  388. SHORT exponent;
  389. exponent = pDevExt->m_pBattery->GetExponent(RUNTIME_TO_EMPTY_INDEX);
  390. ulReturn = CorrectExponent (ulReturn, exponent, 0);
  391. pReturnBuffer = &ulReturn;
  392. ulReturnBufferLength = sizeof (ULONG);
  393. }
  394. break;
  395. case BatteryDeviceName:
  396. //
  397. // Model Number must be returned as a wide string
  398. //
  399. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Device Name\n"));
  400. if(pDevExt->m_pBattery->m_pProduct)
  401. {
  402. pReturnBuffer = pDevExt->m_pBattery->m_pProduct->m_String.Buffer;
  403. ulReturnBufferLength = pDevExt->m_pBattery->m_pProduct->m_String.Length;
  404. }
  405. break;
  406. case BatteryManufactureDate:
  407. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Mfr Date\n"));
  408. if(!pDevExt->m_pBattery->m_ManufactureDate.Day)
  409. {
  410. ntStatus = STATUS_INVALID_DEVICE_REQUEST;
  411. break;
  412. }
  413. pReturnBuffer = &pDevExt->m_pBattery->m_ManufactureDate;
  414. ulReturnBufferLength = sizeof(pDevExt->m_pBattery->m_ManufactureDate);
  415. break;
  416. case BatteryManufactureName:
  417. //
  418. // Oem Info must be returned as wide string
  419. //
  420. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Mfr Name\n"));
  421. if(pDevExt->m_pBattery->m_pManufacturer)
  422. {
  423. pReturnBuffer = pDevExt->m_pBattery->m_pManufacturer->m_String.Buffer;
  424. ulReturnBufferLength = pDevExt->m_pBattery->m_pManufacturer->m_String.Length;
  425. }
  426. break;
  427. case BatteryUniqueID:
  428. //
  429. // Concatenate the serial #, manufacturer name, and Product //
  430. // start off with serial number
  431. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Unique ID\n"));
  432. if(pDevExt->m_pBattery->m_pSerialNumber) {
  433. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Serial = %s\n", pDevExt->m_pBattery->m_pSerialNumber));
  434. cUniqueID.Append(pDevExt->m_pBattery->m_pSerialNumber);
  435. } else {
  436. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Serial = NULL\n"));
  437. CUString * pSTemp = new (NonPagedPool, HidBattTag) CUString(L"1000");
  438. if (pSTemp) {
  439. cUniqueID.Append(pSTemp);
  440. delete pSTemp;
  441. }
  442. }
  443. if(pDevExt->m_pBattery->m_pManufacturer)
  444. cUniqueID.Append(pDevExt->m_pBattery->m_pManufacturer); // add mfr name
  445. else
  446. {
  447. CUString * pSTemp = new (NonPagedPool, HidBattTag) CUString(L"Mfr");
  448. if (pSTemp) {
  449. cUniqueID.Append(pSTemp);
  450. delete pSTemp;
  451. }
  452. }
  453. if(pDevExt->m_pBattery->m_pProduct)
  454. cUniqueID.Append(pDevExt->m_pBattery->m_pProduct); // add Product
  455. else
  456. {
  457. CUString * pSTemp = new (NonPagedPool, HidBattTag) CUString(L"Prod");
  458. if (pSTemp) {
  459. cUniqueID.Append(pSTemp);
  460. delete pSTemp;
  461. }
  462. }
  463. pReturnBuffer = cUniqueID.m_String.Buffer;
  464. ulReturnBufferLength = cUniqueID.m_String.Length;
  465. break;
  466. default:
  467. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Default\n"));
  468. ntStatus = STATUS_INVALID_PARAMETER;
  469. break;
  470. }
  471. //
  472. // Done, return buffer if needed
  473. //
  474. *ReturnedLength = ulReturnBufferLength;
  475. if (BufferLength < ulReturnBufferLength) {
  476. ntStatus = STATUS_BUFFER_TOO_SMALL;
  477. }
  478. if (NT_SUCCESS(ntStatus) && pReturnBuffer) {
  479. RtlCopyMemory (Buffer, pReturnBuffer, ulReturnBufferLength); // Copy what's needed
  480. }
  481. HidBattPrint (HIDBATT_TRACE, ("HidBattQueryInformation - Status = %08x Buffer = %08x\n", ntStatus, *(PULONG)Buffer));
  482. IoReleaseRemoveLock (&pDevExt->m_StopLock, (PVOID) HidBattTag);
  483. return ntStatus;
  484. }
  485. NTSTATUS
  486. HidBattIoCompletion(
  487. IN PDEVICE_OBJECT pDeviceObject,
  488. IN PIRP pIrp,
  489. IN PVOID pdoIoCompletedEvent
  490. )
  491. {
  492. HidBattPrint (HIDBATT_TRACE, ("HidBattIoCompletion\n"));
  493. KeSetEvent((KEVENT *) pdoIoCompletedEvent,0, FALSE);
  494. return STATUS_MORE_PROCESSING_REQUIRED;
  495. }