Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
3.9 KiB

  1. #define DOWNLEVEL
  2. /***
  3. *resetstk.c - Recover from Stack overflow.
  4. *
  5. * Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved.
  6. *
  7. *Purpose:
  8. * Defines the _resetstkoflw() function.
  9. *
  10. *Revision History:
  11. * 12-10-99 GB Module Created
  12. * 04-17-01 PML Enable for Win9x, return success code (vs7#239962)
  13. * 06-04-01 PML Do nothing if guard page not missing, don't shrink
  14. * committed space (vs7#264306)
  15. * 04-25-02 PML Don't set guard page below pMinGuard (vs7#530044)
  16. *
  17. *******************************************************************************/
  18. #include <stdlib.h>
  19. #include <malloc.h>
  20. #include <windows.h>
  21. #define MIN_STACK_REQ_WIN9X 17
  22. #define MIN_STACK_REQ_WINNT 2
  23. /***
  24. * void _resetstkoflw(void) - Recovers from Stack Overflow
  25. *
  26. * Purpose:
  27. * Sets the guard page to its position before the stack overflow.
  28. *
  29. * Exit:
  30. * Returns nonzero on success, zero on failure
  31. *
  32. *******************************************************************************/
  33. #ifdef DOWNLEVEL
  34. #define _resetstkoflw _resetstkoflw_downlevel
  35. #endif
  36. int __cdecl _resetstkoflw(void)
  37. {
  38. LPBYTE pStack, pGuard, pStackBase, pMaxGuard, pMinGuard;
  39. MEMORY_BASIC_INFORMATION mbi;
  40. SYSTEM_INFO si;
  41. DWORD PageSize;
  42. DWORD flNewProtect;
  43. DWORD flOldProtect;
  44. // Use _alloca() to get the current stack pointer
  45. pStack = _alloca(1);
  46. // Find the base of the stack.
  47. if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0)
  48. return 0;
  49. pStackBase = mbi.AllocationBase;
  50. // Find the page just below where the stack pointer currently points.
  51. // This is the highest potential guard page.
  52. GetSystemInfo(&si);
  53. PageSize = si.dwPageSize;
  54. pMaxGuard = (LPBYTE) (((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1))
  55. - PageSize);
  56. // If the potential guard page is too close to the start of the stack
  57. // region, abandon the reset effort for lack of space. Win9x has a
  58. // larger reserved stack requirement.
  59. pMinGuard = pStackBase + ((_osplatform == VER_PLATFORM_WIN32_WINDOWS)
  60. ? MIN_STACK_REQ_WIN9X
  61. : MIN_STACK_REQ_WINNT) * PageSize;
  62. if (pMaxGuard < pMinGuard)
  63. return 0;
  64. // On a non-Win9x system, do nothing if a guard page is already present,
  65. // else set up the guard page to the bottom of the committed range,
  66. // allowing for the reserved stack requirement.
  67. // For Win9x, just set guard page below the current stack page.
  68. if (_osplatform != VER_PLATFORM_WIN32_WINDOWS) {
  69. // Find first block of committed memory in the stack region
  70. pGuard = pStackBase;
  71. do {
  72. if (VirtualQuery(pGuard, &mbi, sizeof mbi) == 0)
  73. return 0;
  74. pGuard = pGuard + mbi.RegionSize;
  75. } while ((mbi.State & MEM_COMMIT) == 0);
  76. pGuard = mbi.BaseAddress;
  77. // If first committed block is already marked as a guard page,
  78. // there is nothing that needs to be done, so return success.
  79. if (mbi.Protect & PAGE_GUARD)
  80. return 1;
  81. // Fail if the first committed block is above the highest potential
  82. // guard page. Should never happen.
  83. if (pMaxGuard < pGuard)
  84. return 0;
  85. // Make sure to leave enough room so the next overflow will have
  86. // the proper reserved stack requirement available.
  87. if (pGuard < pMinGuard)
  88. pGuard = pMinGuard;
  89. VirtualAlloc(pGuard, PageSize, MEM_COMMIT, PAGE_READWRITE);
  90. }
  91. else {
  92. pGuard = pMaxGuard;
  93. }
  94. // Enable the new guard page.
  95. flNewProtect = _osplatform == VER_PLATFORM_WIN32_WINDOWS
  96. ? PAGE_NOACCESS
  97. : PAGE_READWRITE | PAGE_GUARD;
  98. return VirtualProtect(pGuard, PageSize, flNewProtect, &flOldProtect);
  99. }