[wdmaudiodev] Re: Overriding IRP_MJ_DEVICE_CONTROL handling is possible?

  • From: "Cheng-mean Liu (SOCCER)" <soccerl@xxxxxxxxxxxxx>
  • To: "wdmaudiodev@xxxxxxxxxxxxx" <wdmaudiodev@xxxxxxxxxxxxx>
  • Date: Mon, 9 Apr 2007 11:54:15 -0700

Other than saving you the trouble of the trouble of keeping a copy of the 
portcls's IRP_MJ_DEVICE_CONTROL handler, PcDispatchIrp also doe some additional 
parameter validations.

Calling PcDispatchIrp allows portcls to do the default handling on behalf of 
miniport driver.  You can do any proprietary handling for IRPs 
(IRP_MJ_DEVICE_CONTROL, IRP_MJ_CREATE, or IRP_MJ_CLOSE.....)destinating to your 
device before forwarding to portcls for all necessary default handling.  Here 
is some example on how it can be used.

NTSTATUS DriverEntry(IN PDRIVER_OBJECT _pDriverObject,
                     IN  PUNICODE_STRING _pRegistryPath)
{
...
    status = PcInitializeAdapterDriver(_pDriverObject, _pRegistryPath, 
AddDevice);
...
    _pDriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = IoCtlHandler;
..
}
NTSTATUS IoCtlHandler(DEVICE_OBJECT *_Fdo,
                      IRP *_Irp)
{
    PAGED_CODE();
    NTSTATUS status = STATUS_UNSUCCESSFUL;

    IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(_Irp);

    if ((NULL != _Irp->AssociatedIrp.SystemBuffer) &&
        (NULL != stack) &&
        (NULL != stack->FileObject))
    {
        if (0 == RtlCompareUnicodeString (&gPrivateInterfaceRefStringCmp, 
&stack->FileObject->FileName, TRUE))
        {
            // gPrivateInterfaceRefStringCmp is your prviate interface string 
that you register through IoRegisterDeviceInterface
            // in AddDevice routine
            ...
            //
            // Handle the various IOCTLs
            //
            switch (stack->Parameters.DeviceIoControl.IoControlCode)
            {
            case IOCTL_PRIVATE_CODE1:
                {
                    ....
                    break;
                }
            case IOCTL_PRIVATE_CODE2:
                {
                    .....
                    break;
                }
            default:
                {
                    .....
                    status = STATUS_INVALID_PARAMETER;
                    break;
                }
            }

            // Set the IRP status appropriately, and complete the IRP.
            _Irp->IoStatus.Status = status;
            IoCompleteRequest(_Irp, IO_NO_INCREMENT);
            SET_STATUS_AND_JUMP(status, exit);
        } // gPrivateInterfaceRefStringCmp == stack->FileObject->FileName
      }

    // We don't handle this IRP.  Forward it on to Portclass for handling.
    status = PcDispatchIrp(_Fdo, _Irp);

exit:
    return status;
}


Regards,
Cheng-mean Liu
Audio Driver Developer
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.


From: wdmaudiodev-bounce@xxxxxxxxxxxxx 
[mailto:wdmaudiodev-bounce@xxxxxxxxxxxxx] On Behalf Of Tom Eckert
Sent: Monday, April 09, 2007 6:09 AM
To: wdmaudiodev@xxxxxxxxxxxxx
Subject: [wdmaudiodev] Re: Overriding IRP_MJ_DEVICE_CONTROL handling is 
possible?

Don,
I don't think you should be calling IoSkipCurrentIrpStackLocation() and
 IoCallDriver() to pass the call to portcls.  The miniport is not an upper 
driver for portcls, actually portcls takes over your stack location so once 
you've hooked it back (by overwriting the portcls call in the MajorFunction 
table) this will actually re-enter your driver instead of calling portcls (and 
overrun the stack).
Save the address of the IRP_MJ_DEVICE_CONTROL handler that portcls installs and 
call it directly when you've determined that the IRP is not from your app.

PDRIVER_DISPATCH pPortClsDeviceControl;

extern "C" NTSTATUS DriverEntry(
 IN PDRIVER_OBJECT  DriverObject,
 IN PUNICODE_STRING RegistryPathName)
{
  NTSTATUS ntStatus = PcInitializeAdapterDriver(
                                      DriverObject,
                                      RegistryPathName,
                                      (PDRIVER_ADD_DEVICE)AddDevice);

 if(NT_SUCCESS(ntStatus))
 {
    pPortClsDeviceControl = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL];
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControlHandler;
 }
 return ntStatus;
}

and somewhere in DeviceControlHandler
    if(it's my IOCTL)
       status = HandleIt();
    else
       status= pPortClsDeviceControl(fdo,Irp);

This approach works for us but it looks like PcDispatchIrp saves you the 
trouble of keeping a copy of the portcls handler so to use that just eliminate 
the pPortClsDeviceControl variable and call PcDispatchIrp instead.  Maybe 
someone from ms will want to chime in here if there's a reason why the 
PcDispatchIrp approach is better than simply calling the portcls entry?
You'll also need to create symbolic link to use in your user mode CreateFile 
call.

Hope this helps,
Tom

Thomas Eckert
Sr Software Engineer
Audioscience Inc.

Don Bell wrote:
I am trying to find a way to add some custom IOCTL handling to a
miniport audio driver. The driver's DriverEntry() currently looks like
this:


extern "C" NTSTATUS DriverEntry(
 IN PDRIVER_OBJECT  DriverObject,
 IN PUNICODE_STRING RegistryPathName)
{
  NTSTATUS ntStatus = PcInitializeAdapterDriver(
                                      DriverObject,
                                      RegistryPathName,
                                      (PDRIVER_ADD_DEVICE)AddDevice);

 return ntStatus;
}

And I was thinking of adding a DispatchDeviceControl() like this:

extern "C" NTSTATUS DriverEntry(
 IN PDRIVER_OBJECT  DriverObject,
 IN PUNICODE_STRING RegistryPathName)
{
  NTSTATUS ntStatus = PcInitializeAdapterDriver(
                                      DriverObject,
                                      RegistryPathName,
                                      (PDRIVER_ADD_DEVICE)AddDevice);

 if(NT_SUCCESS(ntStatus))
 {
   DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =

DeviceControlHandler;
 }
 return ntStatus;
}

Then, in DeviceControlHandler():

(1) Use IoGetCurrentIrpStackLocation() - to obtain current stack location.

(2) Handle it (i.e. the current IRP) if it's "mine" or pass it down
the stack for processing by using IoSkipCurrentIrpStackLocation() and
then calling IoCallDriver().

My questions is... Is this "legal"? That is, is the PortCls system
designed to handle such customization (i.e. mixing PortCls high-level
Pc* with Io*)?

The main reason I am asking such a trivial question is that while I
can make this appear to work, it may be in violation of some
fundamental principle in the PortCls system, which will trigger bugs
that could be a nightmare to debug.

Am I in for trouble in attempting to hack something like this into PortCls?

Many thanks in advance,
Don
******************

WDMAUDIODEV addresses:
Post message: mailto:wdmaudiodev@xxxxxxxxxxxxx
Subscribe:    mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=subscribe
Unsubscribe:  mailto:wdmaudiodev-request@xxxxxxxxxxxxx?subject=unsubscribe
Moderator:    mailto:wdmaudiodev-moderators@xxxxxxxxxxxxx

URL to WDMAUDIODEV page:
http://www.wdmaudiodev.com/


Other related posts: