www.pudn.com > 代理服务器原代码.rar > resetstk.cpp


/*** 
*resetstk.c - Recover from Stack overflow. 
* 
*       Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved. 
* 
*Purpose: 
*       Defines the _resetstkoflw() function. 
* 
*******************************************************************************/ 
 
#if defined(_MSC_VER) & _MSC_VER < 1300 
#include  
#include  
#include  
 
#define MIN_STACK_REQ_WIN9X 0x11000 
#define MIN_STACK_REQ_WINNT 0x2000 
 
#ifdef _WIN64 
typedef unsigned __int64 REGEX_DWORD_PTR; 
#else 
typedef unsigned __int32 REGEX_DWORD_PTR; 
#endif 
 
struct osplatform_getter 
{ 
    int m_osplatform; 
 
    osplatform_getter() : m_osplatform( 0 ) 
    { 
        OSVERSIONINFOA osvi; 
        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); 
        if( GetVersionExA( & osvi ) ) 
            m_osplatform = osvi.dwPlatformId; 
    } 
}; 
 
inline int get_osplatform() 
{ 
    static osplatform_getter const s_osplatform_getter; 
    return s_osplatform_getter.m_osplatform; 
}; 
 
/*** 
* void _resetstkoflw(void) - Recovers from Stack Overflow 
* 
* Purpose: 
*       Sets the guard page to its position before the stack overflow. 
* 
* Exit: 
*       Returns nonzero on success, zero on failure 
* 
*******************************************************************************/ 
 
extern "C" int __cdecl _resetstkoflw(void) 
{ 
    LPBYTE pStack, pGuard, pStackBase, pMinGuard; 
    MEMORY_BASIC_INFORMATION mbi; 
    SYSTEM_INFO si; 
    DWORD PageSize; 
    DWORD flNewProtect; 
    DWORD flOldProtect; 
 
    // Use _alloca() to get the current stack pointer 
 
    pStack = static_cast( _alloca(1) ); 
 
    // Find the base of the stack. 
 
    if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0) 
        return 0; 
    pStackBase = static_cast( mbi.AllocationBase ); 
 
    // Find the page just below where the stack pointer currently points. 
    // This is the new guard page. 
 
    GetSystemInfo(&si); 
    PageSize = si.dwPageSize; 
 
    pGuard = (LPBYTE) (((REGEX_DWORD_PTR)pStack & ~(REGEX_DWORD_PTR)(PageSize - 1)) 
                       - PageSize); 
 
    // If the potential guard page is too close to the start of the stack 
    // region, abandon the reset effort for lack of space.  Win9x has a 
    // larger reserved stack requirement. 
 
    pMinGuard = pStackBase + ((get_osplatform() == VER_PLATFORM_WIN32_WINDOWS) 
                              ? MIN_STACK_REQ_WIN9X 
                              : MIN_STACK_REQ_WINNT); 
 
    if (pGuard < pMinGuard) 
        return 0; 
 
    // On a non-Win9x system, release the stack region below the new guard 
    // page.  This can't be done for Win9x because of OS limitations. 
 
    if (get_osplatform() != VER_PLATFORM_WIN32_WINDOWS) { 
        if (pGuard > pStackBase) 
            VirtualFree(pStackBase, pGuard - pStackBase, MEM_DECOMMIT); 
 
        VirtualAlloc(pGuard, PageSize, MEM_COMMIT, PAGE_READWRITE); 
    } 
 
    // Enable the new guard page. 
 
    flNewProtect = get_osplatform() == VER_PLATFORM_WIN32_WINDOWS 
                   ? PAGE_NOACCESS 
                   : PAGE_READWRITE | PAGE_GUARD; 
 
    return VirtualProtect(pGuard, PageSize, flNewProtect, &flOldProtect); 
} 
 
#endif