Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

A Device Driver for W2K Signals


August 2001/A Device Driver for W2K Signals/Listing 4

Listing 4: sigdrv.c — Kernel-mode driver for signal library

#define STRICT 1
#include "ntddk.h"
#include "string.h"
#include "sigdrv.h"

#define SIGDRV_DEVICE_NAME_U     L"\\Device\\Sigdrv"
#define SIGDRV_DOS_DEVICE_NAME_U L"\\DosDevices\\SIGDRV"

//  Debugging macros
#ifdef DBG
#define SigDrvKdPrint(_x_) \
                DbgPrint("SigDrv.sys: ");\
                DbgPrint _x_;
#else
#define SigDrvKdPrint(_x_)
#endif

NTSTATUS DriverEntry(
   IN PDRIVER_OBJECT  DriverObject,
   IN PUNICODE_STRING registryPath);

VOID SigDrvUnload(
   IN PDRIVER_OBJECT DriverObject);

NTSTATUS SigDrvDispatch(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp);

NTSTATUS SigDrvSendTheSignal(
   IN PDEVICE_OBJECT DeviceObject,
   IN OUT PVOID ioBuffer,
   IN ULONG inputBufferLength,
   IN ULONG outputBufferLength);

void KeInitializeApc(
   PKAPC Apc,
   PKTHREAD Thread,

   CCHAR ApcStateIndex,
   PKKERNEL_ROUTINE KernelRoutine,
   PKRUNDOWN_ROUTINE RundownRoutine,
   PKNORMAL_ROUTINE NormalRoutine,
   KPROCESSOR_MODE ApcMode,
   PVOID NormalContext);


void KeInsertQueueApc(
   PKAPC Apc,
   PVOID SystemArgument1,
   PVOID SystemArgument2,
   UCHAR unknown);

// Information the driver receives from user mode
typedef struct _SIGINFO
{
   HANDLE   hThread;   // handle of targer thread
   ULONG    SigNo;     // which signal
   ULONG    SigFunc;   // signals' driver-routine of the dll
} SIGINFO, *PSIGINFO;

void KernelApcCallBack(
   PKAPC Apc,
   PKNORMAL_ROUTINE NormalRoutine,
   PVOID NormalContext,
   PVOID SystemArgument1,
   PVOID SystemArgument2)
{
   ExFreePool(Apc);    // just free the kernel memory
   return;
}

void UserApcCallBack(PVOID arg1, PVOID arg2, PVOID arg3)
{
   PSIGINFO psiginfo = (PSIGINFO) arg3;
   ULONG (*SignalDriverRoutine)(ULONG);

   // take the user mode address of the function
   SignalDriverRoutine = (unsigned long (__stdcall *)
        (unsigned long)) psiginfo->SigFunc;

   // call the driver-routine
   SignalDriverRoutine(psiginfo->SigNo);

   return;
}

NTSTATUS DriverEntry(
   IN PDRIVER_OBJECT DriverObject,
   IN PUNICODE_STRING RegistryPath)
{
   PDEVICE_OBJECT deviceObject=NULL;
   NTSTATUS       ntStatus;
   WCHAR          deviceNameBuffer[]=SIGDRV_DEVICE_NAME_U;
   UNICODE_STRING deviceNameUnicodeString;
   WCHAR          deviceLinkBuffer[]=SIGDRV_DOS_DEVICE_NAME_U;
   UNICODE_STRING deviceLinkUnicodeString;

   RtlInitUnicodeString (&deviceNameUnicodeString,
                         deviceNameBuffer);
   ntStatus = IoCreateDevice (
                      DriverObject,0,&deviceNameUnicodeString,
                      FILE_DEVICE_SIGDRV,0,FALSE,&deviceObject);
   if (!NT_SUCCESS(ntStatus))
   {
       SigDrvKdPrint(("IoCreateDevice failed:%x\n", ntStatus));
       return ntStatus;
   }

   DriverObject->MajorFunction[IRP_MJ_CREATE] =
   DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =
   DriverObject->MajorFunction[IRP_MJ_CLOSE]  = SigDrvDispatch;

   DriverObject->DriverUnload = SigDrvUnload;

   RtlInitUnicodeString (&deviceLinkUnicodeString,
                         deviceLinkBuffer);

   ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,
                                    &deviceNameUnicodeString);
   if (!NT_SUCCESS(ntStatus))
   {
      SigDrvKdPrint (("IoCreateSymbolicLink failed\n"));
      IoDeleteDevice (deviceObject);
   }

   return ntStatus;
}

NTSTATUS SigDrvDispatch(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp)
{
   PIO_STACK_LOCATION irpStack;
   PVOID              ioBuffer;
   ULONG              inputBufferLength;
   ULONG              outputBufferLength;
   ULONG              ioControlCode;
   NTSTATUS           ntStatus;

   Irp->IoStatus.Status      = STATUS_SUCCESS;
   Irp->IoStatus.Information = 0;

   irpStack = IoGetCurrentIrpStackLocation(Irp);

   ioBuffer           = Irp->AssociatedIrp.SystemBuffer;
   inputBufferLength  =
      irpStack->Parameters.DeviceIoControl.InputBufferLength;
   outputBufferLength =
      irpStack->Parameters.DeviceIoControl.OutputBufferLength;

   switch (irpStack->MajorFunction)
   {
      case IRP_MJ_CREATE:
         SigDrvKdPrint (("IRP_MJ_CREATE\n"));
         break;

      case IRP_MJ_CLOSE:
         SigDrvKdPrint (("IRP_MJ_CLOSE\n"));
         break;

      case IRP_MJ_DEVICE_CONTROL:
         ioControlCode =
           irpStack->Parameters.DeviceIoControl.IoControlCode;

         switch (ioControlCode)
         {
            case IOCTL_SIGDRV_SEND_SIGNAL:
               Irp->IoStatus.Status = SigDrvSendTheSignal(
                                          DeviceObject,
                                          ioBuffer,
                                          inputBufferLength,
                                          outputBufferLength);

               if (NT_SUCCESS(Irp->IoStatus.Status))
               {
                  Irp->IoStatus.Information = sizeof(PVOID);
                  SigDrvKdPrint(("Signal was sent\n"));
               }
               else
               {
                  Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
                  SigDrvKdPrint(("Signal failed to be sent\n"));
               }
               break;
            default:
               SigDrvKdPrint (("unknown IRP_MJ_DEVICE_CONTROL\n"));
               Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
               break;
         }
         break;
   }

   ntStatus = Irp->IoStatus.Status;
   IoCompleteRequest(Irp, IO_NO_INCREMENT);
   return ntStatus;
}

VOID SigDrvUnload(IN PDRIVER_OBJECT DriverObject)
{
   WCHAR deviceLinkBuffer[]  = SIGDRV_DOS_DEVICE_NAME_U;
   UNICODE_STRING deviceLinkUnicodeString;

   RtlInitUnicodeString (&deviceLinkUnicodeString,
                             deviceLinkBuffer);
   IoDeleteSymbolicLink (&deviceLinkUnicodeString);
   IoDeleteDevice (DriverObject->DeviceObject);

   return;
}

NTSTATUS SigDrvSendTheSignal(
  IN PDEVICE_OBJECT DeviceObject,
  IN OUT PVOID      IoBuffer,
  IN ULONG          InputBufferLength,
  IN ULONG          OutputBufferLength)
{
   NTSTATUS   ntStatus = STATUS_SUCCESS;
   PVOID      virtualAddress;
   SIGINFO    *psiginfo = (PSIGINFO) IoBuffer;
   PETHREAD   uThread = NULL;
   PKAPC      kApc;

   // take a pointer to the kernel thread structure
   ntStatus = ObReferenceObjectByHandle(
                psiginfo->hThread, THREAD_ALL_ACCESS,
                NULL, KernelMode, &uThread, NULL);
   if (NT_ERROR(ntStatus)) {
      SigDrvKdPrint (("ObReferenceObjectByHandle Failed\n"));
      return ntStatus;
   }

   // Allocate an KAPC structure from NonPagedPool
   kApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));

   KeInitializeApc(kApc,
                   (PKTHREAD) uThread, 0,
                   (PKKERNEL_ROUTINE) &KernelApcCallBack, 0,
                   (PKNORMAL_ROUTINE) &UserApcCallBack,
                   KernelMode, (PVOID) 0);
   KeInsertQueueApc (kApc, (PVOID) (ULONG) 10, (PVOID) psiginfo, 0);

   ObDereferenceObject((PVOID) uThread);
   return ntStatus;
}
/* End of File */

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.