📄 smbbatt.c
字号:
BattPrint(BAT_ERROR, ("SmbBattNewDevice: error attaching to device stack\n"));
ExFreePool (SmbBatt);
IoDeleteDevice (fdo);
return(status);
}
//
// Fill in privates
//
SmbNPBatt->Batt = SmbBatt;
SmbNPBatt->SmbBattFdoType = SmbTypeBattery;
IoInitializeRemoveLock (&SmbNPBatt->RemoveLock,
SMB_BATTERY_TAG,
REMOVE_LOCK_MAX_LOCKED_MINUTES,
REMOVE_LOCK_HIGH_WATER_MARK);
ExInitializeFastMutex (&SmbNPBatt->Mutex);
SmbBatt->NP = SmbNPBatt;
SmbBatt->PDO = PDO;
SmbBatt->DeviceObject = fdo;
SmbBatt->SelectorPresent = subsystemExt->SelectorPresent;
SmbBatt->Selector = subsystemExt->Selector;
pdoExt->Fdo = fdo;
//
// Precalculate this batteries SMB_x bit position in the selector status register.
//
// Just move it into the lower nibble and any function that needs
// the bit can shift it left 4 = charger, 8 = power, 12 = smb
//
SmbBatt->SelectorBitPosition = 1;
if (pdoExt->BatteryNumber > 0) {
SmbBatt->SelectorBitPosition <<= pdoExt->BatteryNumber;
}
//
// Have class driver allocate a new SMB miniport device
//
RtlZeroMemory (&BattInit, sizeof(BattInit));
BattInit.MajorVersion = SMB_BATTERY_MAJOR_VERSION;
BattInit.MinorVersion = SMB_BATTERY_MINOR_VERSION;
BattInit.Context = SmbBatt;
BattInit.QueryTag = SmbBattQueryTag;
BattInit.QueryInformation = SmbBattQueryInformation;
BattInit.SetInformation = SmbBattSetInformation;
BattInit.QueryStatus = SmbBattQueryStatus;
BattInit.SetStatusNotify = SmbBattSetStatusNotify;
BattInit.DisableStatusNotify = SmbBattDisableStatusNotify;
BattInit.Pdo = PDO;
BattInit.DeviceName = NULL;
status = BatteryClassInitializeDevice (
&BattInit,
&SmbNPBatt->Class
);
if (status != STATUS_SUCCESS) {
BattPrint(BAT_ERROR, ("SmbBattNewDevice: error initializing battery: %x\n", status));
ExFreePool (SmbBatt);
IoDetachDevice (SmbNPBatt->LowerDevice);
IoDeleteDevice (fdo);
return(status);
}
//
// Register WMI support.
//
status = SmbBattWmiRegistration(SmbNPBatt);
if (!NT_SUCCESS(status)) {
//
// WMI support is not critical to operation. Just log an error.
//
BattPrint(BAT_ERROR,
("SmbBattNewDevice: Could not register as a WMI provider, status = %Lx\n", status));
}
//
// Device is ready for use
//
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
} // else (we have a battery PDO)
return status;
}
VOID
SmbBattUnload(
IN PDRIVER_OBJECT DriverObject
)
/*++
Routine Description:
Cleanup all devices and unload the driver
Arguments:
DriverObject - Driver object for unload
Return Value:
Status
--*/
{
PAGED_CODE();
BattPrint(BAT_TRACE, ("SmbBattUnload: ENTERING\n"));
//
// Should check here to make sure all DO's are gone.
//
ExFreePool (GlobalRegistryPath.Buffer);
// This is listed as an error so I'll always see when it is unloaded...
BattPrint(BAT_ERROR, ("SmbBattUnload: Smbbatt.sys unloaded successfully.\n"));
}
NTSTATUS
SmbBattCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PSMB_NP_BATT SmbNPBatt = (PSMB_NP_BATT) DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status;
PAGED_CODE();
BattPrint(BAT_TRACE, ("SmbBattCreate: ENTERING\n"));
status = IoAcquireRemoveLock (&SmbNPBatt->RemoveLock, IrpSp->FileObject);
//
// Complete the request and return status.
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
BattPrint(BAT_TRACE, ("SmbBattCreate: EXITING (status = 0x%08x\n", status));
return(status);
}
NTSTATUS
SmbBattClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
PSMB_NP_BATT SmbNPBatt = (PSMB_NP_BATT) DeviceObject->DeviceExtension;
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
PAGED_CODE();
BattPrint(BAT_TRACE, ("SmbBattClose: ENTERING\n"));
IoReleaseRemoveLock (&SmbNPBatt->RemoveLock, IrpSp->FileObject);
//
// Complete the request and return status.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
BattPrint(BAT_TRACE, ("SmbBattClose: EXITING\n"));
return(STATUS_SUCCESS);
}
NTSTATUS
SmbBattIoctl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
IOCTL handler. As this is an exclusive battery device, send the
Irp to the battery class driver to handle battery IOCTLs.
Arguments:
DeviceObject - Battery for request
Irp - IO request
Return Value:
Status of request
--*/
{
PSMB_NP_BATT SmbNPBatt;
PSMB_BATT SmbBatt;
ULONG InputLen, OutputLen;
PVOID IOBuffer;
PIO_STACK_LOCATION IrpSp;
BOOLEAN complete = FALSE;
NTSTATUS status = STATUS_NOT_SUPPORTED;
PAGED_CODE();
BattPrint(BAT_TRACE, ("SmbBattIoctl: ENTERING\n"));
IrpSp = IoGetCurrentIrpStackLocation(Irp);
SmbNPBatt = (PSMB_NP_BATT) DeviceObject->DeviceExtension;
status = IoAcquireRemoveLock (&SmbNPBatt->RemoveLock, Irp);
if (NT_SUCCESS(status)) {
if (SmbNPBatt->SmbBattFdoType == SmbTypePdo) {
status = STATUS_NOT_SUPPORTED;
complete = TRUE;
} else if (SmbNPBatt->SmbBattFdoType == SmbTypeSubsystem) {
#if DEBUG
if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_SMBBATT_DATA) {
//
// Direct Access Irp
//
IOBuffer = Irp->AssociatedIrp.SystemBuffer;
InputLen = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
OutputLen = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
status = SmbBattDirectDataAccess (
(PSMB_NP_BATT) DeviceObject->DeviceExtension,
(PSMBBATT_DATA_STRUCT) IOBuffer,
InputLen,
OutputLen
);
if (NT_SUCCESS(status)) {
Irp->IoStatus.Information = OutputLen;
} else {
Irp->IoStatus.Information = 0;
}
} else {
#endif
status = STATUS_NOT_SUPPORTED;
#if DEBUG
}
#endif
} else {
ASSERT (SmbNPBatt->SmbBattFdoType == SmbTypeBattery);
//
// Check to see if this is one of the private Ioctls we handle
//
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
#if DEBUG
case IOCTL_SMBBATT_DATA:
IOBuffer = Irp->AssociatedIrp.SystemBuffer;
InputLen = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
OutputLen = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
//
// This one is only handled by the battery subsystem
//
status = SmbBattDirectDataAccess (
(PSMB_NP_BATT) DeviceObject->DeviceExtension,
(PSMBBATT_DATA_STRUCT) IOBuffer,
InputLen,
OutputLen
);
if (NT_SUCCESS(status)) {
Irp->IoStatus.Information = OutputLen;
} else {
Irp->IoStatus.Information = 0;
}
break;
#endif
default:
//
// Not IOCTL for us, see if it's for the battery
//
SmbBatt = SmbNPBatt->Batt;
status = BatteryClassIoctl (SmbNPBatt->Class, Irp);
if (status != STATUS_NOT_SUPPORTED) {
//
// The Irp was completed by the batery class. Don't
// touch the Irp. Simply release the lock and return.
//
IoReleaseRemoveLock (&SmbNPBatt->RemoveLock, Irp);
BattPrint(BAT_TRACE, ("SmbBattIoctl: EXITING (was battery IOCTL)\n", status));
return status;
}
break;
} // switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
}
IoReleaseRemoveLock (&SmbNPBatt->RemoveLock, Irp);
}
if ((status == STATUS_NOT_SUPPORTED ) && !complete) {
IoSkipCurrentIrpStackLocation (Irp);
status = IoCallDriver (SmbNPBatt->LowerDevice, Irp);
} else {
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
}
BattPrint(BAT_TRACE, ("SmbBattIoctl: EXITING (status = 0x%08x)\n", status));
return status;
}
NTSTATUS
SmbBattQueryTag (
IN PVOID Context,
OUT PULONG BatteryTag
)
/*++
Routine Description:
Called by the class driver to retrieve the batteries current tag value
Arguments:
Context - Miniport context value for battery
BatteryTag - Pointer to return current tag
Return Value:
Success if there is a battery currently installed, else no such device.
--*/
{
//PSMB_BATT_SUBSYSTEM subsystemExt;
NTSTATUS status;
PSMB_BATT SmbBatt;
ULONG oldSelectorState;
PAGED_CODE();
BattPrint(BAT_TRACE, ("SmbBattQueryTag: ENTERING\n"));
//
// Get device lock and make sure the selector is set up to talk to us.
// Since multiple people may be doing this, always lock the selector
// first followed by the battery.
//
SmbBatt = (PSMB_BATT) Context;
SmbBattLockSelector (SmbBatt->Selector);
SmbBattLockDevice (SmbBatt);
status = SmbBattSetSelectorComm (SmbBatt, &oldSelectorState);
if (!NT_SUCCESS (status)) {
BattPrint(BAT_ERROR, ("SmbBattQueryTag: can't set selector communications path\n"));
} else {
//
// If the tag is not valid, check for one
//
if (SmbBatt->Info.Tag == BATTERY_TAG_INVALID) {
SmbBatt->Info.Valid = 0;
}
//
// Insure the static information regarding the battery up to date
//
SmbBattVerifyStaticInfo (SmbBatt, 0);
//
// If theres a battery return it's tag
//
if (SmbBatt->Info.Tag != BATTERY_TAG_INVALID) {
*BatteryTag = SmbBatt->Info.Tag;
status = STATUS_SUCCESS;
} else {
status = STATUS_NO_SUCH_DEVICE;
}
}
//
// Done, unlock the device and reset the selector state
//
if (NT_SUCCESS (status)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -