August 01, 2001
A Device Driver for W2K Signals
August 2001/A Device Driver for W2K Signals/Listing 4
#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