How do I know which device interface is being opened?


Let’s say your device supports two interfaces and you want to expose both of them
on the same device object. Furthermore, let’s say that the I/O interface to each
device interface is different. For instance, let’s say that one interface allows
only one create (e.g. it is exlusive) while the other allows unlimited handles
opened against it. How can you enforce such a policy in your create dispatch routine?

Well this is what the ReferenceString parameter
is for in the call to IoRegisterDeviceInterface
(or WdfDeviceCreateDeviceInterface in KMDF). It allows you
to distinguish between the two interface. In the create dispatch routine, the
reference string will be passed to your driver in the FileName field of the
PFILE_OBJECT. So all you have to do is a string compare and you are done…
but there is a catch! There will be a ‘\’ as the first character and then the
remaining string, so you must account for the ‘\’ as well.
Let’s see how you specify the reference string in your registration call and then
check for it in your create dispatch routine.


#define EXCLUSIVE_STR L”Exclusive”

NTSTATUS DeviceInit(WDFDEVICE Device)
{

UNICODE_STRING refExclusive;

RtlInitUnicodeString(&amprefExclusive, EXCLUSIVE_STR);

WdfDeviceCreateDeviceInterface(device, &ampGUID_DEVINTERFACE_EXCLUSIVE, &amprefExclusive);
WdfDeviceCreateDeviceInterface(device, &ampGUID_DEVINTERFACE_NON_EXCLUSIVE, NULL);

[…]
}

VOID EvtDeviceFileCreate(WDFDEVICE Device, WDFREQUEST Request, WDFFILEOBJECT FileObject)
{
PCUNICODE_STRING pName;
UNICODE_STRING refExclusive;

RtlInitUnicodeString(&amprefExclusive, L”\\” EXCLUSIVE_STR);

pName = WdfFileObjectGetFileName(WdfRequestGetFileObject(Request));

if (RtlCompareUnicodeString(pName, &amprefExclusive, TRUE) == 0x0) {
// opening GUID_DEVINTERFACE_EXCLUSIVE, verify exclusive access…
}
else {
// opening GUID_DEVINTERFACE_NON_EXCLUSIVE…
}

[…]
}

But there is a problem! How you can tell if the application meant to open
GUID_DEVINTERFACE_EXCLUSIVE, but left off the reference string and opened
GUID_DEVINTERFACE_NON_EXCLUSIVE instead? You can fix this by using a reference
string for both device interfaces and fail creates if either the wrong or no reference string
is given.


#define EXCLUSIVE_STR L”Exclusive”
#define NON_EXCLUSIVE_STR L”NonExclusive”

NTSTATUS DeviceInit(WDFDEVICE Device)
{

UNICODE_STRING refExclusive, refNonExclusive;

RtlInitUnicodeString(&amprefExclusive, EXCLUSIVE_STR);
RtlInitUnicodeString(&amprefNonExclusive, NON_EXCLUSIVE_STR);

WdfDeviceCreateDeviceInterface(device, &ampGUID_DEVINTERFACE_EXCLUSIVE, &amprefExclusive);
WdfDeviceCreateDeviceInterface(device, &ampGUID_DEVINTERFACE_NON_EXCLUSIVE, &amprefNonExclusive);

[…]
}

VOID EvtDeviceFileCreate(WDFDEVICE Device, WDFREQUEST Request, WDFFILEOBJECT FileObject)
{
PCUNICODE_STRING pName;
UNICODE_STRING refExclusive, refNonExclusive;

RtlInitUnicodeString(&amprefExclusive, L”\\” EXCLUSIVE_STR);
RtlInitUnicodeString(&amprefNonExclusive, L”\\” NON_EXCLUSIVE_STR);

pName = WdfFileObjectGetFileName(WdfRequestGetFileObject(Request));

if (RtlCompareUnicodeString(pName, &amprefExclusive, TRUE) == 0x0) {
// opening GUID_DEVINTERFACE_EXCLUSIVE, verify exclusive access…
}
else if (RtlCompareUnicodeString(pName, &amprefNonExclusive, TRUE) == 0x0) {
// opening GUID_DEVINTERFACE_NON_EXCLUSIVE…
}
else {
// fail the create, bad reference string
}

[…]
}

Comments (8)

  1. In my last post I showed how you can distinguish between to

    different device interfaces being opened…

  2. Ever wonder how the creation of a handle works? It doesn’t matter type of resource the handle you are

  3. Jonson says:

    How can I set different security policy for the two interface? For example the EXCLUSIVE interface is only for administrator, and the NONEXCLUSIVE one is for every users.

  4. venkatesh says:

    Thanks Doron Holan. This is really helpful. i was exactly look for same use case.

  5. Jitendra Singh says:

    @ Jose E. Menezes

    The API you are using "WdfRequestGetFileObject(Request));" is returning always 0 (Zero) .

    Please let me know about it.

  6. Jitendra Singh says:

    Hi All,

    I am working with KMDF so at some instance i got stuck beacause

    How do I know which device interface is being opened?

    The API used in above example code "WdfRequestGetFileObject(Request));" is returning always 0 (Zero) .

    So when i passing this to WdfFileObjectGetFileName(0) causing System Crash.

    Please Help me .

  7. To successfully get a WDFFILEOBJECT, you need to tell WDF you want them, so you need to call WdfDeviceInitSetFileObjectConfig in EvtDriverDeviceAdd. Also, note that the file name is only valid during EvtDeviceFileCreate. If you are interested in doing something based on the file name, check it in EvtDeviceFileCreate and store some kind of flag in your context off of the WDFFILEBOBJECT (the context you specify in the call to WdfDeviceInitSetFileObjectConfig) and check that flag in subsequent IO on that file object.

  8. Jitendra Singh says:

    Yes i got your point  thanks Doron Holan .