/* FUNCTIONS ******************************************************************/
+VOID
+NTAPI
+CmBattWaitWakeLoop(IN PDEVICE_OBJECT DeviceObject,
+ IN UCHAR MinorFunction,
+ IN POWER_STATE PowerState,
+ IN PVOID Context,
+ IN PIO_STATUS_BLOCK IoStatusBlock)
+{
+ NTSTATUS Status;
+ PCMBATT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+ if (CmBattDebug & 0x20) DbgPrint("CmBattWaitWakeLoop: Entered.\n");
+
+ /* Check for success */
+ if ((NT_SUCCESS(IoStatusBlock->Status)) && (DeviceExtension->WaitWakeEnable))
+ {
+ /* Request a new power IRP */
+ if (CmBattDebug & 2) DbgPrint("CmBattWaitWakeLoop: completed successfully\n");
+ Status = PoRequestPowerIrp(DeviceObject,
+ MinorFunction,
+ PowerState,
+ CmBattWaitWakeLoop,
+ Context,
+ &DeviceExtension->PowerIrp);
+ if (CmBattDebug & 2)
+ DbgPrint("CmBattWaitWakeLoop: PoRequestPowerIrp: status = 0x%08x.\n",
+ Status);
+ }
+ else
+ {
+ /* Clear the power IRP, we failed */
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattWaitWakeLoop: failed: status = 0x%08x.\n",
+ IoStatusBlock->Status);
+ DeviceExtension->PowerIrp = NULL;
+ }
+}
+
NTSTATUS
NTAPI
-CmBattIoCompletion(PDEVICE_OBJECT DeviceObject,
- PIRP Irp,
- PKEVENT Event)
+CmBattIoCompletion(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ IN PKEVENT Event)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ if (CmBattDebug & 2) DbgPrint("CmBattIoCompletion: Event (%x)\n", Event);
+
+ /* Set the completion event */
+ KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
+ return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
NTAPI
-CmBattGetAcpiInterfaces(PDEVICE_OBJECT DeviceObject,
- PACPI_INTERFACE_STANDARD2 *AcpiInterface)
+CmBattGetAcpiInterfaces(IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PACPI_INTERFACE_STANDARD AcpiInterface)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PIRP Irp;
+ NTSTATUS Status;
+ PIO_STACK_LOCATION IoStackLocation;
+ KEVENT Event;
+
+ /* Allocate the IRP */
+ Irp = IoAllocateIrp(DeviceObject->StackSize, 0);
+ if (!Irp)
+ {
+ /* Fail */
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattGetAcpiInterfaces: Failed to allocate Irp\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Set default error code */
+ Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+
+ /* Build the query */
+ IoStackLocation = IoGetNextIrpStackLocation(Irp);
+ IoStackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE;
+ IoStackLocation->Parameters.QueryInterface.InterfaceType = &GUID_ACPI_INTERFACE_STANDARD;
+ IoStackLocation->Parameters.QueryInterface.Size = sizeof(ACPI_INTERFACE_STANDARD);
+ IoStackLocation->Parameters.QueryInterface.Version = 1;
+ IoStackLocation->Parameters.QueryInterface.Interface = (PINTERFACE)AcpiInterface;
+ IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData = NULL;
+
+ /* Set default ACPI interface data */
+ AcpiInterface->Size = sizeof(ACPI_INTERFACE_STANDARD);
+ AcpiInterface->Version = 1;
+
+ /* Initialize our wait event */
+ KeInitializeEvent(&Event, SynchronizationEvent, 0);
+
+ /* Set the completion routine */
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+ IoSetCompletionRoutine(Irp,
+ (PVOID)CmBattIoCompletion,
+ &Event,
+ TRUE,
+ TRUE,
+ TRUE);
+
+ /* Now call ACPI */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait for completion */
+ KeWaitForSingleObject(&Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = Irp->IoStatus.Status;
+ }
+
+ /* Free the IRP */
+ IoFreeIrp(Irp);
+
+ /* Return status */
+ if (!(NT_SUCCESS(Status)) && (CmBattDebug & 0xC))
+ DbgPrint("CmBattGetAcpiInterfaces: Could not get ACPI driver interfaces, status = %x\n", Status);
+ return Status;
}
VOID
NTAPI
-CmBattDestroyFdo(PDEVICE_OBJECT DeviceObject)
+CmBattDestroyFdo(IN PDEVICE_OBJECT DeviceObject)
{
- UNIMPLEMENTED;
+ PAGED_CODE();
+ if (CmBattDebug & 0x220) DbgPrint("CmBattDestroyFdo, Battery.\n");
+
+ /* Delete the device */
+ IoDeleteDevice(DeviceObject);
+ if (CmBattDebug & 0x220) DbgPrint("CmBattDestroyFdo: done.\n");
}
NTSTATUS
NTAPI
-CmBattRemoveDevice(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+CmBattRemoveDevice(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PCMBATT_DEVICE_EXTENSION DeviceExtension;
+ PVOID Context;
+ DeviceExtension = DeviceObject->DeviceExtension;
+ if (CmBattDebug & 2)
+ DbgPrint("CmBattRemoveDevice: CmBatt (%x), Type %d, _UID %d\n",
+ DeviceExtension,
+ DeviceExtension->FdoType,
+ DeviceExtension->DeviceId);
+
+ /* Make sure it's safe to go ahead */
+ IoReleaseRemoveLockAndWait(&DeviceExtension->RemoveLock, 0);
+
+ /* Check for pending power IRP */
+ if (DeviceExtension->PowerIrp)
+ {
+ /* Cancel and clear */
+ IoCancelIrp(DeviceExtension->PowerIrp);
+ DeviceExtension->PowerIrp = NULL;
+ }
+
+ /* Check what type of FDO is being removed */
+ Context = DeviceExtension->AcpiInterface.Context;
+ if (DeviceExtension->FdoType == CmBattBattery)
+ {
+ /* Unregister battery FDO */
+ DeviceExtension->AcpiInterface.UnregisterForDeviceNotifications(Context,
+ (PVOID)CmBattNotifyHandler);
+ CmBattWmiDeRegistration(DeviceExtension);
+ if (!NT_SUCCESS(BatteryClassUnload(DeviceExtension->ClassData))) ASSERT(FALSE);
+ }
+ else
+ {
+ /* Unregister AC adapter FDO */
+ DeviceExtension->AcpiInterface.UnregisterForDeviceNotifications(Context,
+ (PVOID)CmBattNotifyHandler);
+ CmBattWmiDeRegistration(DeviceExtension);
+ AcAdapterPdo = NULL;
+ }
+
+ /* Detach and delete */
+ IoDetachDevice(DeviceExtension->AttachedDevice);
+ IoDeleteDevice(DeviceExtension->DeviceObject);
+ return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
-CmBattPowerDispatch(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+CmBattPowerDispatch(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PIO_STACK_LOCATION IoStackLocation;
+ PCMBATT_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+ if (CmBattDebug & 0x210) DbgPrint("CmBattPowerDispatch\n");
+
+ /* Get stack location and device extension */
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ DeviceExtension = DeviceObject->DeviceExtension;
+ switch (IoStackLocation->MinorFunction)
+ {
+ case IRP_MN_WAIT_WAKE:
+ if (CmBattDebug & 0x10)
+ DbgPrint("CmBattPowerDispatch: IRP_MN_WAIT_WAKE\n");
+ break;
+
+ case IRP_MN_POWER_SEQUENCE:
+ if (CmBattDebug & 0x10)
+ DbgPrint("CmBattPowerDispatch: IRP_MN_POWER_SEQUENCE\n");
+ break;
+
+ case IRP_MN_QUERY_POWER:
+ if (CmBattDebug & 0x10)
+ DbgPrint("CmBattPowerDispatch: IRP_MN_WAIT_WAKE\n");
+ break;
+
+ case IRP_MN_SET_POWER:
+ if (CmBattDebug & 0x10)
+ DbgPrint("CmBattPowerDispatch: IRP_MN_SET_POWER type: %d, State: %d \n",
+ IoStackLocation->Parameters.Power.Type,
+ IoStackLocation->Parameters.Power.State);
+ break;
+
+ default:
+
+ if (CmBattDebug & 1)
+ DbgPrint("CmBattPowerDispatch: minor %d\n", IoStackLocation->MinorFunction);
+ break;
+ }
+
+ /* Start the next IRP and see if we're attached */
+ PoStartNextPowerIrp(Irp);
+ if (DeviceExtension->AttachedDevice)
+ {
+ /* Call ACPI */
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = PoCallDriver(DeviceExtension->AttachedDevice, Irp);
+ }
+ else
+ {
+ /* Complete the request here */
+ Status = Irp->IoStatus.Status;
+ IofCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ /* Return status */
+ return Status;
}
NTSTATUS
NTAPI
-CmBattCreateFdo(PDRIVER_OBJECT DriverObject,
- PDEVICE_OBJECT DeviceObject,
- ULONG DeviceExtensionSize,
- PDEVICE_OBJECT *NewDeviceObject)
+CmBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PIO_STACK_LOCATION IoStackLocation;
+ PCMBATT_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+ KEVENT Event;
+ PAGED_CODE();
+
+ /* Get stack location and device extension */
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ DeviceExtension = DeviceObject->DeviceExtension;
+
+ /* Set default error */
+ Status = STATUS_NOT_SUPPORTED;
+
+ /* Try to acquire the lock before doing anything */
+ Status = IoAcquireRemoveLock(&DeviceExtension->RemoveLock, 0);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Complete the request */
+ Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
+ IofCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_DEVICE_REMOVED;
+ }
+
+ /* What's the operation? */
+ switch (IoStackLocation->MinorFunction)
+ {
+ case IRP_MN_QUERY_PNP_DEVICE_STATE:
+
+ /* Initialize our wait event */
+ KeInitializeEvent(&Event, SynchronizationEvent, 0);
+
+ /* Set the completion routine */
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+ IoSetCompletionRoutine(Irp,
+ (PVOID)CmBattIoCompletion,
+ &Event,
+ TRUE,
+ TRUE,
+ TRUE);
+
+ /* Now call ACPI to inherit its PnP Device State */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait for completion */
+ KeWaitForSingleObject(&Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = Irp->IoStatus.Status;
+ }
+
+ /* However, a battery CAN be disabled */
+ Irp->IoStatus.Information &= ~PNP_DEVICE_NOT_DISABLEABLE;
+
+ /* Release the remove lock and complete the request */
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
+ return Status;
+
+ case IRP_MN_SURPRISE_REMOVAL:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_SURPRISE_REMOVAL\n");
+
+ /* Lock the device extension and set the handle count to invalid */
+ ExAcquireFastMutex(&DeviceExtension->FastMutex);
+ DeviceExtension->HandleCount = -1;
+ ExReleaseFastMutex(&DeviceExtension->FastMutex);
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IRP_MN_START_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_START_DEVICE\n");
+
+ /* Mark the extension as started */
+ if (DeviceExtension->FdoType == CmBattBattery) DeviceExtension->Started = TRUE;
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IRP_MN_STOP_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_STOP_DEVICE\n");
+
+ /* Mark the extension as stopped */
+ if (DeviceExtension->FdoType == CmBattBattery) DeviceExtension->Started = FALSE;
+ Status = STATUS_SUCCESS;
+ break;
+
+ case IRP_MN_QUERY_REMOVE_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_REMOVE_DEVICE\n");
+
+ /* Lock the extension and get the current handle count */
+ ExAcquireFastMutex(&DeviceExtension->FastMutex);
+ if (DeviceExtension->HandleCount == 0)
+ {
+ /* No handles. Mark it as invalid since it'll be removed */
+ DeviceExtension->HandleCount = -1;
+ Status = STATUS_SUCCESS;
+ }
+ else if (DeviceExtension->HandleCount == -1)
+ {
+ /* Don't do anything, but this is strange since it's already removed */
+ Status = STATUS_SUCCESS;
+ if (CmBattDebug & 4)
+ DbgPrint("CmBattPnpDispatch: Recieved two consecutive QUERY_REMOVE requests.\n");
+ }
+ else
+ {
+ /* Fail because there's still open handles */
+ Status = STATUS_UNSUCCESSFUL;
+ }
+
+ /* Release the lock and return */
+ ExReleaseFastMutex(&DeviceExtension->FastMutex);
+ break;
+
+ case IRP_MN_REMOVE_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_REMOVE_DEVICE\n");
+
+ /* Call the remove code */
+ Status = CmBattRemoveDevice(DeviceObject, Irp);
+ break;
+
+ case IRP_MN_CANCEL_REMOVE_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_REMOVE_DEVICE\n");
+
+ /* Lock the extension and get the handle count */
+ ExAcquireFastMutex(&DeviceExtension->FastMutex);
+ if (DeviceExtension->HandleCount == -1)
+ {
+ /* A remove was in progress, set the handle count back to 0 */
+ DeviceExtension->HandleCount = 0;
+ }
+ else if (CmBattDebug & 2)
+ {
+ /* Nop, but warn about it */
+ DbgPrint("CmBattPnpDispatch: Received CANCEL_REMOVE when OpenCount == %x\n",
+ DeviceExtension->HandleCount);
+ }
+
+ /* Return success in all cases, and release the lock */
+ Status = STATUS_SUCCESS;
+ ExReleaseFastMutex(&DeviceExtension->FastMutex);
+ break;
+
+ case IRP_MN_QUERY_STOP_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_STOP_DEVICE\n");
+
+ /* There's no real support for this */
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case IRP_MN_CANCEL_STOP_DEVICE:
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_CANCEL_STOP_DEVICE\n");
+
+ /* There's no real support for this */
+ Status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case IRP_MN_QUERY_CAPABILITIES:
+
+ /* Initialize our wait event */
+ KeInitializeEvent(&Event, SynchronizationEvent, 0);
+
+ /* Set the completion routine */
+ IoCopyCurrentIrpStackLocationToNext(Irp);
+ IoSetCompletionRoutine(Irp,
+ (PVOID)CmBattIoCompletion,
+ &Event,
+ TRUE,
+ TRUE,
+ TRUE);
+
+ /* Now call ACPI */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait for completion */
+ KeWaitForSingleObject(&Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = Irp->IoStatus.Status;
+ }
+
+ /* Get the wake power state */
+ DeviceExtension->PowerState.SystemState = IoStackLocation->Parameters.DeviceCapabilities.Capabilities->SystemWake;
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES %d Capabilities->SystemWake = %x\n",
+ DeviceExtension->FdoType,
+ DeviceExtension->PowerState);
+
+ /* Check if it's invalid */
+ if (DeviceExtension->PowerState.SystemState == PowerSystemUnspecified)
+ {
+ /* Wait wake is not supported in this scenario */
+ DeviceExtension->WaitWakeEnable = FALSE;
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES Wake not supported.\n");
+ }
+ else if (!(DeviceExtension->PowerIrp) &&
+ (DeviceExtension->WaitWakeEnable))
+ {
+ /* If it was requested in the registry, request the power IRP for it */
+ PoRequestPowerIrp(DeviceExtension->DeviceObject,
+ 0,
+ DeviceExtension->PowerState,
+ CmBattWaitWakeLoop,
+ 0,
+ &DeviceExtension->PowerIrp);
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: IRP_MN_QUERY_CAPABILITIES wait/Wake irp sent.\n");
+ }
+
+ /* Release the remove lock and complete the request */
+ IofCompleteRequest(Irp, IO_NO_INCREMENT);
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
+ return Status;
+
+ default:
+ /* Unsupported */
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattPnpDispatch: Unimplemented minor %0x\n",
+ IoStackLocation->MinorFunction);
+ break;
+ }
+
+ /* Release the remove lock */
+ IoReleaseRemoveLock(&DeviceExtension->RemoveLock, Irp);
+
+ /* Set IRP status if we have one */
+ if (Status != STATUS_NOT_SUPPORTED) Irp->IoStatus.Status = Status;
+
+ /* Did someone pick it up? */
+ if ((NT_SUCCESS(Status)) || (Status == STATUS_NOT_SUPPORTED))
+ {
+ /* Still unsupported, try ACPI */
+ IoSkipCurrentIrpStackLocation(Irp);
+ Status = IoCallDriver(DeviceExtension->AttachedDevice, Irp);
+ }
+ else
+ {
+ /* Complete the request */
+ Status = Irp->IoStatus.Status;
+ IofCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ /* Release the remove lock and return status */
+ return Status;
}
NTSTATUS
NTAPI
-CmBattPnpDispatch(PDEVICE_OBJECT DeviceObject,
- PIRP Irp)
+CmBattCreateFdo(IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG DeviceExtensionSize,
+ IN PDEVICE_OBJECT *NewDeviceObject)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PDEVICE_OBJECT FdoDeviceObject;
+ HANDLE KeyHandle;
+ PCMBATT_DEVICE_EXTENSION FdoExtension;
+ UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
+ PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)Buffer;
+ NTSTATUS Status;
+ UNICODE_STRING KeyString;
+ ULONG UniqueId;
+ ULONG ResultLength;
+ PAGED_CODE();
+ if (CmBattDebug & 0x220) DbgPrint("CmBattCreateFdo: Entered\n");
+
+ /* Get unique ID */
+ Status = CmBattGetUniqueId(DeviceObject, &UniqueId);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Assume 0 */
+ UniqueId = 0;
+ if (CmBattDebug & 2)
+ DbgPrint("CmBattCreateFdo: Error %x from _UID, assuming unit #0\n", Status);
+ }
+
+ /* Create the FDO */
+ Status = IoCreateDevice(DriverObject,
+ DeviceExtensionSize,
+ 0,
+ FILE_DEVICE_BATTERY,
+ FILE_DEVICE_SECURE_OPEN,
+ 0,
+ &FdoDeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail */
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattCreateFdo: error (0x%x) creating device object\n", Status);
+ return Status;
+ }
+
+ /* Set FDO flags */
+ FdoDeviceObject->Flags |= DO_BUFFERED_IO;
+ FdoDeviceObject->Flags |= DO_MAP_IO_BUFFER;
+ FdoDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+
+ /* Initialize the extension */
+ FdoExtension = FdoDeviceObject->DeviceExtension;
+ RtlZeroMemory(FdoExtension, DeviceExtensionSize);
+ FdoExtension->DeviceObject = FdoDeviceObject;
+ FdoExtension->FdoDeviceObject = FdoDeviceObject;
+ FdoExtension->PdoDeviceObject = DeviceObject;
+
+ /* Attach to ACPI */
+ FdoExtension->AttachedDevice = IoAttachDeviceToDeviceStack(FdoDeviceObject,
+ DeviceObject);
+ if (!FdoExtension->AttachedDevice)
+ {
+ /* Destroy and fail */
+ CmBattDestroyFdo(FdoExtension->FdoDeviceObject);
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattCreateFdo: IoAttachDeviceToDeviceStack failed.\n");
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Get ACPI interface for EVAL */
+ Status = CmBattGetAcpiInterfaces(FdoExtension->AttachedDevice,
+ &FdoExtension->AcpiInterface);
+ if (!FdoExtension->AttachedDevice)
+ {
+ /* Detach, destroy, and fail */
+ IoDetachDevice(FdoExtension->AttachedDevice);
+ CmBattDestroyFdo(FdoExtension->FdoDeviceObject);
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattCreateFdo: Could not get ACPI interfaces: %x\n", Status);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Setup the rest of the extension */
+ ExInitializeFastMutex(&FdoExtension->FastMutex);
+ IoInitializeRemoveLock(&FdoExtension->RemoveLock, 0, 0, 0);
+ FdoExtension->HandleCount = 0;
+ FdoExtension->WaitWakeEnable = FALSE;
+ FdoExtension->DeviceId = UniqueId;
+ FdoExtension->DeviceName = NULL;
+ FdoExtension->DelayNotification = FALSE;
+ FdoExtension->ArFlag = 0;
+
+ /* Open the device key */
+ Status = IoOpenDeviceRegistryKey(DeviceObject,
+ PLUGPLAY_REGKEY_DEVICE,
+ KEY_READ,
+ &KeyHandle);
+ if (NT_SUCCESS(Status))
+ {
+ /* Read wait wake value */
+ RtlInitUnicodeString(&KeyString, L"WaitWakeEnabled");
+ Status = ZwQueryValueKey(KeyHandle,
+ &KeyString,
+ KeyValuePartialInformation,
+ PartialInfo,
+ sizeof(Buffer),
+ &ResultLength);
+ if (NT_SUCCESS(Status))
+ {
+ /* Set value */
+ FdoExtension->WaitWakeEnable = *(PULONG)PartialInfo->Data;
+ }
+
+ /* Close the handle */
+ ZwClose(KeyHandle);
+ }
+
+ /* Return success and the new FDO */
+ *NewDeviceObject = FdoDeviceObject;
+ if (CmBattDebug & 0x220)
+ DbgPrint("CmBattCreateFdo: Created FDO %x\n", FdoDeviceObject);
+ return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
-CmBattAddBattery(PDRIVER_OBJECT DriverObject,
- PDEVICE_OBJECT DeviceObject)
+CmBattAddBattery(IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ BATTERY_MINIPORT_INFO MiniportInfo;
+ NTSTATUS Status;
+ PDEVICE_OBJECT FdoDeviceObject;
+ PCMBATT_DEVICE_EXTENSION FdoExtension;
+ PAGED_CODE();
+ if (CmBattDebug & 0x220)
+ DbgPrint("CmBattAddBattery: pdo %x\n", DeviceObject);
+
+ /* Create the FDO */
+ Status = CmBattCreateFdo(DriverObject,
+ DeviceObject,
+ sizeof(CMBATT_DEVICE_EXTENSION),
+ &FdoDeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattAddBattery: error (0x%x) creating Fdo\n", Status);
+ return Status;
+ }
+
+ /* Build the FDO extensio, check if we support trip points */
+ FdoExtension = FdoDeviceObject->DeviceExtension;
+ FdoExtension->FdoType = CmBattBattery;
+ FdoExtension->Started = 0;
+ FdoExtension->NotifySent = TRUE;
+ InterlockedExchange(&FdoExtension->ArLockValue, 0);
+ FdoExtension->TripPointValue = BATTERY_UNKNOWN_CAPACITY;
+ FdoExtension->Tag = 0;
+ FdoExtension->InterruptTime = KeQueryInterruptTime();
+ FdoExtension->TripPointSet = CmBattSetTripPpoint(FdoExtension, 0) !=
+ STATUS_OBJECT_NAME_NOT_FOUND;
+
+ /* Setup the battery miniport information structure */
+ RtlZeroMemory(&MiniportInfo, sizeof(MiniportInfo));
+ MiniportInfo.Pdo = DeviceObject;
+ MiniportInfo.MajorVersion = BATTERY_CLASS_MAJOR_VERSION;
+ MiniportInfo.MinorVersion = BATTERY_CLASS_MINOR_VERSION;
+ MiniportInfo.Context = FdoExtension;
+ MiniportInfo.QueryTag = (PVOID)CmBattQueryTag;
+ MiniportInfo.QueryInformation = (PVOID)CmBattQueryInformation;
+ MiniportInfo.SetInformation = NULL;
+ MiniportInfo.QueryStatus = (PVOID)CmBattQueryStatus;
+ MiniportInfo.SetStatusNotify = (PVOID)CmBattSetStatusNotify;
+ MiniportInfo.DisableStatusNotify = (PVOID)CmBattDisableStatusNotify;
+ MiniportInfo.DeviceName = FdoExtension->DeviceName;
+
+ /* Register with the class driver */
+ Status = BatteryClassInitializeDevice(&MiniportInfo, &FdoExtension->ClassData);
+ if (!NT_SUCCESS(Status))
+ {
+ IoDetachDevice(FdoExtension->AttachedDevice);
+ CmBattDestroyFdo(FdoExtension->FdoDeviceObject);
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattAddBattery: error (0x%x) registering with class\n", Status);
+ return Status;
+ }
+
+ /* Register WMI */
+ Status = CmBattWmiRegistration(FdoExtension);
+ if (!NT_SUCCESS(Status))
+ {
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status);
+ return Status;
+ }
+
+ /* Register ACPI */
+ Status = FdoExtension->AcpiInterface.RegisterForDeviceNotifications(FdoExtension->AcpiInterface.Context,
+ (PVOID)CmBattNotifyHandler,
+ FdoExtension);
+ if (!NT_SUCCESS(Status))
+ {
+ CmBattWmiDeRegistration(FdoExtension);
+ BatteryClassUnload(FdoExtension->ClassData);
+ IoDetachDevice(FdoExtension->AttachedDevice);
+ CmBattDestroyFdo(FdoExtension->FdoDeviceObject);
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattAddBattery: Could not register for battery notify, status = %Lx\n", Status);
+ }
+
+ /* Return status */
+ return Status;
}
NTSTATUS
NTAPI
-CmBattAddAcAdapter(PDRIVER_OBJECT DriverObject,
- PDEVICE_OBJECT DeviceObject)
+CmBattAddAcAdapter(IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT PdoDeviceObject)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ PDEVICE_OBJECT FdoDeviceObject;
+ NTSTATUS Status;
+ PCMBATT_DEVICE_EXTENSION DeviceExtension;
+ PAGED_CODE();
+ if (CmBattDebug & 0x220)
+ DbgPrint("CmBattAddAcAdapter: pdo %x\n", PdoDeviceObject);
+
+ /* Check if we already have an AC adapter */
+ if (AcAdapterPdo)
+ {
+ /* Don't do anything */
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBatt: Second AC adapter found. Current version of driver only supports 1 aadapter.\n");
+ }
+ else
+ {
+ /* Set this as the AC adapter's PDO */
+ AcAdapterPdo = PdoDeviceObject;
+ }
+
+ /* Create the FDO for the adapter */
+ Status = CmBattCreateFdo(DriverObject,
+ PdoDeviceObject,
+ sizeof(CMBATT_DEVICE_EXTENSION),
+ &FdoDeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail */
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattAddAcAdapter: error (0x%x) creating Fdo\n", Status);
+ return Status;
+ }
+
+ /* Set the type and do WMI registration */
+ DeviceExtension = FdoDeviceObject->DeviceExtension;
+ DeviceExtension->FdoType = CmBattAcAdapter;
+ Status = CmBattWmiRegistration(DeviceExtension);
+ if (!NT_SUCCESS(Status))
+ {
+ /* We can go on without WMI */
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattAddBattery: Could not register as a WMI provider, status = %Lx\n", Status);
+ }
+
+ /* Register with ACPI */
+ Status = DeviceExtension->AcpiInterface.RegisterForDeviceNotifications(DeviceExtension->AcpiInterface.Context,
+ (PVOID)CmBattNotifyHandler,
+ DeviceExtension);
+ if (!(NT_SUCCESS(Status)) && (CmBattDebug & 0xC))
+ DbgPrint("CmBattAddAcAdapter: Could not register for power notify, status = %Lx\n", Status);
+
+ /* Send the first manual notification */
+ CmBattNotifyHandler(DeviceExtension, ACPI_BATT_NOTIFY_STATUS);
+ return STATUS_SUCCESS;
}
-NTSTATUS NTAPI CmBattAddDevice(PDRIVER_OBJECT DriverObject,
- PDEVICE_OBJECT DeviceObject)
+NTSTATUS
+NTAPI
+CmBattAddDevice(IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT PdoDeviceObject)
{
- UNIMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ NTSTATUS Status;
+ HANDLE KeyHandle;
+ ULONG ResultLength;
+ UNICODE_STRING KeyString;
+ UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)];
+ PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)Buffer;
+ ULONG PowerSourceType;
+ PAGED_CODE();
+ if (CmBattDebug & 0x220)
+ DbgPrint("CmBattAddDevice: Entered with pdo %x\n", PdoDeviceObject);
+
+ /* Make sure we have a PDO */
+ if (!PdoDeviceObject)
+ {
+ /* Should not be having as one */
+ if (CmBattDebug & 0x24) DbgPrint("CmBattAddDevice: Asked to do detection\n");
+ return STATUS_NO_MORE_ENTRIES;
+ }
+
+ /* Open the driver key */
+ Status = IoOpenDeviceRegistryKey(PdoDeviceObject,
+ PLUGPLAY_REGKEY_DRIVER,
+ KEY_READ,
+ &KeyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattAddDevice: Could not get the software branch: %x\n", Status);
+ return Status;
+ }
+
+ /* Read the power source type */
+ RtlInitUnicodeString(&KeyString, L"PowerSourceType");
+ Status = ZwQueryValueKey(KeyHandle,
+ &KeyString,
+ KeyValuePartialInformation,
+ PartialInfo,
+ sizeof(Buffer),
+ &ResultLength);
+ ZwClose(KeyHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ /* We need the data, fail without it */
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattAddDevice: Could not read the power type identifier: %x\n", Status);
+ return Status;
+ }
+
+ /* Check what kind of power source this is */
+ PowerSourceType = *(PULONG)PartialInfo->Data;
+ if (PowerSourceType == 1)
+ {
+ /* Create an AC adapter */
+ Status = CmBattAddAcAdapter(DriverObject, PdoDeviceObject);
+ }
+ else if (PowerSourceType == 0)
+ {
+ /* Create a battery */
+ Status = CmBattAddBattery(DriverObject, PdoDeviceObject);
+ }
+ else
+ {
+ /* Unknown type, fail */
+ if (CmBattDebug & 0xC)
+ DbgPrint("CmBattAddDevice: Invalid POWER_SOURCE_TYPE == %d \n", PowerSourceType);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Return whatever the FDO creation routine did */
+ return Status;
}
/* EOF */