FREE Subscription to Dr. Dobb’s Digest: Same Great Content, New Digital Edition
Site Archive (Complete)
Dobbs M-Dev
Email
Print
Reprint

add to:
Del.icio.us
Digg
Google
Furl
Slashdot
Y! MyWeb
Blink
August 01, 2001

A Device Driver for W2K Signals

(Page 5 of 5)
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 */
Previous Page | 1 | 2 | 3 | 4 | 5
TOP 5 ARTICLES
No Top Articles.



MICROSITES
FEATURED TOPIC

ADDITIONAL TOPICS

INFO-LINK