An ACPI Driver with IRQL BSOD problem

I have wrote an ACPI Driver with will evluate ASL method and accept ASL?s notify from BIOS?the problem now is when I try to get the ACPI Driver Interface, then 0x0A BSOD occour when windows xp starting bar is running, I post some code to reference,please kindly helps!

NTSTATUS HelloWDMAddDevice(IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
ACPI_INTERFACE_STANDARD2 AcpiInterface;
// PVOID AbcdDevice=NULL;
CM_ABCD_DEV AbcdDevice;

PAGED_CODE();
#if DBG
KdPrint((“Enter HelloWDMAddDevice\n”));
#endif
NTSTATUS status;
PDEVICE_OBJECT fdo;
UNICODE_STRING devName;
RtlInitUnicodeString(&devName,L"\Device\MyWDMDevice");
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&(UNICODE_STRING)devName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&fdo);
if( !NT_SUCCESS(status))
return status;
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
pdx->fdo = fdo;
pdx->NextStackDevice = IoAttachDeviceToDeviceStack(fdo, PhysicalDeviceObject);
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName,L"\DosDevices\TEST0001");

pdx->ustrDeviceName = devName;
pdx->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink(&(UNICODE_STRING)symLinkName,&(UNICODE_STRING)devName);

if( !NT_SUCCESS(status))
{
IoDeleteSymbolicLink(&pdx->ustrSymLinkName);
status = IoCreateSymbolicLink(&symLinkName,&devName);
if( !NT_SUCCESS(status))
{
return status;
}
}

fdo->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
fdo->Flags &= ~DO_DEVICE_INITIALIZING;

GetAbcdData(fdo,0);

status = GetAcpiInterfaces(PhysicalDeviceObject,&AcpiInterface);

if (!NT_SUCCESS(status))
{
#if DBG
KdPrint((“GetAcpiInterfaces failed\n”));
KdPrint((“NTSTATUS=%x\n”,status));
#endif
return status;
}

//
// Register the notify handler for this device with ACPI
//

status = AcpiInterface.RegisterForDeviceNotifications (
PhysicalDeviceObject,
AbcdDeviceNotifyHandler,
NULL);

if (!NT_SUCCESS(status))
{
#if DBG
KdPrint((“RegisterForDeviceNotifications failed\n”));
KdPrint((“NTSTATUS=%x\n”,status));
#endif
return status;
}

return STATUS_SUCCESS;
}

NTSTATUS
GetAcpiInterfaces(
IN PDEVICE_OBJECT Pdo,
OUT PACPI_INTERFACE_STANDARD2 AcpiInterfaces
)
/*
Routine Description:
Call ACPI driver to get the direct-call interfaces. It does
this the first time it is called, no more.
Arguments:
None.
Return Value:
Status
*/
{

NTSTATUS Status = STATUS_SUCCESS;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;

PDEVICE_OBJECT LowerPdo=NULL;
// PDEVICE_EXTENSION data1;

// data1 = (PDEVICE_EXTENSION) Pdo->DeviceExtension;

// Only need to do this once
if(!LowerPdo){

LowerPdo = IoGetAttachedDeviceReference (Pdo);

// Allocate an IRP for below
Irp = IoAllocateIrp(LowerPdo->StackSize, FALSE); // Get stack size from
// PDO
// .
// .
// .
IrpSp = IoGetNextIrpStackLocation(Irp);
//
// Use QUERY_INTERFACE to get the address of the direct-
// call ACPI interfaces.
//
IrpSp->MajorFunction = IRP_MJ_PNP;
IrpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
IrpSp->Parameters.QueryInterface.InterfaceType=(LPGUID)&GUID_ACPI_INTERFACE_STANDARD2;
IrpSp->Parameters.QueryInterface.Version = 1;
IrpSp->Parameters.QueryInterface.Size = sizeof (AcpiInterfaces);
//IrpSp->Parameters.QueryInterface.Interface = (PINTERFACE) &AcpiInterfaces;
IrpSp->Parameters.QueryInterface.Interface = (PINTERFACE) AcpiInterfaces;
IrpSp->Parameters.QueryInterface.InterfaceSpecificData = NULL;
IoSetCompletionRoutine(Irp,AbcdDriverSynchronousRequest,NULL,TRUE, TRUE, TRUE);
Status = IoCallDriver (LowerPdo, Irp); ???BSOD at here???
//IoFreeIrp (Irp);
}

return Status;
}

NTSTATUS
AbcdDriverSynchronousRequest (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
// PDEVICE_EXTENSION data;

// data = (PDEVICE_EXTENSION) Context;

Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information =0; // no bytes xfered
IoCompleteRequest( Irp, IO_NO_INCREMENT );

// IoReleaseRemoveLock (&data->RemoveLock, Irp);
IoFreeIrp (Irp);

return STATUS_SUCCESS;
}

Not sure about ACPI stuff, but since you free allocated IRP in completion routine you have to stop processing of the IRP by returning STATUS_MORE_PROCESSING_REQUIRED. Also you don’t need to complete the IRP from the completion routine. Since you get to the completion routine, it means that the lower driver already called IoCompleteRequest for the IRP.

Hi Mikae,
Thanks very much for your reply, your information is very helpful to me,i will try it and posted the result,~ ~

chunhui2578@163.com wrote:

I have wrote an ACPI Driver with will evluate ASL method and accept ASL?s notify from BIOS?the problem now is when I try to get the ACPI Driver Interface, then 0x0A BSOD occour when windows xp starting bar is running, I post some code to reference,please kindly helps!

UNICODE_STRING devName;
RtlInitUnicodeString(&devName,L"\Device\MyWDMDevice");
status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_EXTENSION),
&(UNICODE_STRING)devName,

That cast is completely unnecessary. Casts are evil, and make it way
too easy to hide simple mistakes.

if (!NT_SUCCESS(status))
{
#if DBG
KdPrint((“RegisterForDeviceNotifications failed\n”));
KdPrint((“NTSTATUS=%x\n”,status));
#endif
return status;
}

The #if and #endif are unnecessary. KdPrint already compiles to nothing
if DBG is not defined.

{
NTSTATUS Status = STATUS_SUCCESS;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;

PDEVICE_OBJECT LowerPdo=NULL;
// PDEVICE_EXTENSION data1;

// data1 = (PDEVICE_EXTENSION) Pdo->DeviceExtension;

// Only need to do this once
if(!LowerPdo){

The “if” here is silly. You just initialized LowerPdo to NULL. The
“if” is guaranteed to succeed.

LowerPdo = IoGetAttachedDeviceReference (Pdo);

// Allocate an IRP for below
Irp = IoAllocateIrp(LowerPdo->StackSize, FALSE); // Get stack size from
// PDO
// .
// .
// .
IrpSp = IoGetNextIrpStackLocation(Irp);
//
// Use QUERY_INTERFACE to get the address of the direct-
// call ACPI interfaces.
//
IrpSp->MajorFunction = IRP_MJ_PNP;
IrpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
IrpSp->Parameters.QueryInterface.InterfaceType=(LPGUID)&GUID_ACPI_INTERFACE_STANDARD2;
IrpSp->Parameters.QueryInterface.Version = 1;
IrpSp->Parameters.QueryInterface.Size = sizeof (AcpiInterfaces);

AcpiInterfaces is a pointer. Its sizeof is going to be exactly 4. You
need to use sizeof(ACPI_INTERFACE_STANDARD2).

//IrpSp->Parameters.QueryInterface.Interface = (PINTERFACE) &AcpiInterfaces;
IrpSp->Parameters.QueryInterface.Interface = (PINTERFACE) AcpiInterfaces;

See, here’s a case where a cast has the potential to hurt you. The
first line there would compile, but would produce an explosion, because
AcpiInterfaces is a pointer, not a structure. The second line is the
one you want, and you should delete the first one so you don’t
accidentally try to use it.

NTSTATUS
AbcdDriverSynchronousRequest (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
// PDEVICE_EXTENSION data;

// data = (PDEVICE_EXTENSION) Context;

Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information =0; // no bytes xfered
IoCompleteRequest( Irp, IO_NO_INCREMENT );

You CREATED this request. You are not allowed to complete requests that
you created. There is no one above you to receive the completion. Just
remove those three lines, and flow in to IoFreeIrp.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

thanks for Mikae and Tim Roberts’s great help!
This is my first time to write a WDM Driver,thanks!!!

The 0x0A BOSD has been soloved!

Due to we posted too many codes, so I correct some mistake following Mikae and Tim Roberts and re-posted to code in another thread.please have a look!

http://www.osronline.com/showthread.cfm?link=222597