(Newbie) KMDF EvtIoDeviceControl / EvtIoRead never called

I’m playing with the ramdisk example. I’d like to make it fit the KMDF template and also strip all FAT code from it (I WANT to format the resulting drive by hand).
I started from KMDF template and implemented a few basic methods from ramdisk sample such as DeviceIoControl, IoRead and IoWrite. I did not include the FAT / preformatting stuff or forward progress functionality.

Effectively I only wrote those three functions on top of the template. What I understand from docs, this should be enough to get some basic functionality, but I got stuck: none of the queue methods ever get to be called.

The last confirmed action (TraceView) is successful queue creation, but there it stops. I can see that the RAM for my ramdisk was allocated in kernel, but disk management shows no device and there’s also no indication that it might be available. Driver is nicely visible in device manager, but the device it creates is not.

What am I forgetting?

Can you explain further what you mean by this?

How are you creating your WDFDEVICE? Are you giving it a name? What name? How are you trying to open it from your user-mode application?

Peter
OSR
@OSRDrivers

Well, the device is created like this:

 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&deviceAttributes, DEVICE_CONTEXT);  
 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_DISK);  
 WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoDirect);  
 WdfDeviceInitSetExclusive(DeviceInit, FALSE);  
  
deviceAttributes.EvtCleanupCallback = VVDDeviceCleanup;  
  
status = WdfDeviceCreate(&DeviceInit, &deviceAttributes, &device);  
  
//Later on when device is created successfully  
 status = WdfDeviceCreateDeviceInterface(device, &GUID_DEVINTERFACE_VVD, L"VVD01");  
  

and the queue like this:

 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchParallel);  
  
queueConfig.EvtIoDeviceControl = VVDEvtIoDeviceControl;  
 queueConfig.EvtIoRead = VVDEvtIoReadWrite;  
#pragma warning(suppress: 28024) // This is because I handle both reading and writing in the same function  
 queueConfig.EvtIoWrite = VVDEvtIoReadWrite;  
 queueConfig.EvtIoStop = VVDEvtIoStop;  
  
status = WdfIoQueueCreate(Device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, &queue);  

Is this sufficient information? I can archive the entire project, but I’m afraid it’s pretty much the template boilerplate code right now.

It’s helpful, but you didn’t answer all my questions. I assume you mean “I don’t see the drive letter R: show up anywhere”???

OK… so I went to read the RAM disk sample.

You *do* call WdfDeviceCreateSymbolicLink, right?? You execute that code (that isn’t particularly well commented) in the example that comes RIGHT AFTER the call to RamDiskFormatDisk?

Peter
OSR
@OSRDrivers



Our friends at Microsoft aren’t doing the community any favors by including this sample in the WDK. I realize it’s an interesting example of using the guaranteed forward progress DDIs (I assume somebody wrote it to either learn or test those DDIs), but I’m sure we could find a better way to illustrate these if we got together and thought about it some.

The problem is that this sample doesn’t illustrate the correct way to create a pseudo storage device on Windows, it doesn’t interface with the mount manager to claim its drive letter, and it hard formats the partition to FAT.

So, it’s a CUTE sample, but it really has the potential to lead people astray: “Look! Here’s how you create a disk drive on Windows!” Yeah… not so much. Try to run IOMETER on it. It won’t even show UP in many interfaces as a disk drive.

Peter
OSR
@OSRDrivers

That concludes my pontification for today.

No, I don’t call WdfDeviceCreateSymbolicLink specifically because the documentation says that WdfDeviceCreateDeviceInterface replaces that. I will try it as well, but I’m not holding my breath for it.

That said, I know ramdisk sample is not good. In fact, I have some proper WDM code on my hands that somebody once made for me, but I find that hard to maintain. So I wanted to move to MS promoted KMDF to gain all the IDE perks. I’m moving the driver over step-by-step and really want to understand why things happen when they do. So, initially I just wanted to get some response from the framework before proceeding to PnP and other features.

I have now included the WdfDeviceCreateSymbolicLink call. It made no difference whatsoever.

OK. Then I clearly do not understand what you’re expecting to see.

Your driver loads without error. Please expect what you EXPECT to see as a result, how you’re testing that, and what you actually ARE seeing instead.

Once we have your driver doing what you expect it to do, we can discuss whether the WDM code you have creates a proper pseduo-device. I doubt it does, unless it’s device type is GENDISK. And, yes… using WDF is definitely superior to using WDM.

Sooo… for now… explain what you expect to see, and what you’re not seeing. IF you expect to see a drive letter pop-up automagically in Windows File Explorer, you *definitely* need to create the symbolic link (where else would it get the drive letter… I assume you’re not asking the Mount Manager to assign a drive letter for it). If you’re creating the symbolic link and it’s not showing up in File Explorer automatically (the way a drive letter shows up when you plug in a USB drive) that’s to be expected. File Explorer relies on receiving a windows message to prompt it to look for new drive letters to be created. So you need to refresh File Explorer.

Peter
OSR
@OSRDrivers

OK, first: thanks for taking so much time for me. I really apreciate that.

Now to answer you, what I’m expecting and what happens instead:

  1. I assumed device would only be created on some PnP call. Instead, one is created immediately without any additional code / triggers. Of course, there’s no PnP code in the template so I must be missing something obvious here.

  2. Once a device is created, kernel / framework was supposed to at least query its parameters –> call EvtIoDeviceControl

  3. Since I’m telling kernel that my devices are disk drives, I was expecting these drives to appear in Computer management / Disk management. Naturally, I DO click “refresh” to check for this. I did not expect this drive to appear in Windows Explorer since it isn’t formatted and drive letter isn’t assigned.

  4. WdfDeviceCreateDeviceInterface: From what I understand in docs, this function is supposed to provide a communications path with user mode apps. How exactly I’m supposed to do that, I don’t know yet. I have downloaded the NonPnP sample which supposedly demonstrates this.

  5. WdfDeviceCreateSymbolicLink: The documentation states that WdfDeviceCreateDeviceInterface supersedes this function, so I didn’t even intend to use this function. Honestly, ramdisk sample tries to assign drive letter Z by default and I thought this function to be one of its bad practices. That said, while playing around with CreateSymbolicLink, I got INVALID_PARAMETER just for providing an arbitrary string. Perhaps even my final “\DosDevices\Z” string was inadequate.

  6. I also have issues with general communications concepts: The driver itself doesnt seem to have any comms code. The first hint of any comms is WdfDeviceCreateDeviceInterface, but like mentioned, I don’t see how this can serve any communication. Looking at the WDM driver, all user-mode comms are done through DeviceIoControl, but I guess in WDM that function also takes driver comms, not just device comms as is designed in KMDF.

Whew, I really hope I wasn’t too long. Thanks in advance for clearing up any of these points.

You can only just device interfaces with a pnp driver, NonPnP can only use symbolic links to expose a name to user mode

d

Bent from my phone


From: xxxxx@gmail.commailto:xxxxx
Sent: ?2/?28/?2015 1:33 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: RE:[ntdev] (Newbie) KMDF EvtIoDeviceControl / EvtIoRead never called

OK, first: thanks for taking so much time for me. I really apreciate that.

Now to answer you, what I’m expecting and what happens instead:

1. I assumed device would only be created on some PnP call. Instead, one is created immediately without any additional code / triggers. Of course, there’s no PnP code in the template so I must be missing something obvious here.

2. Once a device is created, kernel / framework was supposed to at least query its parameters –> call EvtIoDeviceControl

3. Since I’m telling kernel that my devices are disk drives, I was expecting these drives to appear in Computer management / Disk management. Naturally, I DO click “refresh” to check for this. I did not expect this drive to appear in Windows Explorer since it isn’t formatted and drive letter isn’t assigned.

4. WdfDeviceCreateDeviceInterface: From what I understand in docs, this function is supposed to provide a communications path with user mode apps. How exactly I’m supposed to do that, I don’t know yet. I have downloaded the NonPnP sample which supposedly demonstrates this.

5. WdfDeviceCreateSymbolicLink: The documentation states that WdfDeviceCreateDeviceInterface supersedes this function, so I didn’t even intend to use this function. Honestly, ramdisk sample tries to assign drive letter Z by default and I thought this function to be one of its bad practices. That said, while playing around with CreateSymbolicLink, I got INVALID_PARAMETER just for providing an arbitrary string. Perhaps even my final “\DosDevices\Z<file:>” string was inadequate.

6. I also have issues with general communications concepts: The driver itself doesnt seem to have any comms code. The first hint of any comms is WdfDeviceCreateDeviceInterface, but like mentioned, I don’t see how this can serve any communication. Looking at the WDM driver, all user-mode comms are done through DeviceIoControl, but I guess in WDM that function also takes driver comms, not just device comms as is designed in KMDF.

Whew, I really hope I wasn’t too long. Thanks in advance for clearing up any of these points.


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

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

I’m going to answer each of your points, above, as best I can. But the bottom line is: You really need to do some reading… or better yet, take one of the classes we teach at OSR… before you waste much more of your time. Because, and I mean this with all due respect, you really don’t know what you’re doing. You’re missing a lot of basic concepts. AND you’re working from a sample that works only in certain circumstances, and even then only because of some quirks or tricks.

So, really… you could spend a whole lot of time on this and not wind up with anything of much value. But if you’re certain you want to do this, you will have to spend the time to learn a bit about WDF. I’ve taught THOUSANDS of people, literally, all over the world, to write Windows drivers. And I can tell you one thing for certain: Driver writing does *not* lend itself to “just take a sample and start hacking on it and figure out and learn stuff on the way.” I realize a LOT of user-mode programming works that way. But, sincerely, driver development does not.

So… if you want to learn how to write a WDF Driver, start with something ultra simple like the USB FX2 sample, which you can learn in stages. That’ll get you set with basic WDF concepts. THEN learn a bit about pseduo-devices. THEN you can attempt to tackle your WDF RAM disk driver. If you still want to. And I advise you don’t.

OK, on to your questions.

Well, in fact, it IS created as a result of a PnP Call. You’re called at EvtDriverDeviceAdd, and that’s where you call WdfDeviceCreate. As soon as you call this function, viola! You have a device! It’s no different from calling IoCreateDevice in WDM.

Ah… no. The kernel / Framework doesn’t query any parameters by sending you a device control.

Well… To be honest, I can’t recall exactly WHAT triggers a device to show up in Disk Management. If nobody jumps in and tells you, I’ll try to remember to ask my colleagues on Monday. I’m sure one of them (who wrote the code) will remember. But it doesn’t matter in any case, because I don’t think you’re close enough that this matters.

[quote]
WdfDeviceCreateDeviceInterface: From what I understand in docs, this function
is supposed to provide a communications path with user mode apps. How exactly
I’m supposed to do that, I don’t know yet.

Yes, this is true. And, if you want to write a user-mode app that opens the device interface using the GUID you’ve specified, you could indeed send read, write, and device control requests to your device for processing by your driver.

The PROBLEM is you don’t WANT “user mode apps” to be able to communicate with your device. You want to trick Windows into thinking your device is a Disk Drive. One talks to disk drives via drive letters, not via device interfaces.

Well, it doesn’t actually say it SUPERSEDES WdfDeviceCreateSymbolicLink. And, the entire driver your writing doesn’t “play by the rules” in any case… because it’s not even attempting to create a proper pseudo device. And, to be honest… there’s absolutely, positively, completely, nothing wrote with calling WdfDeviceCreateSymbolicLink. It’s not bad practice IN THE RIGHT CIRCUMSTANCE.

Well, you user-mode app opens the created device interface using CreateFile. The way you get the NAME to open is using the SetupDiXxxx family of functions. There ARE examples that show you how to do this.

Once your user-mode app has a file handle opened to your device, if it calls ReadFile with that handle, your driver will be called in your EvtIoRead event processing callback. If it calls WriteFile, your driver will be called at EvtIoWrite. If it calls DeviceIoControl, your driver will be called at EvtIoDeviceControl.

That’s a gross over simplification, but it’s good enough for now.

I’m very sorry. But, and again I mean this will all due respect, you are not likely to be successful in your pursuit with your current level of knowledge. If you want to increase your knowledge and thus your chances of success, stop and read Orwick and Fischer, or take a seminar, or start by writing a very, very, simple example driver. The RAMDISK sample is not such a sample.

Peter
OSR
@OSRDrivers

AH! If the RAMDISK sample isn’t a PNP driver (I’m at home and I don’t have immediate access to the WDK Samples) then what Doron says is 100% right… and what I said previously is not correct.

You see… this shit can be tricky.

What I wrote earlier assumed the RAMDISK sample was a PnP software-only WDF driver. If it is a non-PNP driver, what I said about using the device interface or being called in EvtDriverDeviceAdd is not correct… though the bottom line message is the same: You need to learn more about WDF before you’re likely to be successful.

Peter
OSR
@OSRDrivers

I don’t know if the sample is pnp or not

d

Bent from my phone


From: xxxxx@osr.commailto:xxxxx
Sent: ?2/?28/?2015 4:03 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: RE:[ntdev] (Newbie) KMDF EvtIoDeviceControl / EvtIoRead never called



AH! If the RAMDISK sample isn’t a PNP driver (I’m at home and I don’t have immediate access to the WDK Samples) then what Doron says is 100% right… and what I said previously is not correct.

You see… this shit can be tricky.

What I wrote earlier assumed the RAMDISK sample was a PnP software-only WDF driver. If it is a non-PNP driver, what I said about using the device interface or being called in EvtDriverDeviceAdd is not correct… though the bottom line message is the same: You need to learn more about WDF before you’re likely to be successful.

Peter
OSR
@OSRDrivers


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

OSR is HIRING!! See http://www.osr.com/careers

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

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

I think it is not. It doesn’t contain any PnP code, at least if I compare it to my WDF driver.
In addition, it only supports one ramdisk and contains no comms whatsoever handling new device instantiations / disposals.

Peter, thanks for all the answers so far.
I have decided to still attempt to move the WDM code over and see where that takes me. I definitely know my driver-writing experience is pretty much nil right now and samples for what I’m trying to accomplish are scarse at best, but I’m willing to invest another week into this. I’ll try to ask more informed questions from now on. That said, my reading is based on MSDN online help documentation and while extensive, it really isn’t geared towards beginners (even though knowledge in those pages is attempted to be beginner-level).

Just to clarify a few points:

  • I’d appreciate it if you asked your colleagues about what makes a device appear as a disk.
  • I know I’m not supposed to communicate with devices. But I do have to communicate with the driver in order to tell it to instantiate another device when needed - or destroy it when appropriate. I need PnP triggers with appropriate parameter passing for that.
  • I’m not sure why you think my driver doesn’t play by the rules. Ultimately all drivers are software even if they turn out communicating with actual hardware. Mine just needs an existing lower level driver, in this case RAM and network. Unless of course writing a disk driver is against the rules under all circumstances.

Thanks for all your help so far. I know it’s hard to help such a n00b as me and this is already more than I expected. I’m definitely not offended by you telling me that I don’t know enough, that’s exactly why I started asking. OSR seems like the perfect place for that, but I really need to learn more first. I just hoped you guys could fill in the blanks for me while I port my driver. I still think there aren’t going to be that many, but I’ll try to gain more knowledge before asking more.

The toaster bus driver (and friends) sample does exactly this. Just change the identifiers for “toaster” to identifiers for “disk”. Then change the behaviors for the “toaster” to the behaviors for “disk”.

I use quotes because I guarantee that the identifiers will not be those strings.

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Sunday, March 01, 2015 9:56 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] (Newbie) KMDF EvtIoDeviceControl / EvtIoRead never called

[snip]

> - I know I’m not supposed to communicate with devices. But I do have to communicate with the driver in order to tell it to instantiate another device when needed - or destroy it when appropriate. I need PnP triggers with appropriate parameter passing for that.

[snip]

Mr. Erznoznik,

First of all, I apologize for the forum (and now me) mangling your surname. I’ll refer to you as Mr. “Erznoznik”… if you prefer a better formulation, please let me know.

OK… where to start? Let’s go back to the very beginning.

There are two major categories of problems you are encountering:

  1. The RAMDISK sample is cute, but it is *not* a proper example of how to create a virtual disk drive. I think I’ve said this before, right? Because the RAMDISK sample doesn’t create a virtual DISK. It actually creates a virtual VOLUME.

You *could* write a proper WDF driver that creates a virtual DISK. But the best way forward it probably for you to create a StorPort Virtual Miniport driver that creates a virtual disk.

StorPort Miniports are not WDF drivers. They are their own special kind of driver. This is why I’ve been saying the RAMDISK driver is not a good example, and does everyone who touches it more harm than good.

BTW, the WDF RamDisk sample in the Windows 8.1 WDK *is* indeed a software-only PnP driver. You can definitively see this from the fact that in DriverEntry, the driver calls WdfDriverCreate and provides a pointer to an EvtDriverDeviceAdd event processing callback. Also, note that the driver is installed using an INF file. So… this is definitely is a PnP driver. Hence, all my previous comments do indeed apply.

  1. You don’t yet know enough about Windows drivers or I/O Subsystem architecture to do what you’re trying to do.

I’m sorry this has been such a mess for you. I know the RAMDISK sample looks like it should be a good place to start. But it’s not. This is why I hope our friends at Microsoft see if to remove the sample from the WDK. It’s just not a good thing.

I hope that helps,

Peter
OSR
@OSRDrivers

Thanks, this helped immensely. I went looking for a StorPort sample and discovered that my existing driver is actually a StorPort implementation. The code was practically identical, except for the implementation / functionality details, of course.

I guess my attempt was futile from the start. Though I did like the framework’s design. It “promised” to remove all the PDO / FDO stuff which I initially thought to be part of PnP implementation. Well, it is - in a way. Effectively my KMDF driver was just the actual workload functions - had it actually worked.

Like I said, I don’t know enough and I find it hard to understand why a disk driver has to be written in this particular way. I did not find the actual function call in my existing driver that would obviously make my driver properly register a disk drive. I guess just everything together does that.

Also thanks for clearing up the volume vs device part with the ramdisk example. I also figured out in the mean time that KMDF actually takes care of PnP functionality, which again is very nice. Thanks for confirming this.

P.S. I changed my name to use non-accented characters when I saw the encoded string, but forum software doesn’t want to hear about it and still uses the original name. Your “simplification” is the correct one.

I’m glad to hear it.

I should have put you on that track sooner, but I became focused on trying to solve you “how can I make the RAMDISK sample work” problem.

Glad you got things sorted in the end…

Peter
OSR
@OSRDrivers