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(#13#10'TimerWorks: Entering ThreadProc'#13#10);
DbgPrint('TimerWorks: IRQL = %d'#13#10, KeGetCurrentIrql);
pkThread := KeGetCurrentThread;
iPriority := KeQueryPriorityThread(pkThread);
DbgPrint('TimerWorks: Thread Priority = %d'#13#10, iPriority);
Inc(iPriority, 2);
KeSetPriorityThread(pkThread, iPriority);
iPriority := KeQueryPriorityThread(pkThread);
DbgPrint('TimerWorks: Thread Priority = %d'#13#10, iPriority);
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...'#13#10);
while dwCounter < 10 do
begin
KeWaitForSingleObject(@_kTimer, Executive, KernelMode,
FALSE, nil);
Inc(dwCounter);
DbgPrint('TimerWorks: Counter = %d'#13#10, dwCounter);
if g_fStop then
begin
DbgPrint('TimerWorks: Stop counting to let the driver to be uloaded'#13#10);
Break;
end;
end;
KeCancelTimer(@_kTimer);
DbgPrint('TimerWorks: Timer is canceled. Leaving ThreadProc'#13#10);
DbgPrint('TimerWorks: Our thread is about to terminate'#13#10);
PsTerminateSystemThread(STATUS_SUCCESS);
Result := STATUS_SUCCESS;
end;
procedure DriverUnload(p_DriverObject:PDRIVER_OBJECT); stdcall;
begin
DbgPrint(#13#10'TimerWorks: Entering DriverUnload'#13#10);
g_fStop := TRUE; {Break the timer loop if it's counting}
DbgPrint('TimerWorks: Wait for thread exits...'#13#10);
KeWaitForSingleObject(@g_pkThread, Executive, KernelMode, FALSE, nil);
ObfDereferenceObject(@g_pkThread);
IoDeleteSymbolicLink(@g_usSymbolicLinkName);
IoDeleteDevice(p_DriverObject^.DeviceObject);
DbgPrint('TimerWorks: Leaving DriverUnload'#13#10);
end;
function StartThread: NTSTATUS;
var
status: NTSTATUS;
hThread: THANDLE;
begin
DbgPrint(#13#10'TimerWorks: Entering StartThread'#13#10);
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'#13#10);
end else
begin
DbgPrint('TimerWorks: Can''t create Thread. Status: %08X'#13#10, status);
end;
DbgPrint('TimerWorks: Leaving StartThread'#13#10);
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.
var
hThread: THANDLE;
……
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'#13#10);
end else
begin
DbgPrint('TimerWorks: Can''t create Thread. Status: %08X'#13#10, status);
end;