📄 alertdrv.c
字号:
/*
* QueueUserAPCEx: Extending APCs on Windows Operating System (version 2.0)
* Copyright(C) 2004 Panagiotis E. Hadjidoukas
*
* Contact Email: peh@hpclab.ceid.upatras.gr, xdoukas@ceid.upatras.gr
*
* QueueUserAPCEx is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* QueueUserAPCEx is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with QueueUserAPCEx in the file COPYING.LIB;
* if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include "ntddk.h"
#define FILE_DEVICE_ALERTDRV 0x00008005
#define IOCTL_ALERTDRV_SET_ALERTABLE2 CTL_CODE(FILE_DEVICE_ALERTDRV, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define ALERTDRV_DEVICE_NAME_U L"\\Device\\Alertdrv"
#define ALERTDRV_DOS_DEVICE_NAME_U L"\\DosDevices\\ALERTDRV"
/* Debugging macros */
#ifdef DBG
#define AlertDrvKdPrint(_x_) \
DbgPrint("AlertDrv.sys: ");\
DbgPrint _x_;
#else
#define AlertDrvKdPrint(_x_)
#endif
/* Function prototypes for APCs */
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
);
void
KernelApcCallBack(PKAPC Apc, PKNORMAL_ROUTINE NormalRoutine, PVOID NormalContext, PVOID SystemArgument1, PVOID SystemArgument2)
{
KEVENT event;
LARGE_INTEGER Timeout;
AlertDrvKdPrint(("Freeing APC Object\n"));
ExFreePool(Apc); /* free the kernel memory */
Timeout.QuadPart = 0;
KeDelayExecutionThread(UserMode, TRUE, &Timeout);
/*
* Another way for a thread to set itself in alertable state
* (MSJ, Nerditorium, July 99):
*
* KeInitializeEvent(&event, SynchronizationEvent, FALSE);
* KeWaitForSingleObject(&event, Executive, UserMode, TRUE, &Timeout);
*/
return;
}
void
UserApcCallBack(PVOID arg1, PVOID arg2, PVOID arg3)
{
return;
}
/* Function prototypes */
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING registryPath);
NTSTATUS AlertDrvDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
VOID AlertDrvUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS AlertDrvSendTheSignal(PETHREAD Thread);
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT deviceObject = NULL;
NTSTATUS status;
WCHAR deviceNameBuffer[] = ALERTDRV_DEVICE_NAME_U;
UNICODE_STRING deviceNameUnicodeString;
WCHAR deviceLinkBuffer[] = ALERTDRV_DOS_DEVICE_NAME_U;
UNICODE_STRING deviceLinkUnicodeString;
AlertDrvKdPrint (("DriverEntry\n"));
RtlInitUnicodeString (&deviceNameUnicodeString, deviceNameBuffer);
status = IoCreateDevice (DriverObject,0,&deviceNameUnicodeString,
FILE_DEVICE_ALERTDRV, 0,TRUE,&deviceObject);
if (!NT_SUCCESS(status))
{
AlertDrvKdPrint (("IoCreateDevice failed:%x\n", status));
return status;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AlertDrvDispatch;
DriverObject->DriverUnload = AlertDrvUnload;
RtlInitUnicodeString(&deviceLinkUnicodeString,deviceLinkBuffer);
status = IoCreateSymbolicLink (&deviceLinkUnicodeString, &deviceNameUnicodeString);
if (!NT_SUCCESS(status))
{
AlertDrvKdPrint (("IoCreateSymbolicLink failed\n"));
IoDeleteDevice (deviceObject);
}
return status;
}
NTSTATUS AlertDrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
NTSTATUS ntStatus;
PHANDLE ph = NULL;
PETHREAD uThread = NULL;
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:
AlertDrvKdPrint (("IRP_MJ_CREATE\n"));
break;
case IRP_MJ_CLOSE:
AlertDrvKdPrint (("IRP_MJ_CLOSE\n"));
break;
case IRP_MJ_DEVICE_CONTROL:
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
case IOCTL_ALERTDRV_SET_ALERTABLE2:
if (inputBufferLength >= sizeof(PVOID))
{
ph = (PHANDLE) ioBuffer;
Irp->IoStatus.Status = ObReferenceObjectByHandle(*((PHANDLE)ph),THREAD_ALL_ACCESS,NULL,UserMode,&uThread,NULL);
if (NT_ERROR(Irp->IoStatus.Status))
{
AlertDrvKdPrint (("ObReferenceObjectByHandle Failed (%ld)\n", Irp->IoStatus.Status));
}
else
{
AlertDrvKdPrint (("uThread = 0x%lx\n", uThread));
Irp->IoStatus.Status = AlertDrvSendTheSignal(uThread);
ObDereferenceObject((PVOID) uThread);
}
}
else
{
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
AlertDrvKdPrint (("Invalid parameter passed!\n"));
}
break;
default:
AlertDrvKdPrint (("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
AlertDrvUnload(IN PDRIVER_OBJECT DriverObject)
{
WCHAR deviceLinkBuffer[] = ALERTDRV_DOS_DEVICE_NAME_U;
UNICODE_STRING deviceLinkUnicodeString;
RtlInitUnicodeString (&deviceLinkUnicodeString, deviceLinkBuffer);
IoDeleteSymbolicLink (&deviceLinkUnicodeString);
IoDeleteDevice (DriverObject->DeviceObject);
AlertDrvKdPrint (("Driver has been unloaded\n"));
return;
}
NTSTATUS
AlertDrvSendTheSignal(PETHREAD uThread)
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PKAPC kApc;
/* Allocate an KAPC structure from NonPagedPool */
kApc = ExAllocatePool(NonPagedPool, sizeof(KAPC));
if (kApc == NULL)
{
AlertDrvKdPrint (("ExAllocatePool returned NULL\n"));
return !ntStatus;
}
KeInitializeApc(kApc,
(PKTHREAD) uThread,
0,
(PKKERNEL_ROUTINE) &KernelApcCallBack,
0,
(PKNORMAL_ROUTINE) &UserApcCallBack,
KernelMode,
NULL);
KeInsertQueueApc (kApc, NULL, NULL, 0);
return ntStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -