How to interact w/ driver from .NET?

I understand the intention of the WDK examples are primarily focused on driver fundamentals, but an area that I haven’t (until now) had to approach is how to interface with my drivers from a managed language like C#.

I’ve scoured the whitepapers, and haven’t found any universal way to do it.

What are the preferred methods for creating a good user mode API that can be used by .NET applications?

> -----Original Message-----

From: xxxxx@lists.osr.com [mailto:bounce-313802-
xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Tuesday, February 05, 2008 1:55 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] How to interact w/ driver from .NET?

I understand the intention of the WDK examples are primarily focused on
driver fundamentals, but an area that I haven’t (until now) had to
approach is how to interface with my drivers from a managed language
like C#.

I’ve scoured the whitepapers, and haven’t found any universal way to do
it.

What are the preferred methods for creating a good user mode API that
can be used by .NET applications?

Actually, the same methods are used from a managed C# application as from an unmanaged ‘C’ application.

Use the Win32 CreateFile, DeviceIoControl, ReadFile, Close, etc. APIs.

The only nuisance is that these are unmanaged APIs, so you must use P/Invoke to call them in most cases.

In addition, you will have to do some work to convert ‘C’ struct definitions to forms suitable for use in managed code. Study the StructLayout attribute and friends. This will be tedious at first. You will probably learn that there are ways to define structs that make it easier to adapt them to work with managed code.

In some cases it is simply a LOT easier to create an unmanaged supporting ‘C’ DLL that does work that can probably be accomplished in C#, but requires a lot (read “too much”…) of work. In other words, try to use P/Invoke and C# as much as possible, but do not think that a “pure C#” application is a must.

If you are asking this question, then you have a lot of study and experimentation to do before you will be comfortable with this approach, but it is the way.

The pinvoke.net site is helpful in some cases.

Good luck,

Thomas F. Divine

xxxxx@hotmail.com wrote:

I understand the intention of the WDK examples are primarily focused on driver fundamentals, but an area that I haven’t (until now) had to approach is how to interface with my drivers from a managed language like C#.

I’ve scoured the whitepapers, and haven’t found any universal way to do it.

What are the preferred methods for creating a good user mode API that can be used by .NET applications?

This depends entirely on the type of driver. At the lowest level, the
driver interface is just ReadFile, WriteFile, and DeviceIoControl, and
all of those can be called through P/Invoke.

Once you get on top of that, you can expose whatever kind of interface
class makes sense for your device. There is no “universal” way, any
more than there is a universal way to access them from C++.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Async io and OVERLAPPED is going to be a pain point as well. Remember that structs are value types which means you cannot use them for async io if they are stack based. If they are embedded in a reference type, you are going to need to pin the object for the duration of the async call and free it when it has completed (remember that the actual pointer value of the overlapped struct must remain the same and cannot be relocated by the GC)

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Thomas F. Divine
Sent: Tuesday, February 05, 2008 11:21 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] How to interact w/ driver from .NET?

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:bounce-313802-
xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Tuesday, February 05, 2008 1:55 PM
To: Windows System Software Devs Interest List
Subject: [ntdev] How to interact w/ driver from .NET?

I understand the intention of the WDK examples are primarily focused on
driver fundamentals, but an area that I haven’t (until now) had to
approach is how to interface with my drivers from a managed language
like C#.

I’ve scoured the whitepapers, and haven’t found any universal way to do
it.

What are the preferred methods for creating a good user mode API that
can be used by .NET applications?

Actually, the same methods are used from a managed C# application as from an unmanaged ‘C’ application.

Use the Win32 CreateFile, DeviceIoControl, ReadFile, Close, etc. APIs.

The only nuisance is that these are unmanaged APIs, so you must use P/Invoke to call them in most cases.

In addition, you will have to do some work to convert ‘C’ struct definitions to forms suitable for use in managed code. Study the StructLayout attribute and friends. This will be tedious at first. You will probably learn that there are ways to define structs that make it easier to adapt them to work with managed code.

In some cases it is simply a LOT easier to create an unmanaged supporting ‘C’ DLL that does work that can probably be accomplished in C#, but requires a lot (read “too much”…) of work. In other words, try to use P/Invoke and C# as much as possible, but do not think that a “pure C#” application is a must.

If you are asking this question, then you have a lot of study and experimentation to do before you will be comfortable with this approach, but it is the way.

The pinvoke.net site is helpful in some cases.

Good luck,

Thomas F. Divine


NTDEV is sponsored by OSR

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

I guess my question was a little awkward. I’ve thought of two primary ways to create an API for my C# apps.

  1. Create the API in C#, and P/Invoke the CreateFile, ReadFile, WriteFile, DeviceIoControl stuff using ‘equivalent’ data types.

  2. Create an unmanaged C++ library that uses the Win32 calls to CreateFile,…, etc. Wrap this with a managed class library using ‘equivalent’ data types.

Both seemed a little awkward, so I was curious if there was a ‘better’ approach. I come from a linux background so the .NET style of things is still a relatively new to me. Unless something better is suggested, I think I’ll take approach #1

I found a Microsoft TechNet article that demonstrates how to use ReadFile in C# here:
http://technet.microsoft.com/en-us/library/2d9wy99d.aspx

It may help somebody in the future.

As Doron pointed out, object pinning is something to be careful of. The article I linked to above has an example to use declarative pinning in C#.

The only problem I see with creating a C# API in this manner is that your driver IOCTLs cannot be shared via a single header file. So the question becomes, how do you specify an IOCTL when making calls to DeviceIoControl?

In the past, I’ve always found that using a C# app with the driver stuff in
a managed C++ assembly worked best. You get a managed interface plus the
ability to use IJW for CreateFile/DeviceIoControl as needed. The main reason
for this was that for one driver C# definition of a structure was not
possible; I had to write the thing in IL and that meant another assembly
anyway.

It does not radically change your choices, but it did help me in some
situations.

Carl.

wrote in message news:xxxxx@ntdev…
> I guess my question was a little awkward. I’ve thought of two primary
> ways to create an API for my C# apps.
>
> 1) Create the API in C#, and P/Invoke the CreateFile, ReadFile, WriteFile,
> DeviceIoControl stuff using ‘equivalent’ data types.
>
> 2) Create an unmanaged C++ library that uses the Win32 calls to
> CreateFile,…, etc. Wrap this with a managed class library using
> ‘equivalent’ data types.
>
> Both seemed a little awkward, so I was curious if there was a ‘better’
> approach. I come from a linux background so the .NET style of things is
> still a relatively new to me. Unless something better is suggested, I
> think I’ll take approach #1
>

> -----Original Message-----

From: xxxxx@lists.osr.com [mailto:bounce-313816-
xxxxx@lists.osr.com] On Behalf Of xxxxx@hotmail.com
Sent: Tuesday, February 05, 2008 4:35 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] How to interact w/ driver from .NET?

I guess my question was a little awkward. I’ve thought of two primary
ways to create an API for my C# apps.

  1. Create the API in C#, and P/Invoke the CreateFile, ReadFile,
    WriteFile, DeviceIoControl stuff using ‘equivalent’ data types.

  2. Create an unmanaged C++ library that uses the Win32 calls to
    CreateFile,…, etc. Wrap this with a managed class library using
    ‘equivalent’ data types.

Both seemed a little awkward, so I was curious if there was a ‘better’
approach. I come from a linux background so the .NET style of things
is still a relatively new to me. Unless something better is suggested,
I think I’ll take approach #1

What I was trying to say is don’t be a C# “purist”. Use managed code as much as possible, but…

When you encounter a function that seems really tedious and awkward to implement using C#, don’t be afraid to augment your solution by having an unmanaged helper DLL do some dirty work for you.

Judge the overall reliability of the solution on a function-by-function basis. Is the C# implementation likely to be complex and error prone (new code always is) while it is simple in ‘C’? Do it in ‘C’.

Thomas F. Divine

wrote in message news:xxxxx@ntdev…
>I found a Microsoft TechNet article that demonstrates how to use ReadFile in C# here:
> http://technet.microsoft.com/en-us/library/2d9wy99d.aspx
>
> It may help somebody in the future.
>
> As Doron pointed out, object pinning is something to be careful of. The article I linked to above has an example to use
> declarative pinning in C#.
>
> The only problem I see with creating a C# API in this manner is that your driver IOCTLs cannot be shared via a single header
> file. So the question becomes, how do you specify an IOCTL when making calls to DeviceIoControl?
>

Perhaps you mean that macros CTL_CODE etc. defined in winnt.h (or winioctl.h?), are not available in C# ?
Ok, here’s a bit of problem …

–PA

CTL_CODE is not difficult to duplicate -
public const UInt32 IOCTL_MYDEVICE_MYOPERATION = ((FILE_DEVICE_whatever << 16) | (FILE_whatever_ACCESS << 14) | (0x800 << 2) | METHOD_BUFFERED);

I’ve always taken the approach of an unmanaged DLL with C exports in the past. This allows not just .NET, but also any other language to have an easy interface to talk to your driver.

However, a client recently insisted that they needed a pure .NET solution. So I did it. All I can say is, be prepared to become the master of interop…

-Steve

I have’t tried this myself, but I’ll throw it out there as a possibility…

If high performance isn’t a requirement, your driver can expose functionality via WMI. The .NET System.Management namespace has classes to interact with WMI – all the native interop is done by the framework.

–John

wrote in message news:xxxxx@ntdev…
> CTL_CODE is not difficult to duplicate -
> public const UInt32 IOCTL_MYDEVICE_MYOPERATION = ((FILE_DEVICE_whatever << 16) | (FILE_whatever_ACCESS << 14) | (0x800 << 2)
> | METHOD_BUFFERED);
>
> I’ve always taken the approach of an unmanaged DLL with C exports in the past. This allows not just .NET, but also any other
> language to have an easy interface to talk to your driver.
>
> However, a client recently insisted that they needed a pure .NET solution. So I did it. All I can say is, be prepared to
> become the master of interop…
>
> -Steve

Ok just don’t tell this client that using pinvoke makes the program “unsafe”
in the .net sense, so it is effectively no any better than native dlls.
Let 'em stay cool and happy…

–PA