⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pnppower.c

📁 winddk src目录下的WDM源码压缩!
💻 C
📖 第 1 页 / 共 4 页
字号:
    //
    // Build the selector information structure
    //

    // Adjust Number of Batteries to Match SelectorInfo Supported Batteries
    // Just in case the ACPI information is incorrect
    status = SmbBattBuildSelectorStruct (SubsystemFdo);

    if (!NT_SUCCESS (status)) {
        BattPrint(BAT_ERROR, ("SmbBattCreatePdos: couldn't talk to the selector\n"));
        return status;
    }

    //
    // Build device object for each battery
    //

    for (i = 0; i < subsystemExt->NumberOfBatteries; i++) {

        //
        // Create the device object
        //

        status = IoCreateDevice(
            SubsystemFdo->DriverObject,
            sizeof (SMB_BATT_PDO),
            NULL,
            FILE_DEVICE_BATTERY,
            FILE_DEVICE_SECURE_OPEN|FILE_AUTOGENERATED_DEVICE_NAME,
            FALSE,
            &pdo
        );

        if (status != STATUS_SUCCESS) {
            BattPrint(BAT_ERROR, ("SmbBattCreatePdos: error creating battery pdo %x\n", status));

            //
            // Make sure we don't later try to use devices that weren't created.
            //
            subsystemExt->NumberOfBatteries = i;

            return(status);
        }

        //
        // Initialize the Pdo
        //

        pdo->Flags      |= DO_BUFFERED_IO;
        pdo->Flags      |= DO_POWER_PAGABLE;
        
        //
        // Save the PDO in the subsystem FDO PDO list
        //

        subsystemExt->BatteryPdoList[i] = pdo;

        //
        // Initialize the PDO extension
        //

        batteryPdoExt = (PSMB_BATT_PDO) pdo->DeviceExtension;

        batteryPdoExt->SmbBattFdoType   = SmbTypePdo;
        batteryPdoExt->DeviceObject     = pdo;
        batteryPdoExt->BatteryNumber    = i;
        batteryPdoExt->SubsystemFdo     = SubsystemFdo;
        IoInitializeRemoveLock (&batteryPdoExt->RemoveLock,
                                SMB_BATTERY_TAG,
                                REMOVE_LOCK_MAX_LOCKED_MINUTES,
                                REMOVE_LOCK_HIGH_WATER_MARK);

        //
        // Device is ready for use
        //
        
        pdo->Flags      &= ~DO_DEVICE_INITIALIZING;

    }  // for (i = 0; i < subsystemExt->NumberOfBatteries; i++)

    return STATUS_SUCCESS;

}





NTSTATUS
SmbBattBuildDeviceRelations(
    IN  PSMB_BATT_SUBSYSTEM SubsystemExt,
    IN  PDEVICE_RELATIONS   *DeviceRelations
    )
/*++

Routine Description:

    This routine is checks the device relations structure for existing device
    relations, calculates how big a new device relations structure has to be,
    allocates it, and fills it with the PDOs created for the batteries.

Arguments:

    SubsystemExt        - Device extension for the smart battery subsystem FDO

    DeviceRelations     - The Current DeviceRelations for the device...

Return Value:

    NTSTATUS

--*/
{
    PDEVICE_RELATIONS   newDeviceRelations;
    ULONG               i, j;
    ULONG               newDeviceRelationsSize;
    NTSTATUS            status;

    ULONG               existingPdos            = 0;
    ULONG               deviceRelationsSize     = 0;
    ULONG               numberOfPdos            = 0;

    PAGED_CODE();

    //
    // Calculate the size the new device relations structure has to be
    //

    if (*DeviceRelations != NULL && (*DeviceRelations)->Count > 0) {

        //
        // There are existing device relations to be copied
        //

        existingPdos = (*DeviceRelations)->Count;
        deviceRelationsSize = sizeof (ULONG) + (sizeof (PDEVICE_OBJECT) * existingPdos);
    }


    //
    // Calculate the size needed for the new device relations structure and allocate it
    //

    numberOfPdos = existingPdos + SubsystemExt->NumberOfBatteries;
    newDeviceRelationsSize = sizeof (ULONG) + (sizeof (PDEVICE_OBJECT) * numberOfPdos);

    newDeviceRelations = ExAllocatePoolWithTag (PagedPool, newDeviceRelationsSize, 'StaB');

    if (!newDeviceRelations) {
        BattPrint (BAT_ERROR, ("SmbBattBuildDeviceRelations:  couldn't allocate device relations buffer\n"));
        return STATUS_INSUFFICIENT_RESOURCES;
    }


    //
    // If there are existing device relations copy them to the new device
    // relations structure and free the old one.
    //

    if (existingPdos) {
        RtlCopyMemory (newDeviceRelations, *DeviceRelations, deviceRelationsSize);
    }

    if (*DeviceRelations) {   // Could be a zero length list, but still need freeing
        ExFreePool (*DeviceRelations);
    }


    //
    // Now add the battery PDOs to the end of the list and reference it
    //

    for (i = existingPdos, j = 0; i < numberOfPdos; i ++, j ++) {
        newDeviceRelations->Objects[i] = SubsystemExt->BatteryPdoList[j];

        status = ObReferenceObjectByPointer(
            SubsystemExt->BatteryPdoList[j],
            0,
            NULL,
            KernelMode
        );

        if (!NT_SUCCESS(status) ) {

            //
            // This should theoretically never happen...
            //
            BattPrint(BAT_ERROR, ("SmbBattBuildDeviceRelations: error referencing battery pdo %x\n", status));
            return status;
        }
    }

    newDeviceRelations->Count = numberOfPdos;
    *DeviceRelations = newDeviceRelations;

    return STATUS_SUCCESS;
}



NTSTATUS
SmbBattQueryDeviceRelations(
    IN  PDEVICE_OBJECT DeviceObject,
    IN  PIRP           Irp
    )
/*++

Routine Description:

    This routine handles the IRP_MN_QUERY_DEVICE_RELATIONS.

Arguments:

    Pdo         - Battery PDO

    Irp         - The query Irp

Return Value:

    NTSTATUS

--*/
{

    PSMB_NP_BATT            SmbNPBatt       = (PSMB_NP_BATT) DeviceObject->DeviceExtension;
    PSMB_BATT_PDO           PdoExt          = (PSMB_BATT_PDO) DeviceObject->DeviceExtension;
    PSMB_BATT_SUBSYSTEM     SubsystemExt    = (PSMB_BATT_SUBSYSTEM) DeviceObject->DeviceExtension;
    PDEVICE_OBJECT          pdo;
    PIO_STACK_LOCATION      IrpSp           = IoGetCurrentIrpStackLocation(Irp);
    NTSTATUS                status          = STATUS_NOT_SUPPORTED;
    ULONG                   i;
    PDEVICE_RELATIONS   deviceRelations =
        (PDEVICE_RELATIONS) Irp->IoStatus.Information;


    PAGED_CODE();

    BattPrint(BAT_TRACE, ("SmbBattQueryDeviceRelations: ENTERING\n"));

    switch (SmbNPBatt->SmbBattFdoType) {
        case SmbTypeSubsystem: {
            if (IrpSp->Parameters.QueryDeviceRelations.Type == BusRelations) {
                BattPrint(
                    BAT_IRPS,
                    ("SmbBattQueryDeviceRelations: Handling Bus relations request\n")
                );

                if (SubsystemExt->NumberOfBatteries != 0) {
                    //
                    // We've already found our batteries, so we don't need to
                    // look again since smart batteries are static.
                    // Just rebuild the return structure.
                    //

                    status = SmbBattBuildDeviceRelations (SubsystemExt, &deviceRelations);
                } else {
                    status = SmbBattCreatePdos (DeviceObject);

                    if (NT_SUCCESS (status)) {
                        status = SmbBattBuildDeviceRelations (SubsystemExt, &deviceRelations);
                    }

                    if (NT_SUCCESS (status)) {

                        //
                        // Now register for alarms
                        // (Used to register during START_DEVICE,
                        // but don't need notifications until after the batteries
                        // are here. This avoids some other problems too.)

                        status = SmbBattRegisterForAlarm (DeviceObject);
                    }
                }
                Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;

            }

            break;
        }
        case SmbTypeBattery: {
            status = STATUS_NOT_SUPPORTED;

            break;
        }
        case SmbTypePdo: {
            if (IrpSp->Parameters.QueryDeviceRelations.Type == TargetDeviceRelation ) {
                BattPrint(
                    BAT_IRPS,
                    ("SmbBattQueryDeviceRelations: Handling TargetDeviceRelation request\n")
                );
                deviceRelations = ExAllocatePoolWithTag (PagedPool,
                                                         sizeof(DEVICE_RELATIONS),
                                                         SMB_BATTERY_TAG);
                if (!deviceRelations) {
                    return STATUS_INSUFFICIENT_RESOURCES;
                }

                status = ObReferenceObjectByPointer(DeviceObject,
                                                    0,
                                                    NULL,
                                                    KernelMode);
                if (!NT_SUCCESS(status)) {
                    ExFreePool(deviceRelations);
                    return status;
                }
                deviceRelations->Count = 1;
                deviceRelations->Objects[0] = DeviceObject;

                Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
            } else {
                status = STATUS_NOT_SUPPORTED;
            }

            break;
        }
        default: {

            ASSERT (FALSE);
        }
    }

    return status;
}




NTSTATUS
SmbBattRemoveDevice(
    IN  PDEVICE_OBJECT DeviceObject,
    IN  PIRP           Irp
    )
/*++

Routine Description:

    This routine handles the IRP_MN_REMOVE_DEVICE.

Arguments:

    Pdo         - Battery PDO

    Irp         - The query Irp

Return Value:

    NTSTATUS

--*/
{

    PSMB_NP_BATT            SmbNPBatt       = (PSMB_NP_BATT) DeviceObject->DeviceExtension;
    PSMB_BATT_PDO           PdoExt          = (PSMB_BATT_PDO) DeviceObject->DeviceExtension;
    PSMB_BATT_SUBSYSTEM     SubsystemExt    = (PSMB_BATT_SUBSYSTEM) DeviceObject->DeviceExtension;
    PDEVICE_OBJECT          pdo;
    PIO_STACK_LOCATION      IrpSp           = IoGetCurrentIrpStackLocation(Irp);
    NTSTATUS                status          = STATUS_NOT_SUPPORTED;
    ULONG                   i;

    PAGED_CODE();

    BattPrint(BAT_TRACE, ("SmbBattRemoveDevice: ENTERING\n"));

    switch (SmbNPBatt->SmbBattFdoType) {
        case SmbTypeSubsystem: {
            BattPrint(BAT_IRPS, ("SmbBattRemoveDevice: Removing Subsystem FDO.\n"));

            //
            // De-register for notifications
            //

            SmbBattUnregisterForAlarm (DeviceObject);

            IoFreeWorkItem (SubsystemExt->WorkerThread);

            //
            // Remove PDOs
            //

            for (i = 0; i < SubsystemExt->NumberOfBatteries; i++) {
                pdo = SubsystemExt->BatteryPdoList[i];
                if (pdo) {
                    PdoExt = (PSMB_BATT_PDO) pdo->DeviceExtension;
                    status = IoAcquireRemoveLock (&PdoExt->RemoveLock, Irp);
                    IoReleaseRemoveLockAndWait (&PdoExt->RemoveLock, Irp);
                    SubsystemExt->BatteryPdoList[i] = NULL;
                    IoDeleteDevice (pdo);
                }
            }

            if ((SubsystemExt->SelectorPresent) && (SubsystemExt->Selector)) {
                ExFreePool (SubsystemExt->Selector);
            }

            IoSkipCurrentIrpStackLocation (Irp);
            Irp->IoStatus.Status = STATUS_SUCCESS;
            status = IoCallDriver (SubsystemExt->LowerDevice, Irp);

            IoDetachDevice (SubsystemExt->LowerDevice);
            IoDeleteDevice (DeviceObject);

            break;
        }
        case SmbTypeBattery: {

            BattPrint(BAT_IRPS, ("SmbBattRemoveDevice: Removing Battery FDO\n"));
            IoReleaseRemoveLockAndWait (&SmbNPBatt->RemoveLock, Irp);

            //
            // Unregister as a WMI Provider.
            //
            SmbBattWmiDeRegistration(SmbNPBatt);
            
            //
            //  Tell the class driver we are going away
            //
            status = BatteryClassUnload (SmbNPBatt->Class);
            ASSERT (NT_SUCCESS(status));

            ExFreePool (SmbNPBatt->Batt);

            ((PSMB_BATT_PDO) SmbNPBatt->LowerDevice->DeviceExtension)->Fdo = NULL;
            
            IoSkipCurrentIrpStackLocation (Irp);
            Irp->IoStatus.Status = STATUS_SUCCESS;
            status = IoCallDriver (SmbNPBatt->LowerDevice, Irp);

            IoDetachDevice (SmbNPBatt->LowerDevice);
            IoDeleteDevice (DeviceObject);

            break;
        }
        case SmbTypePdo: {
            BattPrint(BAT_IRPS, ("SmbBattRemoveDevice: Remove for Battery PDO (doing nothing)\n"));
            //
            // Don't delete the device until it is physically removed.
            // Usually, the battery subsystem can't be physically removed...
            //

            //
            // Need to release Remove lock, since PnP dispatch won't...
            //
            IoReleaseRemoveLock (&PdoExt->RemoveLock, Irp);

            status = STATUS_SUCCESS;

            //
            // Complete the request with the current status
            //
            Irp->IoStatus.Status = status;
            IoCompleteRequest(Irp, IO_NO_INCREMENT);

            break;
        }
        default: {

            ASSERT (FALSE);
        }
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -