Skip to content

3) ntdll!RtlGetProcessHeaps()

Hume(冷雨飘心)果然对SEH了解深入,以前我一直没有关注过__finally块,直到看见 Hume所给的RtlGetProcessHeaps()伪代码,奇怪Hume凭什么认为这里是__finally块, 而不是__except块,仔细研究了一番,佩服Hume!

原C风格的伪代码基本正确,但在表述__finally块范围时有误,另一处是返回值表述 有误,我修正如下,算是狗尾续貂:


/ * Create: Hume 2003-11-07 17:29 * Modify: scz 2003-11-10 13:51 * 2003-12-01 11:09 * * ntdll.dll中定义的全局变量 / extern unsigned char RtlpDebugPageHeap; extern RTL_CRITICAL_SECTION RtlpProcessHeapsListLock;

DWORD __stdcall RtlGetProcessHeaps ( DWORD NumberOfHeaps, // maximum number of heap handles PHANDLE ProcessHeaps // buffer for heap handles ) { DWORD PebNumberOfHeaps; DWORD LocalNumberOfHeaps; PTEB Teb = NtCurrentTeb(); DWORD ret;

RtlEnterCriticalSection( &RtlpProcessHeapsListLock );
__try
{
    PebNumberOfHeaps    = Teb->Peb->NumberOfHeaps;
    if ( Teb->Peb->NumberOfHeaps > NumberOfHeaps )
    {
        LocalNumberOfHeaps  = NumberOfHeaps;
    }
    else
    {
        LocalNumberOfHeaps  = Teb->Peb->NumberOfHeaps;
    }
    /*
     * 这条语句可能引发异常,需要SEH机制的保护
     */
    CopyMemory
    (
        ProcessHeaps,
        Teb->Peb->ProcessHeaps,
        LocalNumberOfHeaps * sizeof( HANDLE )
    );
    /*
     * 修正形参,为处理调试堆做准备
     */
    ProcessHeaps       += LocalNumberOfHeaps * sizeof( HANDLE );
    NumberOfHeaps      -= LocalNumberOfHeaps;
}
__finally
{
    ret                 = PebNumberOfHeaps;
    RtlLeaveCriticalSection( &RtlpProcessHeapsListLock );
}
/*
 * 注意,后续代码不受本函数中的SEH机制保护,并且已经离开临界区。
 * RtlpDebugPageHeapGetProcessHeaps()有自己的SEH机制提供保护。
 */
if ( RtlpDebugPageHeap )
{
    ret += RtlpDebugPageHeapGetProcessHeaps
           (
               NumberOfHeaps,
               ProcessHeaps
           );
}
/*
 * The return value is the number of heap handles that are valid for
 * the calling process.
 *
 * 注意,这个返回值不是当前获取的堆句柄数,而是整个进程中有效堆句柄数。
 */
return( ret );

} / end of RtlGetProcessHeaps /