Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results
The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.
Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/
I'm trying to write to a serial port from a KMDF driver as a logging mechanism. I'm using the WdfIoxxx APIs as I'm planning to use this same functionality in a minifilter later. My problem is that WdfIoTargetOpen is failing with STATUS_OBJECT_NAME_NOT_FOUND status. I tried all kinds of symbolic links and object names to reference the COM port but the result is the same. Here's a snippet of how I'm trying to open the port :
DECLARE_CONST_UNICODE_STRING(portName, L"\\Device\\COM4"); WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME( ¶ms, &portName, MAXIMUM_ALLOWED); status = WdfIoTargetOpen(m_ioTarget, ¶ms);
PS: To conform to the rules, I'm a student and this is for an academic project.
Upcoming OSR Seminars | ||
---|---|---|
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead! | ||
Kernel Debugging | 13-17 May 2024 | Live, Online |
Developing Minifilters | 1-5 Apr 2024 | Live, Online |
Internals & Software Drivers | 11-15 Mar 2024 | Live, Online |
Writing WDF Drivers | 26 Feb - 1 Mar 2024 | Live, Online |
Comments
Specifically for serial ports, the convention is that the symbolic link name is COMX and it points to \Device\SerialX or something similar. So you would need to open L"\\??\\COM4" to open via the symbolic link name.
Yeah I also tried that and it failed. Enumerating \Device objects in windbg shows Serial0 and using winobj I could find \Global??\COM4 which is a symlink to \Device\Serial0.
Theoretically, L"\\DosDevices\\COM4" should also work. Any special name that works at a command prompt should be available in \DosDevices.
https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/introduction-to-ms-dos-device-names
Tim Roberts, [email protected]
Providenza & Boekelheide, Inc.
This finally worked. I'm not sure what I was doing wrong but I turned back to using ZwCreateFile, had some errors with it, debugged it, figured out my driver is being loaded before serial.sys so that's a problem set aside. Some more tweaks later ZwCreateFile worked and I decided to go back to WdfIoTargetOpen and it miraculously worked. I'm sorry if I can't say for sure what the problem was besides my driver being loaded before serial.sys. For reference, I ended up using
L"\\device\\Serial0"
For a production quality driver, \Device\Serial0 is a pretty fragile name. For a student experiment, it is OK (but not great).
For the load order issue where you are loading before the serial driver, you can register for device interface arrival notifications with IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, &GUID_DEVINTERFACE_COMPORT, ...). You can then use the provided symbolic link name(s) (they look like gibberish) to open the com port.
Okay great, since I've successfully written to the serial port I'll try your method to solve the load order issue. One other thing, I read somewhere that a serial port could not be concurrently open, is that true ? If so, that would be a problem for me because various drivers would be logging to it at the same time.
Yeah that's what I decided to do. I found a close enough open-source driver project that I'm going to port for my needs. It has buffering capabilities and flushes data to the COM port with spinlock synchronisation. But I'm still not sure If building it as an export driver and export a logging function or as a device driver and send manually built IRPs ?
if it matters, you can't implement an export driver with KMDF. since this is a time bound project, go with the simplest path forward that makes it work. that is probably an export driver with a bunch of global state (since it can't have a device object of its own), but it is your judgement call at the end of the day
Okay then, I'll find out what works well for me and report it back here for future reference. Thank you for all the help !
But wait, if a KMDF driver can't be an export driver, that means I can't use the WdfIoXXX functions to write to the COM port. What should I do then ? the ZwXXX functions have an IRQL constraint and you advice people not to use the WDM in your faq ?
As a wise man once wrote: "it is your judgement call at the end of the day" -- If you prefer to do this in WDF, then write a WDF driver that implements the functionality you want. You can communicate to that WDF driver any way you want: Irps, Bus Interface, whatever...
Peter
Peter Viscarola
OSR
@OSRDrivers
You do what you have to do. KMDF is a HUGE leap forward if you're doing dispatching, PnP, and power management, and it's foolish to attempt a full driver without it. However, an export driver doesn't do ANY of those things. It's just a repository of code snippets. Most of the WdfIoXxx functions are rather thin wrappers around their WDM analogs.
Tim Roberts, [email protected]
Providenza & Boekelheide, Inc.