+++ /dev/null
-/*
- * PROJECT: ReactOS ACPI-Compliant Control Method Battery
- * LICENSE: BSD - See COPYING.ARM in the top level directory
- * FILE: boot/drivers/bus/acpi/cmbatt/cmbpnp.c
- * PURPOSE: Plug-and-Play IOCTL/IRP Handling
- * PROGRAMMERS: ReactOS Portable Systems Group
- */
-
-/* INCLUDES *******************************************************************/
-
-#include "cmbatt.h"
-
-/* 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(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp,
- IN PKEVENT Event)
-{
- 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(IN PDEVICE_OBJECT DeviceObject,
- IN OUT PACPI_INTERFACE_STANDARD AcpiInterface)
-{
- 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->MajorFunction = IRP_MJ_PNP;
- 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 */
- 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(IN PDEVICE_OBJECT DeviceObject)
-{
- PAGED_CODE();
- if (CmBattDebug & 0x220) DbgPrint("CmBattDestroyFdo, Battery.\n");
-
- /* Delete the device */
- IoDeleteDevice(DeviceObject);
- if (CmBattDebug & 0x220) DbgPrint("CmBattDestroyFdo: done.\n");
-}
-
-NTSTATUS
-NTAPI
-CmBattRemoveDevice(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- 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(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- 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;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- }
-
- /* Return status */
- return Status;
-}
-
-NTSTATUS
-NTAPI
-CmBattPnpDispatch(IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp)
-{
- 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, Irp);
- if (!NT_SUCCESS(Status))
- {
- /* Complete the request */
- Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
- IoCompleteRequest(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(DeviceExtension->AttachedDevice, 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: Received 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(DeviceExtension->AttachedDevice, 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 */
- IoCompleteRequest(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;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- }
-
- /* Release the remove lock and return status */
- return Status;
-}
-
-NTSTATUS
-NTAPI
-CmBattCreateFdo(IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT DeviceObject,
- IN ULONG DeviceExtensionSize,
- IN PDEVICE_OBJECT *NewDeviceObject)
-{
- 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_POWER_PAGABLE | DO_BUFFERED_IO);
- 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, 'RbmC', 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) != 0);
- }
-
- /* 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(IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT DeviceObject)
-{
- 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 extension, 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(IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT PdoDeviceObject)
-{
- 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 adapter.\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(IN PDRIVER_OBJECT DriverObject,
- IN PDEVICE_OBJECT PdoDeviceObject)
-{
- 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 */