Portclass minidriver interaction

Hello,

Firstly please excuse me if my question may seem a little stupid, that is because I’m new to driver development.
I am trying to build a virtual sound driver starting from MSVAD sample from DDK and now I’m confronted with the following problem: How do I get a user mode application to talk to my miniport driver.
I see that MSVAD does not have any IRP dispatching functions and I read somewhere that is because portclass.sys handles most of the IRPs.
However I found after some “googleing” that you can actually create your own device object in addDevice from MSVAD and use it to receive IRPs that you pass it from user mode.
So here is how it looks the modified addDevice:
NTSTATUS AddDevice
(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
PAGED_CODE();
NTSTATUS ntStatus;
NTSTATUS addAdDeviceStatus = STATUS_UNSUCCESSFUL;
PDEVICE_OBJECT deviceObject;
UNICODE_STRING usDeviceName;
UNICODE_STRING usDosDeviceName;
DPF(D_TERSE, (“[AddDevice]”));

// Tell the class driver to add the device.
//
ntStatus =
PcAddAdapterDevice
(
DriverObject,
PhysicalDeviceObject,
PCPFNSTARTDEVICE(StartDevice),
MAX_MINIPORTS,
0
);

if (!NT_SUCCESS(ntStatus))
{
return ntStatus;
}
addAdDeviceStatus = ntStatus;
DPF(D_TERSE, (“[Added Adapter driver]”));
RtlInitUnicodeString(&usDeviceName, MY_DEVICE_NAME);
RtlInitUnicodeString(&usDosDeviceName, MY_DOSDEVICE_NAME);

// Create the device
ntStatus = IoCreateDevice
(
DriverObject,
0,
&usDeviceName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&deviceObject
);

if(!NT_SUCCESS(ntStatus))
{
DPF(D_TERSE, (“[Failed IoCreateDevice…]”));
return addAdDeviceStatus;
}

deviceObject->Flags |= DO_BUFFERED_IO;

DPF(D_TERSE, (“[Device Created]”));

// Create the symbolic link
ntStatus = IoCreateSymbolicLink
(
&usDosDeviceName,
&usDeviceName
);
if (!NT_SUCCESS(ntStatus)) //try to delete the symbolic link first
{
DPF(D_TERSE,(“[Failed IoCreateSymbolicLink…]”));
IoDeleteDevice(DriverObject->DeviceObject);
return addAdDeviceStatus;
}
DPF(D_TERSE, (“[SymbolicLink Created]”));

// Initialize device object flags
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

return ntStatus;
} // AddDevice
I also added:
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=HMIDIDispatchDeviceControl;
in driver entry. I understand that I can use the device object address above to see if the irp is for me so in the future I should probably add a device extension to my device object but I’m not there yet. One question I have is if I see that the IRP is not mine (MSVAD’s) how do I send it back to PORTCLS?

Ok, I built the driver in this form and saw that MY_DEVICE_NAME was created and I built a simple user mode application(called testdevioctrl) which should connect to the driver and send some IRP. The application causses portcls to crash the code causing the crash is:

HANDLE hDevice; // handle to the drive to be examined
hDevice = CreateFile(_T(“\\.\hmidi”), // drive to open
0, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes

if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
_tprintf(_T(“Invalid handle\n”));
return (FALSE);
}

Windbg says:


Access violation - code c0000005 (!!! second chance !!!)
nt!__InterlockedIncrement+0x5:
80541ac1 0fc101 xadd dword ptr [ecx],eax
kd> !analyze -v
Connected to Windows XP 2600 x86 compatible target, ptr64 FALSE
Loading Kernel Symbols

Loading User Symbols

Loading unloaded module list

*** WARNING: Unable to verify checksum for testdevioctrl.exe
*** ERROR: Module load completed but symbols could not be loaded for vmx_fb.dll
*** ERROR: Module load completed but symbols could not be loaded for hgfs.sys
*** ERROR: Symbol file could not be found. Defaulted to export symbols for drmk.sys -
*** ERROR: Module load completed but symbols could not be loaded for Afc.sys
*** ERROR: Symbol file could not be found. Defaulted to export symbols for vmxnet.sys -
*** ERROR: Module load completed but symbols could not be loaded for vmscsi.sys
*** ERROR: Module load completed but symbols could not be loaded for vmx_svga.sys
*** ERROR: Module load completed but symbols could not be loaded for vmmouse.sys
ERROR: FindPlugIns 8007007b
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************

Unknown bugcheck code (0)
Unknown bugcheck description
Arguments:
Arg1: 00000000
Arg2: 00000000
Arg3: 00000000
Arg4: 00000000

Debugging Details:

PROCESS_NAME: testdevioctrl.e

FAULTING_IP:
nt!__InterlockedIncrement+5
80541ac1 0fc101 xadd dword ptr [ecx],eax

EXCEPTION_RECORD: ffffffff – (.exr ffffffffffffffff)
ExceptionAddress: 80541ac1 (nt!__InterlockedIncrement+0x00000005)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000001
Parameter[1]: 00000080
Attempt to write to address 00000080

ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at “0x%08lx” referenced memory at “0x%08lx”. The memory could not be “%s”.

WRITE_ADDRESS: 00000080

BUGCHECK_STR: ACCESS_VIOLATION

DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE

LAST_CONTROL_TRANSFER: from bac8c455 to 80541ac1

STACK_TEXT:
f7988a0c bac8c455 f7988a28 bac9d02a 00000000 nt!__InterlockedIncrement+0x5
f7988a14 bac9d02a 00000000 81e50f38 81e2dc00 portcls!IncrementPendingIrpCount+0x14
f7988a28 804edfe3 81e50bf8 82838f68 806d02e8 portcls!DispatchCreate+0x13
f7988a38 8064b8a8 82838f78 82838f68 81e2dcf8 nt!IopfCallDriver+0x31
f7988a5c 80577672 81e50be0 81e3639c f7988c04 nt!IovCallDriver+0xa0
f7988b3c 805b390a 81e50bf8 00000000 81e362f8 nt!IopParseDevice+0xa12
f7988bc4 805afdeb 00000000 f7988c04 00000040 nt!ObpLookupObjectName+0x56a
f7988c18 8056a3b1 00000000 00000000 00046001 nt!ObOpenObjectByName+0xeb
f7988c94 8056ad28 0012fe28 00100080 0012fdc8 nt!IopCreateFile+0x407
f7988cf0 8056d3fa 0012fe28 00100080 0012fdc8 nt!IoCreateFile+0x8e
f7988d30 8053ca28 0012fe28 00100080 0012fdc8 nt!NtCreateFile+0x30
f7988d30 7c90eb94 0012fe28 00100080 0012fdc8 nt!KiFastCallEntry+0xf8
0012fd84 7c90d68e 7c810916 0012fe28 00100080 ntdll!KiFastSystemCallRet
0012fd88 7c810916 0012fe28 00100080 0012fdc8 ntdll!NtCreateFile+0xc
0012fe20 004307a7 00000000 00000000 00000003 kernel32!CreateFileW+0x35f
0012ff54 00430fe2 00000001 00332f68 00333018 testdevioctrl!wmain+0x37 [d:\test\minidriver\testdevioctrl\testdevioctrl\testdevioctrl.cpp @ 21]
0012ffb8 00430d9d 0012fff0 7c816fd7 0007da50 testdevioctrl!__tmainCRTStartup+0x232 [f:\sp\vctools\crt_bld\self_x86\crt\src\crt0.c @ 327]
0012ffc0 7c816fd7 0007da50 7c90e1fe 7ffd6000 testdevioctrl!wmainCRTStartup+0xd [f:\sp\vctools\crt_bld\self_x86\crt\src\crt0.c @ 196]
0012fff0 00000000 0042e5a0 00000000 78746341 kernel32!BaseProcessStart+0x23

STACK_COMMAND: kb

FOLLOWUP_IP:
portcls!IncrementPendingIrpCount+14
bac8c455 5d pop ebp

SYMBOL_STACK_INDEX: 1

SYMBOL_NAME: portcls!IncrementPendingIrpCount+14

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: portcls

IMAGE_NAME: portcls.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 41107f13

FAILURE_BUCKET_ID: ACCESS_VIOLATION_W_VRF_portcls!IncrementPendingIrpCount+14

BUCKET_ID: ACCESS_VIOLATION_W_VRF_portcls!IncrementPendingIrpCount+14

Followup: MachineOwner

Now I have a few more questions, the obvious would be why does it crash? Another is if there is another possibility to access MSVAD directly without going through the entire driver stack?

Best regards,
Cristi

Hello again,

Sorry if anyone wasted to much time on my previous post but the problems seemed to be solved by PcDispatchIrp. I was completing the IRP i got in HMIDIDispatchDeviceControl. That was wrong… very wrong.

> PcAddAdapterDevice

. . .
0
);
Maybe it’s irrelevant but the snippet in DDK docs uses at_least
PORT_CLASS_DEVICE_EXTENSION_SIZE
as the last parameter.
Quote (ok, in your case MY_EXTENSION_SIZE is 0, so far at least, but…):

#define MY_EXTENSION_SIZE 64
NTSTATUS ntstatus = PcAddAdapterDevice(DriverObject, PhysicalDeviceObject,
MyStartDevice, MAX_MINIPORTS,
MY_EXTENSION_SIZE + PORT_CLASS_DEVICE_EXTENSION_SIZE);

And this puppy PORT_CLASS_DEVICE_EXTENSION_SIZE is not zero at all,
from C:\WinDDK\6000\inc\ddk\portcls.h:

#define PORT_CLASS_DEVICE_EXTENSION_SIZE (64*sizeof(ULONG_PTR))

Otherwise I don’t see anything wildly wrong…
Hope it helps.

-------------- Original message --------------
From: xxxxx@gmail.com

Hello,

Firstly please excuse me if my question may seem a little stupid, that is
because I’m new to driver development.
I am trying to build a virtual sound driver starting from MSVAD sample from DDK
and now I’m confronted with the following problem: How do I get a user mode
application to talk to my miniport driver.
I see that MSVAD does not have any IRP dispatching functions and I read
somewhere that is because portclass.sys handles most of the IRPs.
However I found after some “googleing” that you can actually create your own
device object in addDevice from MSVAD and use it to receive IRPs that you pass
it from user mode.
So here is how it looks the modified addDevice:
NTSTATUS AddDevice
(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
{
PAGED_CODE();
NTSTATUS ntStatus;
NTSTATUS addAdDeviceStatus = STATUS_UNSUCCESSFUL;
PDEVICE_OBJECT deviceObject;
UNICODE_STRING usDeviceName;
UNICODE_STRING usDosDeviceName;
DPF(D_TERSE, (“[AddDevice]”));

// Tell the class driver to add the device.
//
ntStatus =
PcAddAdapterDevice
(
DriverObject,
PhysicalDeviceObject,
PCPFNSTARTDEVICE(StartDevice),
MAX_MINIPORTS,
0
);

if (!NT_SUCCESS(ntStatus))
{
return ntStatus;
}
addAdDeviceStatus = ntStatus;
DPF(D_TERSE, (“[Added Adapter driver]”));
RtlInitUnicodeString(&usDeviceName, MY_DEVICE_NAME);
RtlInitUnicodeString(&usDosDeviceName, MY_DOSDEVICE_NAME);

// Create the device
ntStatus = IoCreateDevice
(
DriverObject,
0,
&usDeviceName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&deviceObject
);

if(!NT_SUCCESS(ntStatus))
{
DPF(D_TERSE, (“[Failed IoCreateDevice…]”));
return addAdDeviceStatus;
}

deviceObject->Flags |= DO_BUFFERED_IO;

DPF(D_TERSE, (“[Device Created]”));

// Create the symbolic link
ntStatus = IoCreateSymbolicLink
(
&usDosDeviceName,
&usDeviceName
);
if (!NT_SUCCESS(ntStatus)) //try to delete the symbolic link first
{
DPF(D_TERSE,(“[Failed IoCreateSymbolicLink…]”));
IoDeleteDevice(DriverObject->DeviceObject);
return addAdDeviceStatus;
}
DPF(D_TERSE, (“[SymbolicLink Created]”));

// Initialize device object flags
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

return ntStatus;
} // AddDevice
I also added:
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=HMIDIDispatchDeviceControl;
in driver entry. I understand that I can use the device object address above to
see if the irp is for me so in the future I should probably add a device
extension to my device object but I’m not there yet. One question I have is if I
see that the IRP is not mine (MSVAD’s) how do I send it back to PORTCLS?

Ok, I built the driver in this form and saw that MY_DEVICE_NAME was created and
I built a simple user mode application(called testdevioctrl) which should
connect to the driver and send some IRP. The application causses portcls to
crash the code causing the crash is:

HANDLE hDevice; // handle to the drive to be examined
hDevice = CreateFile(_T(“\\.\hmidi”), // drive to open
0, // no access to the drive
FILE_SHARE_READ | // share mode
FILE_SHARE_WRITE,
NULL, // default security attributes
OPEN_EXISTING, // disposition
0, // file attributes
NULL); // do not copy file attributes

if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
{
_tprintf(_T(“Invalid handle\n”));
return (FALSE);
}

Windbg says:



Access violation - code c0000005 (!!! second chance !!!)
nt!__InterlockedIncrement+0x5:
80541ac1 0fc101 xadd dword ptr [ecx],eax
kd> !analyze -v
Connected to Windows XP 2600 x86 compatible target, ptr64 FALSE
Loading Kernel Symbols


Loading User Symbols

Loading unloaded module list

*** WARNING: Unable to verify checksum for testdevioctrl.exe
*** ERROR: Module load completed but symbols could not be loaded for vmx_fb.dll
*** ERROR: Module load completed but symbols could not be loaded for hgfs.sys
*** ERROR: Symbol file could not be found. Defaulted to export symbols for
drmk.sys -
*** ERROR: Module load completed but symbols could not be loaded for Afc.sys
*** ERROR: Symbol file could not be found. Defaulted to export symbols for
vmxnet.sys -
*** ERROR: Module load completed but symbols could not be loaded for vmscsi.sys
*** ERROR: Module load completed but symbols could not be loaded for
vmx_svga.sys
*** ERROR: Module load completed but symbols could not be loaded for vmmouse.sys
ERROR: FindPlugIns 8007007b
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************

Unknown bugcheck code (0)
Unknown bugcheck description
Arguments:
Arg1: 00000000
Arg2: 00000000
Arg3: 00000000
Arg4: 00000000

Debugging Details:

PROCESS_NAME: testdevioctrl.e

FAULTING_IP:
nt!__InterlockedIncrement+5
80541ac1 0fc101 xadd dword ptr [ecx],eax

EXCEPTION_RECORD: ffffffff – (.exr ffffffffffffffff)
ExceptionAddress: 80541ac1 (nt!__InterlockedIncrement+0x00000005)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000001
Parameter[1]: 00000080
Attempt to write to address 00000080

ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at “0x%08lx” referenced
memory at “0x%08lx”. The memory could not be “%s”.

WRITE_ADDRESS: 00000080

BUGCHECK_STR: ACCESS_VIOLATION

DEFAULT_BUCKET_ID: NULL_CLASS_PTR_DEREFERENCE

LAST_CONTROL_TRANSFER: from bac8c455 to 80541ac1

STACK_TEXT:
f7988a0c bac8c455 f7988a28 bac9d02a 00000000 nt!__InterlockedIncrement+0x5
f7988a14 bac9d02a 00000000 81e50f38 81e2dc00
portcls!IncrementPendingIrpCount+0x14
f7988a28 804edfe3 81e50bf8 82838f68 806d02e8 portcls!DispatchCreate+0x13
f7988a38 8064b8a8 82838f78 82838f68 81e2dcf8 nt!IopfCallDriver+0x31
f7988a5c 80577672 81e50be0 81e3639c f7988c04 nt!IovCallDriver+0xa0
f7988b3c 805b390a 81e50bf8 00000000 81e362f8 nt!IopParseDevice+0xa12
f7988bc4 805afdeb 00000000 f7988c04 00000040 nt!ObpLookupObjectName+0x56a
f7988c18 8056a3b1 00000000 00000000 00046001 nt!ObOpenObjectByName+0xeb
f7988c94 8056ad28 0012fe28 00100080 0012fdc8 nt!IopCreateFile+0x407
f7988cf0 8056d3fa 0012fe28 00100080 0012fdc8 nt!IoCreateFile+0x8e
f7988d30 8053ca28 0012fe28 00100080 0012fdc8 nt!NtCreateFile+0x30
f7988d30 7c90eb94 0012fe28 00100080 0012fdc8 nt!KiFastCallEntry+0xf8
0012fd84 7c90d68e 7c810916 0012fe28 00100080 ntdll!KiFastSystemCallRet
0012fd88 7c810916 0012fe28 00100080 0012fdc8 ntdll!NtCreateFile+0xc
0012fe20 004307a7 00000000 00000000 00000003 kernel32!CreateFileW+0x35f
0012ff54 00430fe2 00000001 00332f68 00333018 testdevioctrl!wmain+0x37
[d:\test\minidriver\testdevioctrl\testdevioctrl\testdevioctrl.cpp @ 21]
0012ffb8 00430d9d 0012fff0 7c816fd7 0007da50
testdevioctrl!__tmainCRTStartup+0x232
[f:\sp\vctools\crt_bld\self_x86\crt\src\crt0.c @ 327]
0012ffc0 7c816fd7 0007da50 7c90e1fe 7ffd6000 testdevioctrl!wmainCRTStartup+0xd
[f:\sp\vctools\crt_bld\self_x86\crt\src\crt0.c @ 196]
0012fff0 00000000 0042e5a0 00000000 78746341 kernel32!BaseProcessStart+0x23

STACK_COMMAND: kb

FOLLOWUP_IP:
portcls!IncrementPendingIrpCount+14
bac8c455 5d pop ebp

SYMBOL_STACK_INDEX: 1

SYMBOL_NAME: portcls!IncrementPendingIrpCount+14

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: portcls

IMAGE_NAME: portcls.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 41107f13

FAILURE_BUCKET_ID: ACCESS_VIOLATION_W_VRF_portcls!IncrementPendingIrpCount+14

BUCKET_ID: ACCESS_VIOLATION_W_VRF_portcls!IncrementPendingIrpCount+14

Followup: MachineOwner


Now I have a few more questions, the obvious would be why does it crash? Another
is if there is another possibility to access MSVAD directly without going
through the entire driver stack?

Best regards,
Cristi


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

An extension size of 0 is OK in PcAddAdapterDevice, in fact, unless you are storing some per-device data in the extension (usually the miniport-level objects you create are a much better place), 0 is the BEST value to use.

The proper and easy way to test a portcls miniport is to use the user mode API appropriate to that port (I’m guessing from some of the names in the original post, this is Midi, in which case you can use the midiInxxx or midiOutxxx API, as appropriate).

What you are doing is actually quite broken [but I’ve also seen people ship drivers broken this very way, and I would have hoped they’d know better]. In terms of what I think you’re trying to do, it also isn’t going to work with anything except some custom piece of software you write for yourself, which I doubt is what you really want.

Yes, PortCls handles dispatch for all IRPS (it calls your miniport interfaces when they are needed)- you have taken over IRP_MJ_DEVICE_CONTROL and left all the others to it.

You are crashing because the file open results in an IRP_MJ_CREATE to YOUR device, and you’ve left the handling to PortCls- well PortCls doesn’t even know your device exists, so it assumes it is one of its own, tries to do its own device management with a device extension that in your case doesn’t even exist [and in other cases I’ve seen is completely different size, content, format, intent, etc.], and not too surprisingly, that doesn’t work very well at all…

If you are going to intercept the dispatch table and filter requests based upon device object, then you need to do it for EVERY SINGLE MAJOR FUNCTION PortCls handles, and to do THAT properly isn’t trivial, since we really have no obligation to inform you if we change them for any reason. So safer yet is to grab every single major function, and pass any that don’t match your device to PcDispatchIrp.

My own preference, though, is to record the original dispatch routines in a driver global and chain to them directly, because frankly I don’t trust PcDispatchIrp- IIRC, the handling isn’t always identical, and that has sometimes been a problem. That’s just my opinion, though- go to the wdm audio mailing list if you want input from an “official” source.

I would strongly recommend NOT creating an additional device object and filtering it as you have been attempting, except as a last resort [a bus driver reporting the audio and non-audio devices separately would be better, especially since you can use KMDF for that sort of thing].

[Yes, I left out context for this post, but man, it’s huge and I hate to waste any more space on this].

Sorry if some of that sounds like a rant- at one point in my life, I invested a great deal of time on this issue, and in the end, a lot of it was essentially wasted.

Hello,

I would like to thank everyone who responded to my post.

The proper and easy way to test a portcls miniport is to use the user mode API appropriate to that port (I’m guessing from some of the names in the original post, this is Midi, in which case you can use the midiInxxx or midiOutxxx API, as appropriate).

Yes it is a midi out port the port that I got by modifying the msvad sample and it seems to work because I get in IMiniportMidiStream::Read and IMiniportMidiStream::Write the data from user mode however this is only half of the problem.
I would like another application (also developed by me) to be able to send data to the driver that the driver outputs to the midi port and that is why I built the extra device.

You are crashing because the file open results in an IRP_MJ_CREATE to YOUR device, and you’ve left the handling to PortCls- well PortCls doesn’t even know your device exists, so it assumes it is one of its own, tries to do its own device management with a device extension that in your case doesn’t even exist [and in other cases I’ve seen is completely different size, content, format, intent, etc.], and not too surprisingly, that doesn’t work very well at all…

Ok in my first post the crash seemed to be caused because I didn’t forward the IRP_MJ_DEVICE_CONTROL IRP to portclass, started forwarding the IRP and then it didn’t crash anymore. However still there is a problem because the documentation says I’m responsible for deleting the device I created I tried intercepting IRP_MN_REMOVE_DEVICE an deleting it that but that caused a crash that is probable because portcls is using my device somehow i will look into it better tomorrow. Is there a better place for deleting my device?

So safer yet is to grab every single major function, and pass any that don’t match your device to PcDispatchIrp.

That is what I am doing now.

My own preference, though, is to record the original dispatch routines in a driver global and chain to them directly, because frankly I don’t trust PcDispatchIrp- IIRC, the handling isn’t always identical, and that has sometimes been a problem. That’s just my opinion, though- go to the wdm audio mailing list if you want input from an “official” source.

Thank you for this information.

I would strongly recommend NOT creating an additional device object and filtering it as you have been attempting, except as a last resort [a bus driver reporting the audio and non-audio devices separately would be better, especially since you can use KMDF for that sort of thing].

As I said I’m new to driver development and not quite sure how to build “a bus driver reporting the audio and non-audio devices separately” and I didn’t ever use KMDF as far as I know. Building an extra device seemed to me the easiest way to talk to my driver, but I am opened to better suggestions.

Best regards,
Cristi

Bob Kjelgaard wrote:

If you are going to intercept the dispatch table and filter requests
based upon device object, then you need to do it for EVERY SINGLE
MAJOR FUNCTION PortCls handles, and to do THAT properly isn’t
trivial, since we really have no obligation to inform you if we change
them for any reason.

Is hooking portcls’ dispatch routine’s “forbidden” by WHQL like it is for NDIS?

I’m afraid I don’t know the current WHQL requirements for audio [never had to- I was either root causing problems from OCA and similar sources, or maintaining portcls / ks / sysaudio, etc.- I’ve never had to ship an audio driver, and since I was “hired maintenance help”, there really wasn’t any reason for me to know that end of things- if the issue came up, I’d refer it to one of the folks you could reach from the wdm audio list].

But this technique was illustrated (IIRC, in a broken fashion) in one of the old samples [sb16?]. So there may be some legacy that’s hard to shake.

Most of the time I encountered it, it was drivers for sound cards that also included game ports and/or modems. Problem was, they usually hooked only the functions they expected to see sent to their extra devices. That’s fine if you own the driver- the rest all get routed to an OS function that completes them with a failing status (STATUS_INVALID_DEVICE_REQUEST, IIRC). Not such a great idea if you’re trying to coexist.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Thursday, July 19, 2007 9:50 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Portclass minidriver interaction

Bob Kjelgaard wrote:

If you are going to intercept the dispatch table and filter requests
based upon device object, then you need to do it for EVERY SINGLE
MAJOR FUNCTION PortCls handles, and to do THAT properly isn’t
trivial, since we really have no obligation to inform you if we change
them for any reason.

Is hooking portcls’ dispatch routine’s “forbidden” by WHQL like it is for NDIS?

A correction on my part (perhaps slightly OT, but conscience compels me):

>
My own preference, though, is to record the original dispatch routines in a driver global and chain to them directly, because frankly I don’t trust PcDispatchIrp- IIRC, the handling isn’t always identical, and that has sometimes been a problem. That’s just my opinion, though- go to the wdm audio mailing list if you want input from an “official” source.
<<

Should have simply struck that thought, for a bunch of reasons (among them, I routinely see and fix [and thus later, dimly recall] problems that never ship because I saw and/or fixed them). All I meant by the quotes was that I believe you won’t get an official statement in a non-Microsoft forum, although you can and do get authoritative ones. The folks who still own and maintain this stuff tend to hang out there, so I meant to suggest one might get something better than my paranoid opinion from them. In retrospect, the quotes give the opposite impression…