APC初始化:KeInitializeApc(位于ntoskrnl/ke/apc.c
):
- 设置APC对象类型,填充APC结构大小
- 设置APC状态索引
- 如果参数环境TargetEnvironment为CurrentApcEnvironment,则将当前线程的APC状态索引赋值给APC
- 如果参数环境TargetEnvironment为其他三种,则将TargetEnvironment赋值给APC
- 填充APC结构:所属线程,APC三个函数
- KernelRoutine函数:所有APC都有的函数,会第一个被执行
- RundownRoutine函数:在APC执行期间线程退出了,则执行此函数
- NormalRoutine函数:在PASSIVE_LEVEL IRQL下执行,如果没有制定,APC则是特殊APC,参数和执行模式将被忽略
- 根据NormalRoutine的值判断APC类型来进行字段填充
- 如果有值,表示是普通APC,设置APC的运行模式和该函数的第一个参数
- 如果无值,表示是特殊内核APC,设置APC为内核模式,参数为NULL
- 最后将APC插入标志设置为False
这个函数主要是填充APC结构KAPC的
KeInitializeApc
/*++
* KeInitializeApc
* @implemented NT4
*
* The KeInitializeApc routine initializes an APC object, and registers
* the Kernel, Rundown and Normal routines for that object.
*
* @param Apc
* Pointer to a KAPC structure that represents the APC object to
* initialize. The caller must allocate storage for the structure
* from resident memory.
*
* @param Thread
* Thread to which to deliver the APC.
*
* @param TargetEnvironment
* APC Environment to be used.
*
* @param KernelRoutine
* Points to the KernelRoutine to associate with the APC.
* This routine is executed for all APCs.
*
* @param RundownRoutine
* Points to the RundownRoutine to associate with the APC.
* This routine is executed when the Thread exits during APC execution.
*
* @param NormalRoutine
* Points to the NormalRoutine to associate with the APC.
* This routine is executed at PASSIVE_LEVEL. If this is not specifed,
* the APC becomes a Special APC and the Mode and Context parameters are
* ignored.
*
* @param Mode
* Specifies the processor mode at which to run the Normal Routine.
*
* @param Context
* Specifices the value to pass as Context parameter to the registered
* routines.
*
* @return None.
*
* @remarks The caller can queue an initialized APC with KeInsertQueueApc.
*
*--*/
VOID
NTAPI
KeInitializeApc(IN PKAPC Apc,
IN PKTHREAD Thread,
IN KAPC_ENVIRONMENT TargetEnvironment,
IN PKKERNEL_ROUTINE KernelRoutine,
IN PKRUNDOWN_ROUTINE RundownRoutine OPTIONAL,
IN PKNORMAL_ROUTINE NormalRoutine,
IN KPROCESSOR_MODE Mode,
IN PVOID Context)
{
//typedef enum _KAPC_ENVIRONMENT {
// OriginalApcEnvironment, 原始环境
// AttachedApcEnvironment, 挂靠环境
// CurrentApcEnvironment, 当前环境
// InsertApcEnvironment 插入环境
//} KAPC_ENVIRONMENT;
/* Sanity check */
// 目标环境要小于3
ASSERT(TargetEnvironment <= InsertApcEnvironment);
/* Set up the basic APC Structure Data */
// apc结构填充,设置对象类型为APC对象,设置APC大小
Apc->Type = ApcObject;
Apc->Size = sizeof(KAPC);
/* Set the Environment */
// 判断环境是否为2:CurrentApcEnvironment
if (TargetEnvironment == CurrentApcEnvironment)
{
// 如果要初始化的APC对象的环境是当前环境,则
/* Use the current one for the thread */
// 用当前线程的APC索引来设置APC的APC索引(指向一个apc数组)
Apc->ApcStateIndex = Thread->ApcStateIndex;
}
else
{
// 否则,先确保初始化的环境为_KAPC_ENVIRONMENT枚举类型存在的值
/* Sanity check */
// <=线程的索引
ASSERT((TargetEnvironment <= Thread->ApcStateIndex) ||
(TargetEnvironment == InsertApcEnvironment));
/* Use the one that was given */
// 将初始化的环境赋值给Apc对象的环境
Apc->ApcStateIndex = TargetEnvironment;
}
/* Set the Thread and Routines */
// 填充APC结构:所属线程
Apc->Thread = Thread; // 参数传递的,APC归属的线程
// APc可以执行的三个函数
Apc->KernelRoutine = KernelRoutine; // 必须有
Apc->RundownRoutine = RundownRoutine; // 可有可无
Apc->NormalRoutine = NormalRoutine; // 如果没有,则是特殊内核APC
/* Check if this is a special APC */
// 检查是不是特殊APC
if (NormalRoutine)
{
// 如果有这个函数,则表示是普通APC
/* It's a normal one. Set the context and mode */
// 设置APC运行模式:用户层或内核层
Apc->ApcMode = Mode;
// 设置context,第一个参数
Apc->NormalContext = Context;
}
else
{
// 否则是特殊APC,只有内核模式
/* It's a special APC, which can only be kernel mode */
Apc->ApcMode = KernelMode;
Apc->NormalContext = NULL;
}
/* The APC is not inserted */
// 将APC插入标志设置为未插入
Apc->Inserted = FALSE;
}