How to develop a basic Hello World Device Driver and call its functions from a basic C#.NET wind

Rate this article
5.00 out of 5
Developing a device driver is one of the toughest task in the programming career of any developer. This is especially the case if he is a beginner in the programming filed and have very little knowledge about device driver and C/C++ programing language.

Over a few years I myself felt the need of a video tutorial about device driver development so as to assist the developers in my company KTS InfoTech. This article and its accompanying video tutorial is the outcome of this thinking.
In this tutorial, I will show you how to develop a basic Hello World Device Driver and call its functions from a basic C#.NET windows Application.

Watch the YouTube Video Tutorial From the Link below



Main Portion of the Code Snippets

MyDriver.c Source

//This program demonstrates a basic Hello world Device Driver component that can be invoked and called form
//a User mode application 4th march 2013
//Author Tom Thomas , KTS InfoTech PVT LTD
//

#include <ntddk.h>

#define BUFFERSIZE 100

PVOID    gpEventObject = NULL;

typedef struct _REGISTER_EVENT
{
    HANDLE  hEvent;
    char EventParameter[BUFFERSIZE];

} REGISTER_EVENT , *PREGISTER_EVENT ;

REGISTER_EVENT* driverExtension=0;

#define SIZEOF_REGISTER_EVENT  sizeof(REGISTER_EVENT )

//Function pointer forward declaration
NTSTATUS DriverEntry  (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
NTSTATUS DispatchCreate (IN PDEVICE_OBJECT    pDevObj,IN PIRP pIrp);
NTSTATUS DispatchClose (IN PDEVICE_OBJECT    pDevObj, IN PIRP pIrp);
NTSTATUS DispatchRead (IN PDEVICE_OBJECT    pDevObj,IN PIRP pIrp);
NTSTATUS DispatchWrite (IN PDEVICE_OBJECT    pDevObj, IN PIRP pIrp);
NTSTATUS DeviceIoEvent (IN PDEVICE_OBJECT    pDevObj,IN PIRP pIrp);
NTSTATUS Example_UnSupportedFunction(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);

DRIVER_INITIALIZE DriverEntry;
NTSTATUS
DriverEntry(
   IN  PDRIVER_OBJECT  driverObject,
   IN  PUNICODE_STRING registryPath
   );

DRIVER_UNLOAD DriverUnload;
VOID
DriverUnload(
   IN  PDRIVER_OBJECT driverObject
   );


#ifdef ALLOC_PRAGMA //This Macro make every call associated with PAGE resident and locked in memory
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, DispatchCreate)
#pragma alloc_text(PAGE, DispatchClose)
#pragma alloc_text(PAGE, DispatchRead)
#pragma alloc_text(PAGE, DispatchWrite)
#pragma alloc_text(PAGE, DeviceIoEvent)
#pragma alloc_text(PAGE, DriverUnload)

#endif


//Driver entry point
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{

    NTSTATUS status;
    UNICODE_STRING deviceName;
    UNICODE_STRING bufferDeviceName;
    UNICODE_STRING symLinkName;

    PDEVICE_OBJECT deviceObject;

    RtlInitUnicodeString(&deviceName, L"DeviceMyHwDriver");
    RtlInitUnicodeString(&symLinkName, L"DosDevicesMyHwDriver");

    //Create the IO devce
    status = IoCreateDevice(
    DriverObject,
    sizeof(REGISTER_EVENT),
    &deviceName,
    0, //FILE_DEVICE_UNKNOWN,
    0,
    FALSE,
    &deviceObject);

    if (!NT_SUCCESS(status))
    return status;


    deviceObject->Flags |= DO_BUFFERED_IO;
    deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    status = IoCreateSymbolicLink (&symLinkName, &deviceName);

    if (!NT_SUCCESS(status))
    {
        // if it fails now, must delete Device object
        IoDeleteDevice( DriverObject->DeviceObject );
        return status;
    }

    //Implement basic Driver function pointers
    // This includes Dispatch routines for Create,Close , Read, Write and IO control
    DriverObject->MajorFunction[IRP_MJ_CREATE]                = DispatchCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]                = DispatchClose;
    DriverObject->MajorFunction[IRP_MJ_READ]                = DispatchRead;
    DriverObject->MajorFunction[IRP_MJ_WRITE]                = DispatchWrite;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]        = DeviceIoEvent;

    DriverObject->DriverUnload = DriverUnload;
    DbgPrint("Hello, World from MyHwDriver DriverEntry code ");

    driverExtension = ExAllocatePool(NonPagedPool, sizeof (REGISTER_EVENT));

    if(!driverExtension)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }


    RtlZeroMemory(driverExtension->EventParameter, BUFFERSIZE);
    RtlCopyBytes (driverExtension->EventParameter, "Hai from driver", 16);
    return STATUS_SUCCESS;
}
//Called when the application unloads the driver
VOID DriverUnload(IN  PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING linkString;
    DbgPrint("DriverUnload called");
    ExFreePool(driverExtension);
    RtlInitUnicodeString (&linkString, L"DosDevicesMyHwDriver");
    IoDeleteSymbolicLink (&linkString);
    IoDeleteDevice(DriverObject->DeviceObject);
   
}
//Called when the application creates this device
NTSTATUS DispatchCreate (PDEVICE_OBJECT    pDevObj, PIRP pIrp)
{
    DbgPrint("Inside Dispatch Create Routine");
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
   
}
//Called when the application reads data from this device
NTSTATUS DispatchRead (PDEVICE_OBJECT    pDevObj,PIRP pIrp)
{   
    DbgPrint("Inside Dispatch Read Routine");
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}
//Called when the application writes data to this device
NTSTATUS DispatchWrite (PDEVICE_OBJECT    pDevObj,PIRP pIrp)
{
    DbgPrint("Inside Dispatch Write Routine");
    //Read the data form the User Mode Application..
    if(pIrp->AssociatedIrp.SystemBuffer!=NULL)
    {
        DbgPrint(pIrp->AssociatedIrp.SystemBuffer);
    }
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}
//Called when the application closes the device Handle
NTSTATUS DispatchClose (IN PDEVICE_OBJECT    pDevObj,IN PIRP pIrp)
{
    DbgPrint("Inside Create Dispatch Close Routine");

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}
//Called when the application the application invokes IO control Events
NTSTATUS DeviceIoEvent (IN PDEVICE_OBJECT    DeviceObject,IN PIRP pIrp)
{
    DbgPrint("Inside DeviceIoEvent Routine");
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;

}



// MyDriverTestConsoleApp.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#include <windows.h>

int _tmain(int argc, _TCHAR* argv[])
{
    long ulReturnedLength=0;
    HANDLE hDevice = CreateFile(L".MyHwDriver",
            GENERIC_READ | GENERIC_WRITE,
            0,        // share mode none
            NULL,    // no security
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            NULL );        // no template

        if (hDevice == INVALID_HANDLE_VALUE)
        {
            printf("Failed to create MyHwDriver File ");
            return 1;
        }
        else
        {
            //Now Write and Read something
            printf("MyHwDriver Device Opened ");
            DWORD NoOfWordsWritten=0;
            char InputOutputString[100]="Hell World From User Mode Test App";
            WriteFile(hDevice,InputOutputString,strlen(InputOutputString),&NoOfWordsWritten,NULL);
            printf("Send Message To The Device ");
            ReadFile(hDevice,InputOutputString,20,&NoOfWordsWritten,NULL);
           

        }
        CloseHandle(hDevice);
        printf("Press any Character To Continue ");

        getch();
    return 1;
}



// MyUserModeComponent.h

#pragma once

#include <windows.h>

using namespace System;

namespace MyUserModeComponent {

    public ref class MyComponent
    {
        // TODO: Add your methods for this class here.
        HANDLE hDevice;
    public:

        bool OpenAndSendCommandToDriver(void)
        {
            long ulReturnedLength=0;
            hDevice = CreateFile(L".MyHwDriver",
            GENERIC_READ | GENERIC_WRITE,
            0,        // share mode none
            NULL,    // no security
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL,
            NULL );        // no template

            if (hDevice == INVALID_HANDLE_VALUE)
            {
               
                return false;
            }
            else
            {
                //Now Write and Read something
           
                DWORD NoOfWordsWritten=0;
                char InputOutputString[100]="Hell World From User Mode Test App";
                WriteFile(hDevice,InputOutputString,strlen(InputOutputString),&NoOfWordsWritten,NULL);
           
                ReadFile(hDevice,InputOutputString,20,&NoOfWordsWritten,NULL);
               

            }
            CloseHandle(hDevice);
            return true;
       
        }
    };
}



MyApplication Main C# Project File

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using MyUserModeComponent;

namespace MyApplication
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void buttonOpenAndSend_Click(object sender, EventArgs e)
        {
            MyComponent DeviceObj = new MyComponent();
            DeviceObj.OpenAndSendCommandToDriver();
            MessageBox.Show("Command Send Successfully");
        }
    }
}



Download Source Code

Author :
Tom Thomas
Joined Date :12-Aug-2011
Articles
Posted
9
Messages
Posted
207
Mr. Tom is the Co-Founder and CTO of  KTS InfoTech.  He started his career as a C/C++ programmer in the late 90's and has been very active and passionate in programming since then. He had worked both in start-ups ( Infortech software Pvt Ltd) as well as in CMM Level 5 companies (NeST and Wipro Technologies) for clients like General Electric, Agilent, Hitachi, Toshiba, Fujitsu, Alcatel, Insurance Service Corporation etc. His experience as an Engineer, Architect, Project Manager, Chief Technical Officer and as a Teacher makes him ideal for any type of jobs related to Information Technology.

His role with his present employer includes exploring new business opportunities and partnerships, Developing software product frameworks, developing and executing marketing strategies for company products etc.  

He holds Masters degree in Physics and Computer Science form CUSAT , one of the premier Science and Technology Institutions in India .

His major interests are in Optical Networking, Robotics, Device drivers, Database, Graphics, web applications, Software product Engineering, Open source Technologies and Sports physics.

He resides in Kerala ,India, with his mother, wife and his little angel.

He can be reached on Skype at this ID thomas_tom99 or at his E Mail address tom.thomas (at)ktsinfotech.com

         

   
Messages
NemesiisV
Posted: 08/09/2016
I have a error when I run the program with OSRLOADER and "start service" it say " This driver has been blocked from loading" can you help me please.
thomas_tom99
Posted: 08/09/2016
Hello,

You might have tried out in 64 bit version of Windows. Please try out in 32 bit version of windows. By default 64 bit version of windows will not allow you to load drivers that are not signed.

Also the driver which I developed in the tutorial is compatible only for 32 bit.

Tom

thomas_tom99
Posted: 08/09/2016

Here is One question form a User

I saw your education and training Thank you for this http://tektips.in/how-to-develop-a-hello-world-device-driver.aspx

 

     But I have a question

How can I create a virtual Usb HID device using WDK on WIN7 32 bit?(add to device manger)

             And then I send and receive data?(application test)

              Please help me. Resources the Internet has misled me.

              please tell me a simple example

    I am impatiently waiting for your response

   Thank you very much


Answer

You Need to change the CreateIODevice routine in DriverEntry especially FILE_DEVICE_UNKNOWN part to USB_DEVICE Types and associated changes. Check DDK/WDK Sample and see the link below..

http://msdn.microsoft.com/en-us/library/windows/hardware/ff563821%28v=vs.85%29.aspx

Tom



Tom



mostafasoli93
Posted: 08/09/2016
Wow, how much did you give a quick answer
Thank you
How can I do with "VID/PID" make owen sample virual device
If possible take a simple example
Thank you
desai.laukik999
Posted: 08/09/2016
Hello Sir,

Could you please create the KMDF driver Demo tutorial on the similar basis.I need to know how access device_context(device_extension in WDM analogy) inside the event callbacks of KMDF driver.

(My ultimate purpose is to create the small kmdf driver which can store the data sent by USER mode app and can also send it back to Usermode whenever asked. [For maintaining the buffer/userdata in kernal mode inside Device i have created the Device_Context object inside the evDriverDeviceAdd routine But I am not sure how to access it in the event callabacks.(like evIoRead,evIoWrite..)]
Or could you please suggest alternate way to do it effectively.
Please Login to Post Your Comments
Name (Max 50 Chars)
Comments

TekTipsDownload
GateExam
Academic Projects
TekTipsExperts



 
Site optimized for IE7, 1280 X 768 and above. Copyright © 2010 - 2018 KTS InfoTech
Site Developed Using KTS WebCloud