unit TimerWorks;
interface
uses
nt_status, ntoskrnl, hal, native, fcall, macros;
function
_DriverEntry(pDriverObject:PDRIVER_OBJECT;
pusRegistryPath:PUNICODE_STRING): NTSTATUS; stdcall;
implementation
var
g_pkThread: PVOID; {PTR KTHREAD}
g_fStop: Boolean;
g_usDeviceName, g_usSymbolicLinkName: UNICODE_STRING;
function
ThreadProc(StartContext: PVOID): NTSTATUS;
var
dwCounter: DWORD;
pkThread: PVOID; {PKTHREAD}
_kTimer: KTIMER;
liDueTime: LARGE_INTEGER;
iPriority: KPRIORITY;
begin
dwCounter := 0;
DbgPrint(
DbgPrint(
'TimerWorks: IRQL = %d'
pkThread := KeGetCurrentThread;
iPriority := KeQueryPriorityThread(pkThread);
DbgPrint(
'TimerWorks: Thread Priority = %d'
Inc(iPriority, 2);
KeSetPriorityThread(pkThread, iPriority);
iPriority := KeQueryPriorityThread(pkThread);
DbgPrint(
'TimerWorks: Thread Priority = %d'
KeInitializeTimerEx(@_kTimer, SynchronizationTimer);
liDueTime.HighPart := liDueTime.HighPart or -1;
liDueTime.LowPart := $FD050F80; {-50000000}
KeSetTimerEx(@_kTimer, liDueTime.LowPart, liDueTime.HighPart, 1000, nil);
DbgPrint(
'TimerWorks: Timer is set. It starts counting in 5 seconds...'
while
dwCounter < 10
do
begin
KeWaitForSingleObject(@_kTimer, Executive, KernelMode,
FALSE, nil);
Inc(dwCounter);
DbgPrint(
'TimerWorks: Counter = %d'
if
g_fStop
then
begin
DbgPrint(
'TimerWorks: Stop counting to let the driver to be uloaded'
Break;
end;
end;
KeCancelTimer(@_kTimer);
DbgPrint(
'TimerWorks: Timer is canceled. Leaving ThreadProc'
DbgPrint(
'TimerWorks: Our thread is about to terminate'
PsTerminateSystemThread(STATUS_SUCCESS);
Result := STATUS_SUCCESS;
end;
procedure DriverUnload(p_DriverObject:PDRIVER_OBJECT); stdcall;
begin
DbgPrint(
g_fStop := TRUE; {Break the timer loop
if
it's counting}
DbgPrint(
'TimerWorks: Wait for thread exits...'
KeWaitForSingleObject(@g_pkThread, Executive, KernelMode, FALSE, nil);
ObfDereferenceObject(@g_pkThread);
IoDeleteSymbolicLink(@g_usSymbolicLinkName);
IoDeleteDevice(p_DriverObject^.DeviceObject);
DbgPrint(
'TimerWorks: Leaving DriverUnload'
end;
function
StartThread: NTSTATUS;
var
status: NTSTATUS;
hThread: THANDLE;
begin
DbgPrint(
status := PsCreateSystemThread(@hThread,
THREAD_ALL_ACCESS, nil, 0,
nil, @ThreadProc, nil);
if
status = STATUS_SUCCESS
then
begin
ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS,
nil, KernelMode, @g_pkThread, nil);
ZwClose(hThread);
DbgPrint(
'TimerWorks: Thread created'
end
else
begin
DbgPrint(
'TimerWorks: Can'
't create Thread. Status: %08X'
end;
DbgPrint(
'TimerWorks: Leaving StartThread'
Result := status;
end;
function
_DriverEntry(pDriverObject:PDRIVER_OBJECT;
pusRegistryPath:PUNICODE_STRING): NTSTATUS; stdcall;
var
status: NTSTATUS;
pDeviceObject: TDeviceObject;
begin
status := STATUS_DEVICE_CONFIGURATION_ERROR;
RtlInitUnicodeString(g_usDeviceName,
'\Device\TimerWorks'
);
RtlInitUnicodeString(g_usSymbolicLinkName,
'\DosDevices\TimerWorks'
);
if
IoCreateDevice(pDriverObject, 0, @g_usDeviceName,
FILE_DEVICE_UNKNOWN, 0, TRUE,
pDeviceObject) = STATUS_SUCCESS
then
begin
if
IoCreateSymbolicLink(@g_usSymbolicLinkName,
@g_usDeviceName) = STATUS_SUCCESS
then
begin
if
StartThread = STATUS_SUCCESS
then
begin
g_fStop :=
false
; {reset global flag}
pDriverObject^.DriverUnload := @DriverUnload;
status := STATUS_SUCCESS;
end
else
begin
IoDeleteSymbolicLink(@g_usSymbolicLinkName);
IoDeleteDevice(@pDeviceObject);
end;
end
else
begin
IoDeleteDevice(@pDeviceObject);
end;
end;
Result := status;
end;
end.