0.driverbase-Wait函数和创建线程(sytem和本进程)

来源:互联网 发布:sql asin() 编辑:程序博客网 时间:2024/06/05 04:15

1. Wait函数

用户模式下的WaitForSingleObject和WaitForMultipleObject都是依赖内核模式下的KeWaitForSingleObject和KeWaitForMultipleObjects函数实现的,其声明如下:

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表示永久等待


2.创建线程

内核下创建新线程使用PsCreateSystemThread

NTSTATUS  PsCreateSystemThread(OUT PHANDLE  ThreadHandle,//得到新创建的线程句柄IN ULONG  DesiredAccess,//创建的权限IN POBJECT_ATTRIBUTES  ObjectAttributes  OPTIONAL,//一般设为NULLIN HANDLE  ProcessHandle  OPTIONAL,//如果是进程句柄,则线程属于指定的进程,如果NULL,则为系统进程OUT PCLIENT_ID  ClientId  OPTIONAL,//驱动创建时,设为NULLIN 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); }

调用方式:使用demo发个IO控制码过去,调用CreateThreadTest即可