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

时间:2021-11-06 18:49:31

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