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的更多相关文章

  1. [笔记]linux下和windows下的 创建线程函数

    linux下和windows下的 创建线程函数 #ifdef __GNUC__ //Linux #include <pthread.h> #define CreateThreadEx(ti ...

  2. Windows驱动开发-手动创建IRP

    手动创建IRP有以下几个步骤: 1,先得到设备的指针,一种方法是用IoGetDeviceObjectPointer内核函数得到设备对象指针,另外一种方法是用zwCreateFile内核函数先得到设备句 ...

  3. Windows驱动开发-内核常用内存函数

    搞内存常用函数 C语言 内核 malloc ExAllocatePool memset RtlFillMemory memcpy RtlMoveMemory free ExFreePool

  4. WordPress 主题开发 - (六) 创建主题函数 待翻译

    We’ve got a file structure in place, now let’s start adding things to them! First, we’re going to ad ...

  5. linux线程笔记1之创建线程

    1 线程与进程的对比 这里有一个笔记详细的阐述 http://blog.csdn.net/laviolette/article/details/51506953 2 创建线程函数 int pthrea ...

  6. 4、linux下应用创建线程

    1.linux创建线程之pthread_create 函数简介 pthread_create是UNIX环境创建线程函数 头文件 #include<pthread.h> 函数声明 int p ...

  7. Windows驱动开发之线程与同步事件

    转载请注明来源: enjoy5512的博客 : http://blog.csdn.net/enjoy5512 GitHub : https://github.com/whu-enjoy .1. 使用系 ...

  8. 《Windows内核安全与驱动开发》 4.4 线程与事件

    <Windows内核安全与驱动开发>阅读笔记 -- 索引目录 <Windows内核安全与驱动开发> 4.4 线程与事件 一.开辟一个线程,参数为(打印内容+打印次数),利用线程 ...

  9. iOS开发多线程篇—创建线程

    iOS开发多线程篇—创建线程 一.创建和启动线程简单说明 一个NSThread对象就代表一条线程 创建.启动线程 (1) NSThread *thread = [[NSThread alloc] in ...

随机推荐

  1. <转>VPN技术原理

    原文地址:VPN技术原理 VPN,Virtual Private Network(虚拟专用 网络),被定义为通过一个公用网络(通常是因特网)建立一个临时的.安全的连接,是一条穿过公用网络的安全.稳定的 ...

  2. VIM常用操作总结

    VIM常用的模式网上说法不太一样,但是大同小异,这里大致分一下,便于后面总结 1.一般模式 默认打开文件后的模式,这个时候只能移动光标,不能编辑 2.输入模式 一般模式按下i,就可以进入输入模式,输入 ...

  3. How to raise exceptions in Delphi

    uses SysUtils; procedure RaiseMyException; begin raise Exception.Create('Hallo World!'); end;

  4. ffmpeg-20160731-bin.7z

    ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 f ...

  5. 数据结构——B树、B+树

    B树和B+树主要应用于外排序,对于外排序,从硬盘读取的时间要远远大于遍历树的时间,因此要想办法减少从硬盘读取的时间. B树(有时也叫B-树) M阶B树定义如下: 是一种多路搜索树(并不是二叉的):1. ...

  6. UVALive 6577 Binary Tree 二叉树的LRU串

    今天继续攒人品...真开心啊O(∩_∩)O~~各种身体不舒服~~ https://icpcarchive.ecs.baylor.edu/external/65/6577.pdf 题意是这样的,现在有一 ...

  7. C# 操作IIS方法集合

    如果在win8,win7情况下报错:未知错误(0x80005000) 见http://blog.csdn.net/ts1030746080/article/details/8741399 using ...

  8. 【linux】linux脚本中#!/bin/sh的含义

    来源:百度知道 #! /bin/sh 是指此脚本使用,/bin/sh来解释执行,#!是特殊的表示符,其后面根的是此解释此脚本的shell的路径.

  9. 【XLL 框架库函数】 Excel/Excel12f

    Excel/Excel12f 这两个库函数分别包装了 C API 中的 Excel4 和 Excel12 函数,它们会检查函数没有参数时是否为零,它将表明创建临时的 XLOPER 或 XLOPER12 ...

  10. Hibernate单向多对一对象关系模型映射

    单向的many-to-one 案例: 班级和学生 父亲和子女 单向:只能由其中一方维护关系 Many-to-one中有many的一方法维护或者体现两者之间的关系. 单向的many-to-one描述学生 ...