Hello,
I am learning how to develop drivers for Windows and I can’t understand concept of providing interface to applications in user space. I am used to UNIX model - driver (module) registers a filename in system and passes set of callback funtions (for reading and writing to the virtual file).
I’ve been reading MSDN for hours, however I wasn’t able to find any article which deals with providing interface to user space on level I can understand. What articles should I read? What is a good starting point for this topic?
Typically a plug an play driver will provide a device interface see
http://msdn.microsoft.com/en-us/library/windows/hardware/ff545432(v=vs.85).a
spx For functions, assuming a WDF driver, you typically create a WDF Queue
http://msdn.microsoft.com/en-us/library/windows/hardware/ff547401(v=vs.85).a
spx registering the callbacks for the specific operations, i.e. read, write,
device IO control you want.
Don Burn
Windows Driver Consulting
Website: http://www.windrvr.com
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@honzamrazek.cz
Sent: Friday, October 31, 2014 8:14 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] How to provide interface for user apps?
Hello,
I am learning how to develop drivers for Windows and I can’t understand
concept of providing interface to applications in user space. I am used to
UNIX model - driver (module) registers a filename in system and passes set
of callback funtions (for reading and writing to the virtual file).
I’ve been reading MSDN for hours, however I wasn’t able to find any article
which deals with providing interface to user space on level I can
understand. What articles should I read? What is a good starting point for
this topic?
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
Just like in Unix, in Windows applications communicate with drivers by read/write/ioctl requests. The old way of naming device files was to make names known to applications beforehand. PNP drivers allow to generate GUID-based names (interfaces), and there is a set of usermode API calls to enumerate currently existing devices with these names. GUID-based interfaces are persistently bound to the device instances. They don’t change across reboots.
Thank you for your answers! I’ve read the articles, but I still have no idea, how to implement it. Is there any sample for this in the Windows Driver Kit (WDK) 8.1 Samples?
Take a look at the Toaster Sample Driver then under KMDF look at the func
directory. There is both a simple and a featured version of the driver, the
simple is a good starting point.
Don Burn
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@honzamrazek.cz
Sent: Saturday, November 01, 2014 6:36 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] How to provide interface for user apps?
Thank you for your answers! I’ve read the articles, but I still have no
idea, how to implement it. Is there any sample for this in the Windows
Driver Kit (WDK) 8.1 Samples?
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
On Nov 1, 2014, at 3:36 PM, xxxxx@honzamrazek.cz wrote:
Thank you for your answers! I’ve read the articles, but I still have no idea, how to implement it. Is there any sample for this in the Windows Driver Kit (WDK) 8.1 Samples?
You use WdfDeviceCreateDeviceInterface to create the device interface. You will create your own GUID as the name of this interface.
Then, you use the SetupDi interfaces from user mode to search all devices to find the ones with your interface. That will give you a fancy long file name, and from there on it?s exactly like the Unix model. You pass that file name to CreateFile, and send ioctls with DeviceIoControl. There are lots of examples on the web showing how to use SetupDiEnumDeviceInterfaces to find a device. The APIs are a little wordy, but it?s boilerplate. Once you have the snippet, you?ll use it over and over.
It is still possible to assign a simple file name to your device, to eliminate the SetupDi dance. The problem is that makes it much more difficult to handle multiple instances in a reliable way.
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
On 02-Nov-2014 06:45, Tim Roberts wrote:
…
and from there on it’s exactly like the Unix model. You pass that file name to CreateFile, and send ioctls with DeviceIoControl.
It’s worth mentioning here that Windows strongly prefers ioctls for
device interfaces over reads & writes - unlike the Other OS that
discourages ioctls.
This is a pity, because reads & writes are so easy to use, even in
simple shell scripts. With ioctls (aka DeviceIoControl) you have to make
some API-like wrappers, function codes, and things go haywire.
Also, as in the Other OS, Windows allows “namespaces” under the device
base name ( /dev/foo/featureA, /dev/foo/featureB …) but this takes
more work than adding functions to DeviceIoControl.
And there is a sysfs-like thing called WMI. Don’t go there unless you
must 
– pa
If you’re presently confused, ignore all the advice to use a device interface.
In EvtDriverDeviceAdd, assign a name to the device you’re creating (using WdfDeviceInitAssignName). Assign a name like “\Device\MyDevice” (you’ll need to “escape” the backslashes in a C-Language quoted string of course). Create the device (using WdfDeviceCreate). Then, to make your device accessible by name, assign a symbolic link to your device. The symbolic link name must be in the "\Global??" namespace… for example “\Global??\MyDevice” (yes, the question marks are actually a literal part of the syntax, not a wildcard character or anything).
OK so far?
Note that the above will work for only ONE device… because device names must be unique, and every device you create using the above instructions will be named \Device\MyDevice. Don’t worry about this right now. Just create only one device instance.
Get your driver loaded. You should be able to see the device created by your driver in Device Manager.
NOW… back in user mode, assuming the example names we’ve been using above, use the Win32 API function CreateFile to open the device you created using its symbolic link name:
hFile = CreateFile(“\.\MyDevice”,…);
Again, note that you’ll need to escape those backslashes in the string… and YES, you DO REQUIRE the "\." before your device name (this tells Windows the device you’re opening is on the current system).
ONCE YOU GET THIS WORKING then you can start to think about device interfaces. DO NOT think about device interfaces before that time.
And, also… ignore stuff like WPP Tracing for now. That just adds more complexity and can lead to additional confusion.
Peter
OSR
@OSRDrivers
>Is there any sample for this in the Windows Driver Kit (WDK) 8.1 Samples?
Yes there plenty of samples using device interfaces, probably too much to point to one particular sample.
A better solution is to download Visual Studio 2013 Express Edition. You can now build drivers with this edition. The WDK 8.1 is integrated with Visual Studio 2013. Just create a new KMDF Kernel Mode Driver project. Source files, headers, and an INF file will be generated and you should have a working driver that handles a PNP root enumerated device and creates a device interface (look at the source file named Device.c).
At this point you should only be able to open the device. To send read, write or IOCTL requests, you have to setup EvtIoRead, EvtIoWrite or EvtIoDeviceControl callbacks just before the device queue is created (take a look at Queue.c).
To have an example of a user mode application opening a device using a device interface, once again use Visual Studio and create a new WinUsb application project. One of the generated source files contains a function whose name is OpenDevice or something similar.
To use a device interface for user-mode and kernel-mode interaction, all you need to share is a GUID.
On 02-Nov-2014 16:09, xxxxx@osr.com wrote:
hFile = CreateFile(“\.\MyDevice”,…);
Again, note that you’ll need to escape those backslashes in the string… and YES, you DO REQUIRE the "\." before your device name (this tells Windows the device you’re opening is on the current system).
Were there plans ever to support opening devices across network?
– pa
No, \.\ is the namespace escape, just happens to share the same smb syntax
d
Bent from my phone
From: Pavel A.mailto:xxxxx
Sent: ?11/?2/?2014 9:40 AM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: Re:[ntdev] How to provide interface for user apps?
On 02-Nov-2014 16:09, xxxxx@osr.com wrote:
> hFile = CreateFile(“\.\MyDevice”,…);
>
> Again, note that you’ll need to escape those backslashes in the string… and YES, you DO REQUIRE the "\." before your device name (this tells Windows the device you’re opening is on the current system).
Were there plans ever to support opening devices across network?
– pa
—
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 am used to UNIX model - driver (module) registers a filename in system
Very similar to Windows.
In Windows, you need to register PnP devinterface in system.
and passes set of callback funtions (for reading and writing to the virtual file).
Exactly same as in Windows.
But note that Windows uses async/overlapped IO, so each IO operation for your driver is converted to the structure called “IRP”, which is the “possible (and not necessary) async IO operation in progress”.
If you want extremely high perfomance, and your IO pattern is mainly sync, then you can also provide FastIo functions to your driver. These functions allow to do the IO (ONLY sync IO) without using the IRP.
providing interface to user space on level I can understand. What articles should I read?
IoRegisterDeviceInterface
IoSetDeviceInterfaceState
–
Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com
>enumerate currently existing devices with these names. GUID-based interfaces are persistently
bound to the device instances. They don’t change across reboots.
Yes.
Also they get rid of the issue with non-contiguous device numbers which arises in the classic Device%d naming scheme.
–
Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com
> It’s worth mentioning here that Windows strongly prefers ioctls for
device interfaces over reads & writes - unlike the Other OS that
discourages ioctls.
I think IOCTLs are great for any OS, am I wrong?
And, if you have the natural read/write
–
Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com
On Nov 4, 2014, at 5:45 PM, Maxim S. Shatskih wrote:
>> It’s worth mentioning here that Windows strongly prefers ioctls for
>> device interfaces over reads & writes - unlike the Other OS that
>> discourages ioctls.
>
> I think IOCTLs are great for any OS, am I wrong?
No, you?re right and he?s wrong. The paradigms are exactly the same. You use read and write where the model allows that to make sense, and you use ioctls where read and write don?t work. Linux also has mmap as a fundamental operation, which is a handy option that Windows lacks.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
On 05-Nov-2014 03:45, Maxim S. Shatskih wrote:
I think IOCTLs are great for any OS, am I wrong?
I’ll quote from the LDD book (yes, it is quite old…) :
http://www.makelinux.net/ldd3/chp-6-sect-1
“The unstructured nature of the ioctl call has caused it to fall out of
favor among kernel developers. … As a result, there is strong
pressure to implement miscellaneous control operations by just about any
other means.”
Basically, arguments against ioctls in *nix are similar to the “neither”
method in Windows: needs accurate validation on the driver side.
IIRC there were also some technical issues with ioctl implementation
about 5 years ago (2.6.something). It might be have fixed since then,
but all those fs-like interfaces (sysfs, modfs, debugfs…) proved
convenient and won’t go away.
And, if you have the natural read/write
The Other OS has also pread/pwrite which passes input parameter to
read/write atomically (yes, usually the offset, but can be anything). In
Windows this requires the overlapped stuff. Or, DeviceIoControl with two
buffers 
So… all this looks nice on the paper, but - devil is in detals.
Regards,
– pa
And I forgot something else:
In Windows, ioctl can pass two buffers of maximum allowed size.
In posix ioctl, the buffer size is encoded in few bits of the 2nd arg
(command) when the 3rd arg is a pointer.
The type of this arg is int. So the buffer size that can be passed via
ioctl is ~ 64K on systems where int is 32 bits. Or you have to resort to
“neither” trickery.
– pa
On 05-Nov-2014 10:15, Pavel A. wrote:
On 05-Nov-2014 03:45, Maxim S. Shatskih wrote:
…
On 05-Nov-2014 10:15, Pavel A. wrote:
IIRC there were also some technical issues with ioctl implementation
about 5 years ago (2.6.something).
Here is the “executive summary” - http://lwn.net/Articles/119652/
(It was almost 10 years ago! How fast Linux years fly …)
– pa