[转](73)分析 KeInitializeApc ,了解 KAPC 的初始化

 

一、回顾

 

第71篇博客我们分析了 PspTerminateThreadByPointer 函数,其中调用了 KeInitializeApc 函数初始化 KAPC 结果。这次课我们来分析 KeInitializeApc 函数,了解 APC 如何初始化。

 

PspTerminateThreadByPointer(psdelete.c) 调用 KeInitializeApc

 

KeInitializeApc (ExitApc,
                 PsGetKernelThread (Thread),
                 OriginalApcEnvironment,		// 父进程
                 PsExitSpecialApc,				// 释放APC内存,退出当前线程
                 PspExitApcRundown,				// 释放APC内存
                 PspExitNormalApc,				
                 KernelMode,					// 内核模式
                 ULongToPtr (ExitStatus));		// 线程退出码

 

NtQueueApcThread(psctx.c) 调用 KeInitializeApc

 

KeInitializeApc (Apc,
    &Thread->Tcb,
    OriginalApcEnvironment,			// 插入到所属进程(创建线程的那个进程)
    PspQueueApcSpecialApc,			// KernelRoutine , 作用是释放 APC 内存(ExFreePool)
    NULL,							// RundownRoutine 未指定
    (PKNORMAL_ROUTINE)ApcRoutine,	// 用户APC总入口 BaseDispatchAPC(3环函数)
    UserMode,						// 用户模式APC
    ApcArgument1);					// 3环APC函数

 

二、KeInitializeApc (apcobj.c)

 

这个函数比较简单,就是初始化,最难理解的是 ApcStateIndex ,我已经在注释里写清楚了,还是不懂的话,可以结合 KiInsertQueueApc 函数来分析 ApcStateIndex 的用途。

 

VOID
KeInitializeApc (
    IN PRKAPC Apc,									// APC结构体指针
    IN PRKTHREAD Thread,							// 要插入APC的目标线程
    IN KAPC_ENVIRONMENT Environment,				// 四种环境状态,包括父进程,挂靠进程,当前进程(提供CR3的进程),插入时的当前进程
    IN PKKERNEL_ROUTINE KernelRoutine,				// 不管是用户APC还是内核APC,这个函数的共同作用是释放APC;内核APC可能会有额外的功能,如退出、挂起、恢复线程
    IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,	// 如果是用户APC,这里是NULL;如果是要求退出线程的内核APC,这里是 PspExitApcRundown
    IN PKNORMAL_ROUTINE NormalRoutine OPTIONAL,		// 如果是用户APC,这里是 BaseDispatchAPC(3环函数);
													// 如果是内核APC,这里就是内核APC函数
    IN KPROCESSOR_MODE ApcMode OPTIONAL,			// 用户模式 / 内核模式
    IN PVOID NormalContext OPTIONAL					// 如果是用户APC,这里就是3环提供的APC函数的参数
    )

/*++

Routine Description:

    This function initializes a kernel APC object. The thread, kernel
    routine, and optionally a normal routine, processor mode, and normal
    context parameter are stored in the APC object.

	分配空间,初始化KAPC结构体

Arguments:

    Apc - Supplies a pointer to a control object of type APC.

    Thread - Supplies a pointer to a dispatcher object of type thread.

    Environment - Supplies the environment in which the APC will execute.
        Valid values for this parameter are: OriginalApcEnvironment,
        AttachedApcEnvironment, CurrentApcEnvironment, or InsertApcEnvironment

    KernelRoutine - Supplies a pointer to a function that is to be
        executed at IRQL APC_LEVEL in kernel mode.

    RundownRoutine - Supplies an optional pointer to a function that is to be
        called if the APC is in a thread's APC queue when the thread terminates.

    NormalRoutine - Supplies an optional pointer to a function that is
        to be executed at IRQL 0 in the specified processor mode. If this
        parameter is not specified, then the ProcessorMode and NormalContext
        parameters are ignored.

    ApcMode - Supplies the processor mode in which the function specified
        by the NormalRoutine parameter is to be executed.

    NormalContext - Supplies a pointer to an arbitrary data structure which is
        to be passed to the function specified by the NormalRoutine parameter.	

Return Value:

    None.

--*/

{

    ASSERT(Environment <= InsertApcEnvironment);

    //
    // Initialize standard control object header.
    //

    Apc->Type = ApcObject; // 0x12 内核对象类型
    Apc->Size = sizeof(KAPC);

    //
    // Initialize the APC environment, thread address, kernel routine address,
    // rundown routine address, normal routine address, processor mode, and
    // normal context parameter. If the normal routine address is null, then
    // the processor mode is defaulted to KernelMode and the APC is a special
    // APC. Otherwise, the processor mode is taken from the argument list.
    //

	
	//typedef enum _KAPC_ENVIRONMENT {
	//	OriginalApcEnvironment, // 所属进程(创建线程的进程)
	//	AttachedApcEnvironment, // 挂靠进程
	//	CurrentApcEnvironment,	// 当前环境,提供CR3的进程(正常状态是所属进程,挂靠状态是挂靠进程)
	//	InsertApcEnvironment	// 插入APC时的环境
	//} KAPC_ENVIRONMENT;

	// ApcStateIndex 决定了挂到哪个进程的APC队列

    if (Environment == CurrentApcEnvironment) {
		// 如果要求的是当前状态,那么就从 Thread->ApcStateIndex 里取值,如果当前没有挂靠,则是0,;如果挂靠了,就是1.
        Apc->ApcStateIndex = Thread->ApcStateIndex;

    } else {
		
        ASSERT((Environment <= Thread->ApcStateIndex) || (Environment == InsertApcEnvironment));

		// 否则就默认插入到所属进程(创建线程的进程)的APC队列里
        Apc->ApcStateIndex = (CCHAR)Environment;
    }

    Apc->Thread = Thread;					// 目标线程
    Apc->KernelRoutine = KernelRoutine;		// 主要功能是释放APC
    Apc->RundownRoutine = RundownRoutine;	// 可选,退出线程时会用到
    Apc->NormalRoutine = NormalRoutine;		// 如果是用户APC,这里是 BaseDispatchAPC(3环函数);
											// 如果是内核APC,这里就是内核APC函数
    if (ARGUMENT_PRESENT(NormalRoutine)) {
        Apc->ApcMode = ApcMode; // 0内核,1用户
        Apc->NormalContext = NormalContext; // 内核APC:NULL;用户APC:真正的APC函数

    } else {
        Apc->ApcMode = KernelMode;
        Apc->NormalContext = NIL; // NULL
    }

    Apc->Inserted = FALSE;
    return;
}


---------------------
作者:hambaga
来源:CSDN
原文:https://blog.csdn.net/Kwansy/article/details/110234089
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:CSDN,CNBLOG博客文章一键转载插件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值