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

  • Anonymous
    August 23, 2006
    In my last post I showed how you can distinguish between to
    different device interfaces being opened...

  • Anonymous
    October 03, 2007
    Ever wonder how the creation of a handle works? It doesn't matter type of resource the handle you are

  • Anonymous
    July 27, 2010
    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.

  • Anonymous
    July 26, 2011
    Thanks Doron Holan. This is really helpful. i was exactly look for same use case.

  • Anonymous
    September 11, 2013
    @ Jose E. Menezes The API you are using "WdfRequestGetFileObject(Request));" is returning always 0 (Zero) . Please let me know about it.

  • Anonymous
    September 11, 2013
    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 .

  • Anonymous
    September 12, 2013
    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.

  • Anonymous
    September 15, 2013
    Yes i got your point  thanks Doron Holan .