百度空间 | 百度首页 
 
查看文章
 
[note]WRK--MmFlushImageSection相关(1)
2007年11月28日 星期三 13:08

最近开始学习文件过滤驱动。资料打印了部分(不过都是英文的,而且WINDOWS Internal的PDF还有保护,不能打印,郁闷啊);

上网时候就到处溜达,找点文章资料和部分代码看看. 于是在kanxue看到了一篇关于删除正在运行的程序文件的帖子:bbs.pediy.com/showthread.php.哈哈,正好拿来学习~~~~

---------------------------------------------资料查到哪儿写到哪儿--------------------------------------------------

① Interrupt Objects

每个驱动的物理设备都要产生中断,就必须注册一个ISR,此时系统创建一个interrupt object来保存信息

  • The set of processors on which interrupts can occur (processor affinity) [晕,这个没看明白]
  • The system-assigned interrupt vectors for each device on each I/O bus in the machine
  • The DIRQL assigned to each system interrupt vector
  • The address of the InterruptService routine, which will be called when the device interrupts.
  • Additional information for internal use by the system.

运用Interrupt Objects可以使驱动兼容各个WINDOWS版本,因为驱动不是直接访问硬件,而是传递指向Interrupt Objects的指针到系统,由系统获得对象内容.

② Input parameters for all Dispatch routines are supplied in the IRP structure pointed to by Irp. Additional parameters are supplied in the driver's associated I/O stack location, which is described by the IO_STACK_LOCATION structure and can be obtained by calling IoGetCurrentIrpStackLocation.

③ Registering an ISR

通过IoConnectInterrupt注册ISR. 好像很复杂,看了一下,头晕了.discard...

④ Providing ISR Context Information

或者存放在device object中,或者是device extension 中

⑤ Writing an ISR

ISR这个东西会竭尽全力去解除此中断,possibly including stopping the device from interrupting.然后保存当前状态,排队一个DPC来完成I/O操作,这个过程的IRQL小于当前的ISR's

A driver's ISR executes in an interrupt context, at some system-assigned DIRQL, as specified by the SynchronizeIrql parameter to IoConnectInterrupt.

In general, an ISR does no actual I/O processing to satisfy an IRP. Instead, it stops its device from interrupting, sets up necessary state information, and queues the driver’s DpcForIsr or CustomDpc to do whatever I/O processing is necessary to satisfy the current request that caused the device to interrupt.

⑥ Synchronizing Access to Device Data

Raising the processor's IRQL to the device's DIRQL value prevents the current processor from being interrupted, except by a higher-priority device. Acquiring a spin lock prevents other processors from executing any critical section code associated with that spin lock. (This spin lock is sometimes called an interrupt spin lock.)

---------------------------------------------sudami.的分割线--------------------------------------------------

哈哈,一大堆函数,慢慢的看.先把这些函数看完,做个铺垫,然后再读MmFlushImageSection函数的源码就容易多了; 现在来看看 LOCK_PFN 这个龌龊的宏

#define LOCK_PFN(OLDIRQL) ASSERT (KeGetCurrentIrql() <= APC_LEVEL);         \
                          MiLockPfnDatabase(OLDIRQL);                       \
                          MI_SET_PFN_OWNER ();                              \
                          LOCK_PFN_TIMESTAMP();

MiLockPfnDatabase也是一个宏,它调用的是上面图片中的函数: KeAcquireQueuedSpinLock (This function raises IRQL to DISPATCH_LEVEL and acquires the specified numbered queued spin lock.)

MI_SET_PFN_OWNER 宏定义如下:

LOCK_PFN_TIMESTAMP() 这个宏没查到是什么

再看看 UNLOCK_PFN

差不多就这意思了。。。

---------------------------------------------sudami.的分割线--------------------------------------------------

MmFlushImageSection函数的开头部分就是2个参数,主要关注第一个参数:

BOOLEAN
MmFlushImageSection (
    __in PSECTION_OBJECT_POINTERS SectionPointer,
    __in MMFLUSH_TYPE FlushType
    )

lkd> dt nt!_SECTION_OBJECT_POINTERS
   +0x000 DataSectionObject : Ptr32 Void
   +0x004 SharedCacheMap   : Ptr32 Void
   +0x008 ImageSectionObject : Ptr32 Void

MmFlushImageSection 就是判断2个指针是否为空 ImageSectionObjectDataSectionObject

lkd> dt nt!_CONTROL_AREA
   +0x000 Segment          : Ptr32 _SEGMENT
   +0x004 DereferenceList : _LIST_ENTRY
   +0x00c NumberOfSectionReferences : Uint4B
   +0x010 NumberOfPfnReferences : Uint4B
   +0x014 NumberOfMappedViews : Uint4B
   +0x018 NumberOfSubsections : Uint2B
   +0x01a FlushInProgressCount : Uint2B
   +0x01c NumberOfUserReferences : Uint4B
   +0x020 u                : __unnamed
   +0x024 FilePointer      : Ptr32 _FILE_OBJECT
   +0x028 WaitingForDeletion : Ptr32 _EVENT_COUNTER
   +0x02c ModifiedWriteCount : Uint2B
   +0x02e NumberOfSystemCacheViews : Uint2B

+0x020 u                : union __unnamed, 2 elements, 0x4 bytes
      +0x000 LongFlags        : Uint4B
      +0x000 Flags            : struct _MMSECTION_FLAGS, 31 elements, 0x4 bytes
         +0x000 BeingDeleted     : Bitfield Pos 0, 1 Bit
         +0x000 BeingCreated     : Bitfield Pos 1, 1 Bit
         +0x000 BeingPurged      : Bitfield Pos 2, 1 Bit
         +0x000 NoModifiedWriting : Bitfield Pos 3, 1 Bit
         +0x000 FailAllIo        : Bitfield Pos 4, 1 Bit

晕死,然后下面的源码看得太蒙胧了。。。

---------------------------------------------sudami.的分割线--------------------------------------------------


BOOLEAN
MmFlushImageSection (
    __in PSECTION_OBJECT_POINTERS SectionPointer,
    __in MMFLUSH_TYPE FlushType
    )

/*++

Routine Description:

    This function determines if any views of the specified image section
    are mapped, and if not, flushes valid pages (even modified ones)
    from the specified section and returns any used pages to the free
    list. This is accomplished by examining the prototype PTEs
    from the specified offset to the end of the section, and if
    any prototype PTEs are in the transition state, putting the
    prototype PTE back into its original state and putting the
    physical page on the free list.

Arguments:

    SectionPointer - Supplies a pointer to a section object pointers
                     within the FCB.

    FlushType - Supplies the type of flush to check for. One of
                MmFlushForDelete or MmFlushForWrite.

Return Value:

    Returns TRUE if either no section exists for the file object or
    the section is not mapped and the purge was done, FALSE otherwise.

--*/

{
    PLIST_ENTRY Next;
    PCONTROL_AREA ControlArea;
    PLARGE_CONTROL_AREA LargeControlArea;
    KIRQL OldIrql;
    LOGICAL state;

    if (FlushType == MmFlushForDelete) {

        //
        // Do a quick check to see if there are any mapped views for
        // the data section. If so, just return FALSE.
        //

        LOCK_PFN (OldIrql);
        ControlArea = (PCONTROL_AREA)(SectionPointer->DataSectionObject);
        if (ControlArea != NULL) {
            if ((ControlArea->NumberOfUserReferences != 0) ||
                (ControlArea->u.Flags.BeingCreated)) {
                UNLOCK_PFN (OldIrql);
                return FALSE;
            }
        }
        UNLOCK_PFN (OldIrql);
    }

    //
    // Check the status of the control area. If the control area is in use
    // or the control area is being deleted, this operation cannot continue.
    //

    state = MiCheckControlAreaStatus (CheckImageSection,
                                      SectionPointer,
                                      FALSE,
                                      &ControlArea,
                                      &OldIrql);

    if (ControlArea == NULL) {
        return (BOOLEAN) state;
    }

    //
    // PFN LOCK IS NOW HELD!
    //

    //
    // Repeat until there are no more control areas - multiple control areas
    // for the same image section occur to support user global DLLs - these DLLs
    // require data that is shared within a session but not across sessions.
    // Note this can only happen for Hydra.
    //

    do {

        //
        // Set the being deleted flag and up the number of mapped views
        // for the segment. Upping the number of mapped views prevents
        // the segment from being deleted and passed to the deletion thread
        // while we are forcing a delete.
        //

        ControlArea->u.Flags.BeingDeleted = 1;
        ControlArea->NumberOfMappedViews = 1;
        LargeControlArea = NULL;

        if (ControlArea->u.Flags.GlobalOnlyPerSession == 0) {
            NOTHING;
        }
        else if (IsListEmpty(&((PLARGE_CONTROL_AREA)ControlArea)->UserGlobalList)) {
            ASSERT (ControlArea ==
                    (PCONTROL_AREA)SectionPointer->ImageSectionObject);
        }
        else {

            //
            // Check if there's only one image section in this control area, so
            // we don't reference the section object pointers as the
            // MiCleanSection call may result in its deletion.
            //

            //
            // There are multiple control areas, bump the reference count
            // on one of them (doesn't matter which one) so that it can't
            // go away. This ensures the section object pointers will stick
            // around even after the calls below so we can safely reloop to
            // flush any other remaining control areas.
            //

            ASSERT (ControlArea->u.Flags.GlobalOnlyPerSession == 1);

            Next = ((PLARGE_CONTROL_AREA)ControlArea)->UserGlobalList.Flink;

            LargeControlArea = CONTAINING_RECORD (Next,
                                                  LARGE_CONTROL_AREA,
                                                  UserGlobalList);
       
            ASSERT (LargeControlArea->u.Flags.GlobalOnlyPerSession == 1);

            LargeControlArea->NumberOfSectionReferences += 1;
        }

        //
        // This is a page file backed or image segment. The segment is being
        // deleted, remove all references to the paging file and physical
        // memory.
        //

        UNLOCK_PFN (OldIrql);

        MiCleanSection (ControlArea, TRUE);

        //
        // Get the next Hydra control area.
        //

        if (LargeControlArea != NULL) {
            state = MiCheckControlAreaStatus (CheckImageSection,
                                              SectionPointer,
                                              FALSE,
                                              &ControlArea,
                                              &OldIrql);
            if (!ControlArea) {
                LOCK_PFN (OldIrql);
                LargeControlArea->NumberOfSectionReferences -= 1;
                MiCheckControlArea ((PCONTROL_AREA)LargeControlArea,
                                    OldIrql);
            }
            else {
                LargeControlArea->NumberOfSectionReferences -= 1;
                MiCheckControlArea ((PCONTROL_AREA)LargeControlArea,
                                    OldIrql);
                LOCK_PFN (OldIrql);
            }
        }
        else {
            state = TRUE;
            break;
        }

    } while (ControlArea);

    return (BOOLEAN) state;
}


类别:Note | 浏览() | 评论 (0)
 
最近读者:
 
网友评论:
本篇日志被作者设置为禁止发表新评论

     

©2009 Baidu