Source code of Windows XP (NT5)
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.

173 lines
4.7 KiB

  1. /***
  2. *ehvecdtr.cxx - EH-aware version of destructor iterator helper function
  3. *
  4. * Copyright (c) 1990-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * These functions are called when constructing and destructing arrays of
  8. * objects. Their purpose is to assure that constructed elements get
  9. * destructed if the constructor for one of the elements throws.
  10. *
  11. * Must be compiled using "-d1Binl" to be able to specify __thiscall
  12. * at the user level
  13. *
  14. *Revision History:
  15. * 10-11-93 JDR Module created
  16. * 05-09-94 BES Module adapted for CRT source conventions
  17. * 05-13-94 SKS Remove _CRTIMP modifier
  18. * 10-10-94 CFW Fix EH/SEH exception handling.
  19. * 10-17-94 BWT Disable code for PPC.
  20. * 11-09-94 CFW Back out 10-10-94 change.
  21. * 02-08-95 JWM Mac merge.
  22. * 04-14-95 JWM Re-fix EH/SEH exception handling.
  23. * 04-17-95 JWM Restore non-WIN32 behavior.
  24. * 04-27-95 JWM EH_ABORT_FRAME_UNWIND_PART now #ifdef ALLOW_UNWIND_ABORT.
  25. * 05-17-99 PML Remove all Macintosh support.
  26. * 05-20-99 PML Turn off __thiscall for IA64.
  27. * 07-12-99 RDL Image relative fixes under CC_P7_SOFT25.
  28. * 03-15-00 PML Remove CC_P7_SOFT25, which is now on permanently.
  29. *
  30. ****/
  31. #ifdef _WIN32
  32. #if defined(_NTSUBSET_)
  33. extern "C" {
  34. #include <nt.h>
  35. #include <ntrtl.h>
  36. #include <nturtl.h>
  37. #include <ntstatus.h> // STATUS_UNHANDLED_EXCEPTION
  38. #include <ntos.h>
  39. #include <ex.h> // ExRaiseException
  40. }
  41. #endif
  42. #endif
  43. #include <cruntime.h>
  44. #include <ehdata.h>
  45. #include <eh.h>
  46. #if defined (_M_IX86)
  47. #define CALLTYPE __thiscall
  48. #else
  49. #define CALLTYPE __stdcall
  50. #endif
  51. #ifdef _WIN32
  52. void __stdcall __ArrayUnwind(
  53. void* ptr, // Pointer to array to destruct
  54. size_t size, // Size of each element (including padding)
  55. int count, // Number of elements in the array
  56. void(CALLTYPE *pDtor)(void*) // The destructor to call
  57. );
  58. void __stdcall __ehvec_dtor(
  59. void* ptr, // Pointer to array to destruct
  60. size_t size, // Size of each element (including padding)
  61. int count, // Number of elements in the array
  62. void(CALLTYPE *pDtor)(void*) // The destructor to call
  63. ){
  64. int success = 0;
  65. // Advance pointer past end of array
  66. ptr = (char*)ptr + size*count;
  67. __try
  68. {
  69. // Destruct elements
  70. while ( --count >= 0 )
  71. {
  72. ptr = (char*)ptr - size;
  73. (*pDtor)(ptr);
  74. }
  75. success = 1;
  76. }
  77. __finally
  78. {
  79. if (!success)
  80. __ArrayUnwind(ptr, size, count, pDtor);
  81. }
  82. }
  83. static int ArrayUnwindFilter(EXCEPTION_POINTERS* pExPtrs)
  84. {
  85. EHExceptionRecord *pExcept = (EHExceptionRecord*)pExPtrs->ExceptionRecord;
  86. switch(PER_CODE(pExcept))
  87. {
  88. case EH_EXCEPTION_NUMBER:
  89. terminate();
  90. #ifdef ALLOW_UNWIND_ABORT
  91. case EH_ABORT_FRAME_UNWIND_PART:
  92. return EXCEPTION_EXECUTE_HANDLER;
  93. #endif
  94. default:
  95. return EXCEPTION_CONTINUE_SEARCH;
  96. }
  97. }
  98. void __stdcall __ArrayUnwind(
  99. void* ptr, // Pointer to array to destruct
  100. size_t size, // Size of each element (including padding)
  101. int count, // Number of elements in the array
  102. void(CALLTYPE *pDtor)(void*) // The destructor to call
  103. ){
  104. // 'unwind' rest of array
  105. __try
  106. {
  107. while ( --count >= 0 )
  108. {
  109. ptr = (char*) ptr - size;
  110. (*pDtor)(ptr);
  111. }
  112. }
  113. __except( ArrayUnwindFilter(exception_info()) )
  114. {
  115. }
  116. }
  117. #else
  118. void __stdcall __ehvec_dtor(
  119. void* ptr, // Pointer to array to destruct
  120. unsigned size, // Size of each element (including padding)
  121. int count, // Number of elements in the array
  122. void(CALLTYPE *pDtor)(void*) // The destructor to call
  123. ){
  124. // Advance pointer past end of array
  125. ptr = (char*)ptr + size*count;
  126. try
  127. {
  128. // Destruct elements
  129. while ( --count >= 0 )
  130. {
  131. ptr = (char*)ptr - size;
  132. (*pDtor)(ptr);
  133. }
  134. }
  135. catch(...)
  136. {
  137. // If a destructor throws an exception, unwind the rest of this
  138. // array
  139. while ( --count >= 0 )
  140. {
  141. ptr = (char*) ptr - size;
  142. try {
  143. (*pDtor)(ptr);
  144. }
  145. catch(...) {
  146. // If any destructor throws during unwind, terminate
  147. terminate();
  148. }
  149. }
  150. // After array is unwound, rethrow the exception so a user's handler
  151. // can handle it.
  152. throw;
  153. }
  154. }
  155. #endif