2 *resetstk.c - Recover from Stack overflow.
4 * Copyright (c) Microsoft Corporation. All rights reserved.
7 * Defines the _resetstkoflw() function.
9 *******************************************************************************/
15 #define MIN_STACK_REQ_WIN9X 17
16 #define MIN_STACK_REQ_WINNT 2
18 #define _osplatform VER_PLATFORM_WIN32_NT
21 * void _resetstkoflw() - Recovers from Stack Overflow
24 * Sets the guard page to its position before the stack overflow.
27 * Returns nonzero on success, zero on failure
29 *******************************************************************************/
33 LPBYTE pStack
, pGuard
, pStackBase
, pMaxGuard
, pMinGuard
;
34 MEMORY_BASIC_INFORMATION mbi
;
40 // Use _alloca() to get the current stack pointer
44 // Find the base of the stack.
46 if (VirtualQuery(pStack
, &mbi
, sizeof mbi
) == 0)
48 pStackBase
= mbi
.AllocationBase
;
50 // Find the page just below where the stack pointer currently points.
51 // This is the highest potential guard page.
54 PageSize
= si
.dwPageSize
;
56 pMaxGuard
= (LPBYTE
) (((DWORD_PTR
)pStack
& ~(DWORD_PTR
)(PageSize
- 1))
59 // If the potential guard page is too close to the start of the stack
60 // region, abandon the reset effort for lack of space. Win9x has a
61 // larger reserved stack requirement.
63 pMinGuard
= pStackBase
+ ((_osplatform
== VER_PLATFORM_WIN32_WINDOWS
)
65 : MIN_STACK_REQ_WINNT
) * PageSize
;
67 if (pMaxGuard
< pMinGuard
)
70 // On a non-Win9x system, do nothing if a guard page is already present,
71 // else set up the guard page to the bottom of the committed range,
72 // allowing for the reserved stack requirement.
73 // For Win9x, just set guard page below the current stack page.
75 if (_osplatform
!= VER_PLATFORM_WIN32_WINDOWS
) {
77 // Find first block of committed memory in the stack region
81 if (VirtualQuery(pGuard
, &mbi
, sizeof mbi
) == 0)
83 pGuard
= pGuard
+ mbi
.RegionSize
;
84 } while ((mbi
.State
& MEM_COMMIT
) == 0);
85 pGuard
= mbi
.BaseAddress
;
87 // If first committed block is already marked as a guard page,
88 // there is nothing that needs to be done, so return success.
90 if (mbi
.Protect
& PAGE_GUARD
)
93 // Fail if the first committed block is above the highest potential
94 // guard page. Should never happen.
96 if (pMaxGuard
< pGuard
)
99 // Make sure to leave enough room so the next overflow will have
100 // the proper reserved stack requirement available.
102 if (pGuard
< pMinGuard
)
105 VirtualAlloc(pGuard
, PageSize
, MEM_COMMIT
, PAGE_READWRITE
);
111 // Enable the new guard page.
113 flNewProtect
= _osplatform
== VER_PLATFORM_WIN32_WINDOWS
115 : PAGE_READWRITE
| PAGE_GUARD
;
117 return VirtualProtect(pGuard
, PageSize
, flNewProtect
, &flOldProtect
);