For simple usage of DPC and workitem, dpcworkitem
This essay records my time in about half a month, from idea to information inquiry, and to practical results.
What I want to achieve is to write a file at a specified time. I thought it would be possible to call the written function. The result is various BSOD and IRQL_NOT_LESS_OR_EQUAL. This blue screen prompt is displayed, the result is IRQL of the function. kernel functions all have IRQL. I want to run a low-level PASSIVE_LEVEL in DISPATCH_LEVEL, because the write function runs on PASSIVE_LEVEL. The solution is to use DPC and IoQueueWorkItem. The following code is a simple test of my ideas. It only writes time and simple data structure information to the file. It is only suitable for beginners. All the code is as follows (note the red mark code):
1 # include <stdio. h> 2 # include <stdlib. h> 3 # include "ntddk. h "4 5 # define WRITE_FILE_INTERVAL-10000*1000*10 6 typedef struct my_info {7 int age; 8 int weight; 9 char * name; 10} myInfo, * PmyInfo; 11 VOID ThreadStart (in pvoid StartContext); 12 13 VOID CustomDpc (IN struct _ KDPC * Dpc, 14 in pvoid DeferredContext, 15 in pvoid SystemArgument1, 16 in pvoid SystemArgument2 ); 17 18 VOID SyncTechUnload (IN PDRIVER_OBJECT DriverObject); 19 // VOID workItem (); 20 NTSTATUS GetLocalTime (OUT PTIME_FIELDS timeFields); 21 VOID TestFile (IN PDEVICE_OBJECT DeviceObject, 22 in pvoid Context ); 23 24 KTIMER Timer ;//????????????????? 25 PDEVICE_OBJECT DeviceObject; 26 bytes success; 27 LARGE_INTEGER DueTime; 28 KDPC Dpc; 29 HANDLE hThread; 30 31 NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN bytes RegistryPath) 32 {33 34 bytes ObjectAttributes; 35 CLIENT_ID CID; 36 NTSTATUS status; 37 UNICODE_STRING DeviceName, Win32Device; 38 39 40 KdPrint ("dpc: DriverEntry Cur Process: % s Cur IRQL: % d \ N ", 41 (char *) (ULONG) PsGetCurrentProcess () + 0x174), KeGetCurrentIrql (); 42 43 RtlInitUnicodeString (& DeviceName, L "\ Device \ jay0"); 44 RtlInitUnicodeString (& Win32Device, L "\ DosDevices \ jay0"); 45 status = IoCreateDevice (DriverObject, 46 10, 47 & DeviceName, 48 FILE_DEVICE_UNKNOWN, 49 0, 50 FALSE, 51 & DeviceObject); 52 if (! NT_SUCCESS (status) 53 return status; 54 if (! DeviceObject) 55 {56 KdPrint ("dpc: DeviceObject is failure \ n"); 57 return STATUS_UNEXPECTED_IO_ERROR; 58} 59 // initialize the Timer 60 KeInitializeTimer (& Timer ); 61 DriverObject-> DriverUnload = SyncTechUnload; 62 InitializeObjectAttributes (& ObjectAttributes, NULL, success, NULL, NULL); 63 // create a system thread 64 status = PsCreateSystemThread (65 & hThread, 66 GENERIC_READ | GENERIC_WRITE, 67 & ObjectAttributes, 68 NtCurrentProcess (), 69 & CID, 70(PKSTART_ROUTINE) ThreadStart,71 NULL 72); 73 if (! NT_SUCCESS (status) 74 {75 KdPrint ("dpc: PsCreateSystemThread failure! \ N "); 76 return 0; 77} 78 ZwClose (hThread); 79 KdPrint (" dpc: Exit \ n "); 80 return STATUS_SUCCESS; 81} 82 83 VOID ThreadStart (in pvoid StartContext) 84 {85 86 PmyInfo pmyInfo; 87 KdPrint ("dpc: Cur Process: % s IRQL: % d \ n ", 88 (char *) (ULONG) PsGetCurrentProcess () + 0x174), KeGetCurrentIrql (); 89 pmyInfo = ExAllocatePool (NonPagedPool, sizeof (myInfo )); 90 pmyInfo-> age = 23; 91 pmyInfo-> weight = 60; 9 2 pmyInfo-> name = "zc"; 93 // KdPrint ("dpc: my age is % d, my weight is % d \ n", context-> age, context-> weight); 94 DueTime = RtlConvertLongToLargeInteger (WRITE_FILE_INTERVAL); 95 // initialize a Dpc 96 // This CustomDpc is a custom function and runs on DISPATCH_LEVEL, the following myInfo parameter is the function parameter 97 KeInitializeDpc (& Dpc, (PKDEFERRED_ROUTINE) CustomDpc, pmyInfo); 98 // you can set the DPC Timer 99 KeSetTimer (& Timer, DueTime, & Dpc); 100 // wait for the timer 101 KeWaitForSingle Object (& Timer, Executive, KernelMode, FALSE, NULL); 102 KdPrint ("dpc: ThreadStart time expire"); 103 return; 104} 105 106 // simple output process name and current IRQL. Note that this function runs at the dispatch level 107 108 VOID CustomDpc (IN struct _ KDPC * Dpc, 109 IN PmyInfo pmyInfo, 110 in pvoid SystemArgument1, 111 in pvoid SystemArgument2) 112 {113 114 115 KdPrint ("dpc: CustomDpc Process: % s IRQL: % d \ n", 116 (char *) (ULONG) PsGetCurrentProcess () + 0x174), KeGe TCurrentIrql (); 117 // KdPrint ("dpc: my age is % d, my weight is % d, my name is % s \ n ", 118 // pmyInfo-> age, pmyInfo-> weight, pmyInfo-> name); 119 120 // use IoAllocateWorkItem to allocate an ioworkitem 121 pIoWorkItem = IoAllocateWorkItem (DeviceObject ); 122 // IoInitializeWorkItem (DeviceObject, pIoWorkItem); 123 124 125 if (pIoWorkItem) 126 {127 // insert a workitem. TestFile is the function for writing files, the fourth parameter is also the function parameter 128 IoQueueWorkItem (p IoWorkItem, (PIO_WORKITEM_ROUTINE) TestFile, DelayedWorkQueue, pmyInfo); 129} 130 // due to timed write, set the Timer again. If you do not set it to write only 131 KeSetTimer (& Timer, dueTime, Dpc); 132} 133 134 135 NTSTATUS136 GetLocalTime (OUT PTIME_FIELDS timeFields) 137/* ++ 138 -- */139 {140 NTSTATUS status = STATUS_SUCCESS; 141 LARGE_INTEGER sysTime, locTime; 142 143 KeQuerySystemTime (& sysTime); 144 ExSystemTimeToLocalTime (& sysTime, & locTime); 145 RtlTimeToTimeFields (& locTime, timeFields); 146 147 return STATUS_SUCCESS; 148 149 150} 151 VOID TestFile (IN PDEVICE_OBJECT DeviceObject, 152 IN PmyInfo pmyInfo) 153 154 {155 TIME_FIELDS time; 156 UNICODE_STRING string; 157 HANDLE hFile; 158 IO_STATUS_BLOCK iostatus; 159 NTSTATUS status; 160 WCHAR pBuffer [200]; 161 OBJECT_ATTRIBUTES objattr; 162 LARGE_INTEGER ByteOffset; 163 KIRQL irql; 164 165 RtlInitUnicode String (& string, L "\\?? \ C: \ Log \ 1.log"); 166 InitializeObjectAttributes (& objattr, & string, OBJ_CASE_INSENSITIVE, NULL, NULL); 167 GetLocalTime (& time ); 168 irql = KeGetCurrentIrql (); 169 KdPrint ("dpc: cur irql = % d", irql); 170 // open the file 171 status = ZwCreateFile (& hFile, FILE_APPEND_DATA, 172 & objattr, & iostatus, 173 NULL, FILE_ATTRIBUTE_NORMAL, 174 file_0000_write, 175 FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); 176 177 s Wprintf (pBuffer, L "[% d-% d]", 178 time. year, 179 time. month, 180 time. day, 181 time. hour, 182 time. minute, 183 time. second); 184 KdPrint ("dpc: % S", pBuffer); 185 KdPrint ("dpc: my age is % d, my weight is % d, my name is % s \ n ", 186 pmyInfo-> age, pmyInfo-> weight, pmyInfo-> name); 187 // Write File 188 status = ZwWriteFile (hFile, NULL, & iostatus, 189 pBuffer, wcslen (pBuffer) * sizeof (WCHAR), NULL, NULL); 190 // write the linefeed 191 status = ZwWriteFile (hFile, NULL, & iostatus, 192 L "\ n", sizeof (WCHAR), NULL, NULL); 193 194 // close file handle 195 ZwClose (hFile); 196 // release memory 197 // ExFreePool (pBuffer ); 198 199 200} 201 202 VOID SyncTechUnload (IN PDRIVER_OBJECT DriverObject) 203 {204 205 KeCancelTimer (& Timer); 206 IoFreeWorkItem (pIoWorkItem); 207 IoDeleteDevice (DriverObject-> DeviceObject ); 208 KdPrint ("dpc: DpcTest Unload! \ N "); 209 210}
The code is assigned, pasted, and installed after compilation. sys can be directly run.