驱动开发之 创建线程函数PsCreateSystemThread

PsCreateSystemThread 创建一个执行在内核模式的系统线程。

注意:创建线程必须用函数PsTerminateSystemThread强制线程结束。否则该线程是无法自动退出的。

函数原型:

 

  1. NTSTATUS PsCreateSystemThread(  
  2.   _Out_      PHANDLE ThreadHandle,  
  3.   _In_       ULONG DesiredAccess,  
  4.   _In_opt_   POBJECT_ATTRIBUTES ObjectAttributes,  
  5.   _In_opt_   HANDLE ProcessHandle,  
  6.   _Out_opt_  PCLIENT_ID ClientId,  
  7.   _In_       PKSTART_ROUTINE StartRoutine,  
  8.   _In_opt_   PVOID StartContext  
  9. );  
  1. NTSTATUS PsCreateSystemThread(  
  2.   _Out_      PHANDLE ThreadHandle,  
  3.   _In_       ULONG DesiredAccess,  
  4.   _In_opt_   POBJECT_ATTRIBUTES ObjectAttributes,  
  5.   _In_opt_   HANDLE ProcessHandle,  
  6.   _Out_opt_  PCLIENT_ID ClientId,  
  7.   _In_       PKSTART_ROUTINE StartRoutine,  
  8.   _In_opt_   PVOID StartContext  
  9. );  
NTSTATUS PsCreateSystemThread(
  _Out_      PHANDLE ThreadHandle,
  _In_       ULONG DesiredAccess,
  _In_opt_   POBJECT_ATTRIBUTES ObjectAttributes,
  _In_opt_   HANDLE ProcessHandle,
  _Out_opt_  PCLIENT_ID ClientId,
  _In_       PKSTART_ROUTINE StartRoutine,
  _In_opt_   PVOID StartContext
);

 


参数说明

ThreadHandle [out]

         返回的handle。当此handle不再使用时,调用ZwClose关闭。对于windows vista以及以后版本,这个handle是一个内核句柄。

DesiredAccess [in]

         ACCESS_MASK值,创建的权限。一般取THREAD_ALL_ACCESS。

ObjectAttributes [in, optional]

         线程属性,一般设为null。

ProcessHandle [in, optional]

         线程所在地址空间的进程的handle。对于驱动线程,通常设为NULL。也可以设为NtCurrentProcess()指定为当前进程。

ClientId [out, optional]

         对于驱动线程设为null。

StartRoutine [in]

         函数指针,创建的系统线程的入口指针。此函数接受一个参数,就是StartContext。

StartContext [in, optional]

         线程执行时传给StartRoutine的参数。

 

返回值

 

PsCreateSystemThread成功返回 STATUS_SUCCESS。

例子1:

  1. NTSTATUS lstatus;  
  2. lstatus = PsCreateSystemThread( &hThread,   
  3.                 0,  
  4.         NULL, //或者THREAD_ALL_ACCESS  
  5.         NtCurrentProcess(),   
  6.         NULL,   
  7.         (PKSTART_ROUTINE)ThreadProc,  
  8.         NULL );  
  9. if (!NT_SUCCESS(lstatus))  
  10. {  
  11.     ;  
  12. }  
  1. NTSTATUS lstatus;  
  2. lstatus = PsCreateSystemThread( &hThread,   
  3.                 0,  
  4.         NULL, //或者THREAD_ALL_ACCESS  
  5.         NtCurrentProcess(),   
  6.         NULL,   
  7.         (PKSTART_ROUTINE)ThreadProc,  
  8.         NULL );  
  9. if (!NT_SUCCESS(lstatus))  
  10. {  
  11.     ;  
  12. }  
NTSTATUS lstatus;
lstatus = PsCreateSystemThread( &hThread, 
                0,
		NULL, //或者THREAD_ALL_ACCESS
		NtCurrentProcess(), 
		NULL, 
		(PKSTART_ROUTINE)ThreadProc,
		NULL );
if (!NT_SUCCESS(lstatus))
{
	;
}
  1. NTSTATUS   
  2.     ThreadProc()  
  3. {  
  4.     DbgPrint("CreateThread Successfully");    
  5.     //创建线程必须用函数PsTerminateSystemThread强制线程结束。否则该线程是无法自动退出的。      
  6.     PsTerminateSystemThread(STATUS_SUCCESS);    
  7. }  
  1. NTSTATUS   
  2.     ThreadProc()  
  3. {  
  4.     DbgPrint("CreateThread Successfully");    
  5.     //创建线程必须用函数PsTerminateSystemThread强制线程结束。否则该线程是无法自动退出的。      
  6.     PsTerminateSystemThread(STATUS_SUCCESS);    
  7. }  
NTSTATUS 
	ThreadProc()
{
	DbgPrint("CreateThread Successfully");  
	//创建线程必须用函数PsTerminateSystemThread强制线程结束。否则该线程是无法自动退出的。    
	PsTerminateSystemThread(STATUS_SUCCESS);  
}

2.提供一种方式来通知线程终止并等待终止发生。

 

 

  1. typedef struct _DEVICE_EXTENSION {  
  2.   ...  
  3.   KEVENT evKill;//在设备扩展中声明一个KEVENT对象  
  4.   PKTHREAD thread;  
  5. };  
  6.   
  7. NTSTATUS StartThread(PDEVICE_EXTENSION pdx)  
  8. {  
  9.   NTSTATUS status;  
  10.   HANDLE hthread;  
  11.   KeInitializeEvent(&pdx->evKill, NotificationEvent, FALSE);                       
  12.   status = PsCreateSystemThread(&hthread,   //创建新线程                           
  13.                 THREAD_ALL_ACCESS,  
  14.                 NULL,  
  15.                 NULL,  
  16.                 NULL,  
  17.                 (PKSTART_ROUTINE) ThreadProc,  
  18.                 pdx);  
  19.   if (!NT_SUCCESS(status))  
  20.     return status;  
  21.   ObReferenceObjectByHandle(hthread,        //为了等待线程终止,你需要KTHREAD对象的地址来代替从PsCreateSystemThread获得的线程句柄。  
  22.                 THREAD_ALL_ACCESS,  //调用ObReferenceObjectByHandle获得这个地址。  
  23.                 NULL,  
  24.                 KernelMode,  
  25.                 (PVOID*) &pdx->thread,  
  26.                 NULL);  
  27.   ZwClose(hthread);         //现在可以关闭线程句柄了,因为已经得到thread                        
  28.   return STATUS_SUCCESS;  
  29. }  
  30.   
  31. VOID StopThread(PDEVICE_EXTENSION pdx)  
  32. {  
  33.   KeSetEvent(&pdx->evKill, 0, FALSE);                                      
  34.   KeWaitForSingleObject(pdx->thread, Executive, KernelMode, FALSE, NULL);                  
  35.   ObDereferenceObject(pdx->thread);                                    
  36. }  
  37.   
  38. VOID ThreadProc(PDEVICE_EXTENSION pdx)  
  39. {  
  40.   ...  
  41.   KeWaitForXxx(<at least pdx->evKill>);                                      
  42.   ...  
  43.   PsTerminateSystemThread(STATUS_SUCCESS);                                
  44. }  
  1. typedef struct _DEVICE_EXTENSION {  
  2.   ...  
  3.   KEVENT evKill;//在设备扩展中声明一个KEVENT对象  
  4.   PKTHREAD thread;  
  5. };  
  6.   
  7. NTSTATUS StartThread(PDEVICE_EXTENSION pdx)  
  8. {  
  9.   NTSTATUS status;  
  10.   HANDLE hthread;  
  11.   KeInitializeEvent(&pdx->evKill, NotificationEvent, FALSE);                       
  12.   status = PsCreateSystemThread(&hthread,   //创建新线程                           
  13.                 THREAD_ALL_ACCESS,  
  14.                 NULL,  
  15.                 NULL,  
  16.                 NULL,  
  17.                 (PKSTART_ROUTINE) ThreadProc,  
  18.                 pdx);  
  19.   if (!NT_SUCCESS(status))  
  20.     return status;  
  21.   ObReferenceObjectByHandle(hthread,        //为了等待线程终止,你需要KTHREAD对象的地址来代替从PsCreateSystemThread获得的线程句柄。  
  22.                 THREAD_ALL_ACCESS,  //调用ObReferenceObjectByHandle获得这个地址。  
  23.                 NULL,  
  24.                 KernelMode,  
  25.                 (PVOID*) &pdx->thread,  
  26.                 NULL);  
  27.   ZwClose(hthread);         //现在可以关闭线程句柄了,因为已经得到thread                        
  28.   return STATUS_SUCCESS;  
  29. }  
  30.   
  31. VOID StopThread(PDEVICE_EXTENSION pdx)  
  32. {  
  33.   KeSetEvent(&pdx->evKill, 0, FALSE);                                      
  34.   KeWaitForSingleObject(pdx->thread, Executive, KernelMode, FALSE, NULL);                  
  35.   ObDereferenceObject(pdx->thread);                                    
  36. }  
  37.   
  38. VOID ThreadProc(PDEVICE_EXTENSION pdx)  
  39. {  
  40.   ...  
  41.   KeWaitForXxx(<at least pdx->evKill>);                                      
  42.   ...  
  43.   PsTerminateSystemThread(STATUS_SUCCESS);                                
  44. }  
typedef struct _DEVICE_EXTENSION {
  ...
  KEVENT evKill;//在设备扩展中声明一个KEVENT对象
  PKTHREAD thread;
};

NTSTATUS StartThread(PDEVICE_EXTENSION pdx)
{
  NTSTATUS status;
  HANDLE hthread;
  KeInitializeEvent(&pdx->evKill, NotificationEvent, FALSE);						
  status = PsCreateSystemThread(&hthread,	//创建新线程							
				THREAD_ALL_ACCESS,
				NULL,
				NULL,
				NULL,
				(PKSTART_ROUTINE) ThreadProc,
				pdx);
  if (!NT_SUCCESS(status))
    return status;
  ObReferenceObjectByHandle(hthread,		//为了等待线程终止,你需要KTHREAD对象的地址来代替从PsCreateSystemThread获得的线程句柄。
			    THREAD_ALL_ACCESS,  //调用ObReferenceObjectByHandle获得这个地址。
			    NULL,
			    KernelMode,
			    (PVOID*) &pdx->thread,
			    NULL);
  ZwClose(hthread);			//现在可以关闭线程句柄了,因为已经得到thread						
  return STATUS_SUCCESS;
}

VOID StopThread(PDEVICE_EXTENSION pdx)
{
  KeSetEvent(&pdx->evKill, 0, FALSE);									
  KeWaitForSingleObject(pdx->thread, Executive, KernelMode, FALSE, NULL);				
  ObDereferenceObject(pdx->thread);									
}

VOID ThreadProc(PDEVICE_EXTENSION pdx)
{
  ...
  KeWaitForXxx(<at least pdx->evKill>);									
  ...
  PsTerminateSystemThread(STATUS_SUCCESS);								
}

jpg改rar

 



转载于:https://www.cnblogs.com/kuangke/p/5597052.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值