CompBattOpenClose(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PAGED_CODE();
+ if (CompBattDebug & 0x100) DbgPrint("CompBatt: ENTERING OpenClose\n");
+
+ /* Complete the IRP with success */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ /* Return success */
+ if (CompBattDebug & 0x100) DbgPrint("CompBatt: Exiting OpenClose\n");
+ return STATUS_SUCCESS;
}
NTSTATUS
CompBattSystemControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+ NTSTATUS Status;
+ PAGED_CODE();
+ if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING System Control\n");
+
+ /* Are we attached yet? */
+ if (DeviceExtension->AttachedDevice)
+ {
+ /* Send it up the stack */
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
+ }
+ else
+ {
+ /* We don't support WMI */
+ Status = STATUS_NOT_SUPPORTED;
+ Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ /* Return status */
+ return Status;
}
NTSTATUS
NTSTATUS
NTAPI
-CompBattMonitorIrpCompleteWorker(IN PCOMPBATT_BATTERY_ENTRY BatteryData)
+CompBattMonitorIrpCompleteWorker(IN PCOMPBATT_BATTERY_DATA BatteryData)
{
UNIMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
-NTSTATUS
+VOID
NTAPI
CompBattRecalculateTag(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PCOMPBATT_BATTERY_DATA BatteryData;
+ ULONG Tag;
+ PLIST_ENTRY ListHead, NextEntry;
+ if (CompBattDebug & 0x100) DbgPrint("CompBatt: ENTERING CompBattRecalculateTag\n");
+
+ /* Loop the battery list */
+ ExAcquireFastMutex(&DeviceExtension->Lock);
+ ListHead = &DeviceExtension->BatteryList;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the battery information and check if it has a tag */
+ BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
+ if (BatteryData->Flags & COMPBATT_TAG_ASSIGNED)
+ {
+ /* Generate the next tag and exit */
+ Tag = DeviceExtension->NextTag;
+ DeviceExtension->Flags |= COMPBATT_TAG_ASSIGNED;
+ DeviceExtension->Tag = Tag;
+ DeviceExtension->NextTag = Tag + 1;
+ break;
+ }
+
+ /* No tag for this device extension, clear it */
+ DeviceExtension->Tag = 0;
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* We're done */
+ ExReleaseFastMutex(&DeviceExtension->Lock);
+ if (CompBattDebug & 0x100) DbgPrint("CompBatt: EXITING CompBattRecalculateTag\n");
}
NTSTATUS
CompBattIoctl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PCOMPBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+ NTSTATUS Status;
+ if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING Ioctl\n");
+
+ /* Let the class driver handle it */
+ Status = BatteryClassIoctl(DeviceExtension->ClassData, Irp);
+ if (Status == STATUS_NOT_SUPPORTED)
+ {
+ /* It failed, try the next driver up the stack */
+ Irp->IoStatus.Status = Status;
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
+ }
+
+ /* Return status */
+ if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING Ioctl\n");
+ return Status;
}
NTSTATUS
CompBattQueryTag(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
OUT PULONG Tag)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status;
+ PAGED_CODE();
+ if (CompBattDebug & 0x100) DbgPrint("CompBatt: ENTERING QueryTag\n");
+
+ /* Was a tag assigned? */
+ if (!(DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED))
+ {
+ /* Assign one */
+ CompBattRecalculateTag(DeviceExtension);
+ }
+
+ /* Do we have a tag now? */
+ if ((DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED) && (DeviceExtension->Tag))
+ {
+ /* Return the tag */
+ *Tag = DeviceExtension->Tag;
+ Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ /* No tag */
+ *Tag = 0;
+ Status = STATUS_NO_SUCH_DEVICE;
+ }
+
+ /* Return status */
+ if (CompBattDebug & 0x100) DbgPrint("CompBatt: EXITING QueryTag\n");
+ return Status;
}
NTSTATUS
NTAPI
CompBattDisableStatusNotify(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PCOMPBATT_BATTERY_DATA BatteryData;
+ PLIST_ENTRY ListHead, NextEntry;
+ if (CompBattDebug & 0x100) DbgPrint("CompBatt: ENTERING DisableStatusNotify\n");
+
+ /* Loop the battery list */
+ ExAcquireFastMutex(&DeviceExtension->Lock);
+ ListHead = &DeviceExtension->BatteryList;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Get the battery information and clear capacity data */
+ BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
+ BatteryData->WaitStatus.LowCapacity = 0;
+ BatteryData->WaitStatus.HighCapacity = 0x7FFFFFFF;
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Done */
+ ExReleaseFastMutex(&DeviceExtension->Lock);
+ if (CompBattDebug & 0x100) DbgPrint("CompBatt: EXITING DisableStatusNotify\n");
+ return STATUS_SUCCESS;
}
NTSTATUS
NTSTATUS
NTAPI
-CompBattGetBatteryInformation(OUT PBATTERY_INFORMATION BatteryInformation,
+CompBattGetBatteryInformation(OUT PBATTERY_INFORMATION BatteryInfo,
IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status = STATUS_SUCCESS;
+ BATTERY_QUERY_INFORMATION InputBuffer;
+ PCOMPBATT_BATTERY_DATA BatteryData;
+ PLIST_ENTRY ListHead, NextEntry;
+ if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING GetBatteryInformation\n");
+
+ /* Set defaults */
+ BatteryInfo->DefaultAlert1 = 0;
+ BatteryInfo->DefaultAlert2 = 0;
+ BatteryInfo->CriticalBias = 0;
+
+ /* Loop the battery list */
+ ExAcquireFastMutex(&DeviceExtension->Lock);
+ ListHead = &DeviceExtension->BatteryList;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Try to acquire the remove lock */
+ BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
+ if (NT_SUCCESS(IoAcquireRemoveLock(&BatteryData->RemoveLock, 0)))
+ {
+ /* Now release the device lock since the battery can't go away */
+ ExReleaseFastMutex(&DeviceExtension->Lock);
+
+ /* Build the query */
+ InputBuffer.BatteryTag = BatteryData->Tag;
+ InputBuffer.InformationLevel = BatteryInformation;
+ InputBuffer.AtRate = 0;
+
+ /* Make sure the battery has a tag */
+ if (BatteryData->Tag)
+ {
+ /* Do we already have the data? */
+ if (!(BatteryData->Flags & COMPBATT_BATTERY_INFORMATION_PRESENT))
+ {
+ /* Send the IOCTL to query the information */
+ RtlZeroMemory(&BatteryData->BatteryInformation,
+ sizeof(BatteryData->BatteryInformation));
+ Status = BatteryIoctl(IOCTL_BATTERY_QUERY_INFORMATION,
+ BatteryData->DeviceObject,
+ &InputBuffer,
+ sizeof(InputBuffer),
+ &BatteryData->BatteryInformation,
+ sizeof(BatteryData->BatteryInformation),
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail if the query had a problem */
+ if (Status == STATUS_DEVICE_REMOVED) Status = STATUS_NO_SUCH_DEVICE;
+ ExAcquireFastMutex(&DeviceExtension->Lock);
+ IoReleaseRemoveLock(&BatteryData->RemoveLock, 0);
+ break;
+ }
+
+ /* Next time we can use the static copy */
+ BatteryData->Flags |= COMPBATT_BATTERY_INFORMATION_PRESENT;
+ if (CompBattDebug & 2)
+ DbgPrint("CompBattGetBatteryInformation: Read individual BATTERY_INFORMATION\n"
+ "-------- Capabilities = %x\n-------- Technology = %x\n"
+ "-------- Chemistry[4] = %x\n-------- DesignedCapacity = %x\n"
+ "-------- FullChargedCapacity = %x\n-------- DefaultAlert1 = %x\n"
+ "-------- DefaultAlert2 = %x\n-------- CriticalBias = %x\n"
+ "-------- CycleCount = %x\n",
+ BatteryData->BatteryInformation.Capabilities,
+ BatteryData->BatteryInformation.Technology,
+ BatteryData->BatteryInformation.Chemistry,
+ BatteryData->BatteryInformation.DesignedCapacity,
+ BatteryData->BatteryInformation.FullChargedCapacity,
+ BatteryData->BatteryInformation.DefaultAlert1,
+ BatteryData->BatteryInformation.DefaultAlert2,
+ BatteryData->BatteryInformation.CriticalBias,
+ BatteryData->BatteryInformation.CycleCount);
+ }
+
+ /* Combine capabilities */
+ BatteryInfo->Capabilities |= BatteryData->BatteryInformation.Capabilities;
+
+ /* Add-on capacity */
+ if (BatteryData->BatteryInformation.DesignedCapacity != BATTERY_UNKNOWN_CAPACITY)
+ {
+ BatteryInfo->DesignedCapacity += BatteryData->BatteryInformation.DesignedCapacity;
+ }
+
+ /* Add on fully charged capacity */
+ if (BatteryData->BatteryInformation.FullChargedCapacity != BATTERY_UNKNOWN_CAPACITY)
+ {
+ BatteryInfo->FullChargedCapacity += BatteryData->BatteryInformation.FullChargedCapacity;
+ }
+
+ /* Choose the highest alert */
+ BatteryInfo->DefaultAlert1 = max(BatteryInfo->DefaultAlert1,
+ BatteryData->BatteryInformation.DefaultAlert1);
+
+ /* Choose the highest alert */
+ BatteryInfo->DefaultAlert2 = max(BatteryInfo->DefaultAlert2,
+ BatteryData->BatteryInformation.DefaultAlert2);
+
+ /* Choose the highest critical bias */
+ BatteryInfo->CriticalBias = max(BatteryInfo->CriticalBias,
+ BatteryData->BatteryInformation.CriticalBias);
+ }
+
+ /* Re-acquire the device extension lock and release the remove lock */
+ ExAcquireFastMutex(&DeviceExtension->Lock);
+ IoReleaseRemoveLock(&BatteryData->RemoveLock, 0);
+ }
+
+ /* Next entry */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* We are done with the list, check if the information was queried okay */
+ ExReleaseFastMutex(&DeviceExtension->Lock);
+ if (NT_SUCCESS(Status))
+ {
+ /* If there's no fully charged capacity, use the design capacity */
+ if (!BatteryInfo->FullChargedCapacity)
+ {
+ BatteryInfo->FullChargedCapacity = BatteryInfo->DesignedCapacity;
+ }
+
+ /* Print out final combined data */
+ if (CompBattDebug & 2)
+ DbgPrint("CompBattGetBatteryInformation: Returning BATTERY_INFORMATION\n"
+ "-------- Capabilities = %x\n-------- Technology = %x\n"
+ "-------- Chemistry[4] = %x\n-------- DesignedCapacity = %x\n"
+ "-------- FullChargedCapacity = %x\n-------- DefaultAlert1 = %x\n"
+ "-------- DefaultAlert2 = %x\n-------- CriticalBias = %x\n"
+ "-------- CycleCount = %x\n",
+ BatteryInfo->Capabilities,
+ BatteryInfo->Technology,
+ BatteryInfo->Chemistry,
+ BatteryInfo->DesignedCapacity,
+ BatteryInfo->FullChargedCapacity,
+ BatteryInfo->DefaultAlert1,
+ BatteryInfo->DefaultAlert2,
+ BatteryInfo->CriticalBias,
+ BatteryInfo->CycleCount);
+
+ /* Copy the data into the device extension */
+ RtlCopyMemory(&DeviceExtension->BatteryInformation,
+ BatteryInfo,
+ sizeof(DeviceExtension->BatteryInformation));
+ DeviceExtension->Flags |= COMPBATT_BATTERY_INFORMATION_PRESENT;
+ }
+
+ /* We are done */
+ if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING GetBatteryInformation\n");
+ return Status;
}
NTSTATUS
CompBattGetBatteryGranularity(OUT PBATTERY_REPORTING_SCALE ReportingScale,
IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status = STATUS_SUCCESS;
+ BATTERY_QUERY_INFORMATION InputBuffer;
+ PCOMPBATT_BATTERY_DATA BatteryData;
+ BATTERY_REPORTING_SCALE BatteryScale[4];
+ PLIST_ENTRY ListHead, NextEntry;
+ ULONG i;
+ if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING GetBatteryGranularity\n");
+
+ /* Set defaults */
+ ReportingScale[0].Granularity = -1;
+ ReportingScale[1].Granularity = -1;
+ ReportingScale[2].Granularity = -1;
+ ReportingScale[3].Granularity = -1;
+
+ /* Loop the battery list */
+ ExAcquireFastMutex(&DeviceExtension->Lock);
+ ListHead = &DeviceExtension->BatteryList;
+ NextEntry = ListHead->Flink;
+ while (NextEntry != ListHead)
+ {
+ /* Try to acquire the remove lock */
+ BatteryData = CONTAINING_RECORD(NextEntry, COMPBATT_BATTERY_DATA, BatteryLink);
+ if (NT_SUCCESS(IoAcquireRemoveLock(&BatteryData->RemoveLock, 0)))
+ {
+ /* Now release the device lock since the battery can't go away */
+ ExReleaseFastMutex(&DeviceExtension->Lock);
+
+ /* Build the query */
+ InputBuffer.BatteryTag = BatteryData->Tag;
+ InputBuffer.InformationLevel = BatteryGranularityInformation;
+
+ /* Make sure the battery has a tag */
+ if (BatteryData->Tag)
+ {
+ /* Send the IOCTL to query the information */
+ RtlZeroMemory(&BatteryData->BatteryInformation,
+ sizeof(BatteryData->BatteryInformation));
+ Status = BatteryIoctl(IOCTL_BATTERY_QUERY_INFORMATION,
+ BatteryData->DeviceObject,
+ &InputBuffer,
+ sizeof(InputBuffer),
+ &BatteryScale,
+ sizeof(BatteryScale),
+ 0);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail if the query had a problem */
+ ExAcquireFastMutex(&DeviceExtension->Lock);
+ IoReleaseRemoveLock(&BatteryData->RemoveLock, 0);
+ break;
+ }
+
+ /* Loop all 4 scales */
+ for (i = 0; i < 4; i++)
+ {
+ /* Check for valid granularity */
+ if (BatteryScale[i].Granularity)
+ {
+ /* If it's smaller, use it instead */
+ ReportingScale[i].Granularity = min(BatteryScale[i].Granularity,
+ ReportingScale[i].Granularity);
+ }
+
+ }
+ }
+
+ /* Re-acquire the device extension lock and release the remove lock */
+ ExAcquireFastMutex(&DeviceExtension->Lock);
+ IoReleaseRemoveLock(&BatteryData->RemoveLock, 0);
+ }
+
+ /* Next entry */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* All done */
+ ExReleaseFastMutex(&DeviceExtension->Lock);
+ if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING GetBatteryGranularity\n");
+ return STATUS_SUCCESS;
}
NTSTATUS
NTSTATUS
NTAPI
-CompBattQueryInformation(IN PCOMPBATT_DEVICE_EXTENSION FdoExtension,
+CompBattQueryInformation(IN PCOMPBATT_DEVICE_EXTENSION DeviceExtension,
IN ULONG Tag,
IN BATTERY_QUERY_INFORMATION_LEVEL InfoLevel,
IN OPTIONAL LONG AtRate,
IN ULONG BufferLength,
OUT PULONG ReturnedLength)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ BATTERY_INFORMATION BatteryInfo;
+ BATTERY_REPORTING_SCALE BatteryGranularity[4];
+ PWCHAR BatteryName = L"Composite Battery";
+ BATTERY_MANUFACTURE_DATE Date;
+ ULONG Dummy, Time;
+ PVOID QueryData = NULL;
+ ULONG QueryLength = 0;
+ NTSTATUS Status = STATUS_SUCCESS;
+ PAGED_CODE();
+ if (CompBattDebug & 1) DbgPrint("CompBatt: ENTERING QueryInformation\n");
+
+ /* Check for valid/correct tag */
+ if ((Tag != DeviceExtension->Tag) ||
+ (!(DeviceExtension->Flags & COMPBATT_TAG_ASSIGNED)))
+ {
+ /* Not right, so fail */
+ return STATUS_NO_SUCH_DEVICE;
+ }
+
+ /* Check what caller wants */
+ switch (InfoLevel)
+ {
+ case BatteryInformation:
+
+ /* Query combined battery information */
+ RtlZeroMemory(&BatteryInfo, sizeof(BatteryInfo));
+ Status = CompBattGetBatteryInformation(&BatteryInfo, DeviceExtension);
+ if (NT_SUCCESS(Status))
+ {
+ /* Return the data if successful */
+ QueryData = &BatteryInfo;
+ QueryLength = sizeof(BatteryInfo);
+ }
+ break;
+
+ case BatteryGranularityInformation:
+
+ /* Query combined granularity information */
+ RtlZeroMemory(&BatteryGranularity, sizeof(BatteryGranularity));
+ Status = CompBattGetBatteryGranularity(BatteryGranularity, DeviceExtension);
+ if (NT_SUCCESS(Status))
+ {
+ /* Return the data if successful */
+ QueryLength = sizeof(BatteryGranularity);
+ QueryData = &BatteryGranularity;
+ }
+ break;
+
+ case BatteryEstimatedTime:
+
+ /* Query combined time estimate information */
+ RtlZeroMemory(&Time, sizeof(Time));
+ Status = CompBattGetEstimatedTime(&Time, DeviceExtension);
+ if (NT_SUCCESS(Status))
+ {
+ /* Return the data if successful */
+ QueryLength = sizeof(Time);
+ QueryData = &Time;
+ }
+ break;
+
+ case BatteryManufactureName:
+ case BatteryDeviceName:
+
+ /* Return the static buffer */
+ QueryData = BatteryName;
+ QueryLength = sizeof(L"Composite Battery");
+ break;
+
+ case BatteryManufactureDate:
+
+ /* Static data */
+ Date.Day = 26;
+ Date.Month = 06;
+ Date.Year = 1997;
+ break;
+
+ case BatteryTemperature:
+ case BatteryUniqueID:
+
+ /* Return zero */
+ Dummy = 0;
+ QueryData = &Dummy;
+ QueryLength = sizeof(Dummy);
+ break;
+
+ default:
+
+ /* Everything else is unknown */
+ Status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+
+ /* Return the required length and check if the caller supplied enough */
+ *ReturnedLength = QueryLength;
+ if (BufferLength < QueryLength) Status = STATUS_BUFFER_TOO_SMALL;
+
+ /* Copy the data if there's enough space and it exists */
+ if ((NT_SUCCESS(Status)) && (QueryData)) RtlCopyMemory(Buffer, QueryData, QueryLength);
+
+ /* Return function result */
+ if (CompBattDebug & 1) DbgPrint("CompBatt: EXITING QueryInformation\n");
+ return Status;
}
NTSTATUS
DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ /* Register add device routine */
+ DriverObject->DriverExtension->AddDevice = CompBattAddDevice;
+
+ /* Register other handlers */
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = CompBattOpenClose;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = CompBattOpenClose;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = CompBattIoctl;
+ DriverObject->MajorFunction[IRP_MJ_POWER] = CompBattPowerDispatch;
+ DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = CompBattSystemControl;
+ DriverObject->MajorFunction[IRP_MJ_PNP] = CompBattPnpDispatch;
+ return STATUS_SUCCESS;
}
/* EOF */