NTSTATUS KeWaitForMultipleObjects( IN ULONG Count,// IN PVOID Object[], IN WAIT_TYPE WaitType, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable,// IN PLARGE_INTEGER Timeout OPTIONAL, IN PKWAIT_BLOCK WaitBlockArray OPTIONAL );Alertable是一个布尔类型的值。它不同于WaitReason,这个参数以另一种方式影响系统行为,它决定等待是否可以提前终止以提交一个APC。如果等待发生在用户模式中,那么内存管理器就可以把线程的内核模式堆栈换出。如果驱动程序以自动变量(在堆栈中)形式创建事件对象,并且某个线程又在提升的IRQL级上调用了KeSetEvent,而此时该事件对象刚好又被换出内存,结果将产生一个bug check。所以我们应该总把alertable参数指定为FALSE,即在内核模式中等待。
Timeout是一个64位超时值的地址,单位为100纳秒。正数的超时表示一个从1601年1月1日起的绝对时间。调用KeQuerySystemTime函数可以获得当前系统时间。负数代表相对于当前时间的时间间隔。如果你指定了绝对超时,那么系统时钟的改变也将影响到你的超时时间。如果系统时间越过你指定的绝对时间,那么永远都不会超时。相反,如果你指定相对超时,那么你经过的超时时间将不受系统时钟改变的影响,指定为NULL表示永久等待
NTSTATUS PsCreateSystemThread( OUT PHANDLE ThreadHandle,//得到新创建的线程句柄 IN ULONG DesiredAccess,//创建的权限 IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,//一般设为NULL IN HANDLE ProcessHandle OPTIONAL,//如果是进程句柄,则线程属于指定的进程,如果NULL,则为系统进程 OUT PCLIENT_ID ClientId OPTIONAL,//驱动创建时,设为NULL IN PKSTART_ROUTINE StartRoutine,//新线程的运行地址 IN PVOID StartContext//新线程接收的参数 );系统进程指ID为4的System进程,创建的线程并须自己用PsTerminateSystemThread强制结束线程,否则线程是无法自动退出的,这个调用必须在IRQL=PASSIVE_LEVEL下进行
#define IOCTL_TEST2 CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS¦FILE_WRITE_ACCESS) #pragma code_seg("PAGE") VOID SystemThread(PVOID pContext) { KdPrint(("Entry SystemThreadn")); PEPROCESS pEProcess = IoGetCurrentProcess(); PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174); KdPrint(("This Thread run in %s processn", ProcessName)); PsTerminateSystemThread(STATUS_SUCCESS); KdPrint(("Leave SystemThreadn")); } #pragma code_seg("PAGE") VOID MyThread(PVOID pContext) { KdPrint(("Entry MyThread:%sn", (CHAR*)pContext)); PEPROCESS pEProcess = IoGetCurrentProcess(); PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174); KdPrint(("This Thread run in %s processn", ProcessName)); PsTerminateSystemThread(STATUS_SUCCESS); KdPrint(("Leave MyThreadn")); } #pragma code_seg("PAGE") VOID CreateThreadTest() { HANDLE hSysThread = NULL; HANDLE hMyThread = NULL; CHAR *p = "parameter"; NTSTATUS status = PsCreateSystemThread (&hSysThread, 0, NULL, NULL, NULL, SystemThread, NULL); status = PsCreateSystemThread (&hMyThread, 0, NULL, NtCurrentProcess(), NULL, MyThread, (PVOID)p); }