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