selph
selph
发布于 2021-11-13 / 345 阅读
0
0

APC初始化过程--基于Windows XP源码

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;
}

评论