驱动开发之 创建线程函数PsCreateSystemThread
PsCreateSystemThread 创建一个执行在内核模式的系统线程。
注意:创建线程必须用函数PsTerminateSystemThread强制线程结束。否则该线程是无法自动退出的。
函数原型:
- 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
- );
- 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
- );
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:
- NTSTATUS lstatus;
- lstatus = PsCreateSystemThread( &hThread,
- 0,
- NULL, //或者THREAD_ALL_ACCESS
- NtCurrentProcess(),
- NULL,
- (PKSTART_ROUTINE)ThreadProc,
- NULL );
- if (!NT_SUCCESS(lstatus))
- {
- ;
- }
- NTSTATUS lstatus;
- lstatus = PsCreateSystemThread( &hThread,
- 0,
- NULL, //或者THREAD_ALL_ACCESS
- NtCurrentProcess(),
- NULL,
- (PKSTART_ROUTINE)ThreadProc,
- NULL );
- if (!NT_SUCCESS(lstatus))
- {
- ;
- }
NTSTATUS lstatus; lstatus = PsCreateSystemThread( &hThread, 0, NULL, //或者THREAD_ALL_ACCESS NtCurrentProcess(), NULL, (PKSTART_ROUTINE)ThreadProc, NULL ); if (!NT_SUCCESS(lstatus)) { ; }
- NTSTATUS
- ThreadProc()
- {
- DbgPrint("CreateThread Successfully");
- //创建线程必须用函数PsTerminateSystemThread强制线程结束。否则该线程是无法自动退出的。
- PsTerminateSystemThread(STATUS_SUCCESS);
- }
- NTSTATUS
- ThreadProc()
- {
- DbgPrint("CreateThread Successfully");
- //创建线程必须用函数PsTerminateSystemThread强制线程结束。否则该线程是无法自动退出的。
- PsTerminateSystemThread(STATUS_SUCCESS);
- }
NTSTATUS ThreadProc() { DbgPrint("CreateThread Successfully"); //创建线程必须用函数PsTerminateSystemThread强制线程结束。否则该线程是无法自动退出的。 PsTerminateSystemThread(STATUS_SUCCESS); }
2.提供一种方式来通知线程终止并等待终止发生。
- 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);
- }
- 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);
- }
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