天天看點

windows SEH機制注釋(2) 基于ReactOS

    在windows SEH機制注釋(1) 基于ReactOS 一文中,注釋了try/except宏,windows的SEH機制除了這對宏,還有try/finall宏,用來執行善後處理。相比try/except,try/finall簡單很多,沒有繞人的長跳轉,基本上屬于順序處理流程。如下:

1.
func()
{
     _SEH_TRY

     {

         //do sth

         _asm int 0x03;

     }

     _SEH_FINALLY(FINALLY_)

     {

         status = _SEH_GetExceptionCode();

     }

     _SEH_END

 }      

2.宏擴充

func()

 {

     for(;;) 

     { 

         _SEH_INIT_CONST int _SEHTopTryLevel = (_SEHScopeKind != 0); 

         _SEHPortableFrame_t * const _SEHCurPortableFrame = _SEHPortableFrame; 

         _SEHPortableTryLevel_t * const _SEHPrevPortableTryLevel = _SEHPortableTryLevel; 

      

         { 

             _SEH_INIT_CONST int _SEHScopeKind = 0; 

             register int _SEHState = 0; 

             register int _SEHHandle = 0; 

             _SEHFrame_t _SEHFrame; 

             _SEHTryLevel_t _SEHTryLevel; 

             _SEHPortableFrame_t * const _SEHPortableFrame = 

                 _SEHTopTryLevel ? &_SEHFrame.SEH_Header : _SEHCurPortableFrame; 

             _SEHPortableTryLevel_t * const _SEHPortableTryLevel = &_SEHTryLevel.ST_Header; 

     

             (void)_SEHScopeKind; 

             (void)_SEHPortableFrame; 

             (void)_SEHPortableTryLevel; 

             (void)_SEHHandle; 

     

             for(;;) 

             { 

                 if(_SEHState)

                 /*

                 初始時_SEHState為0,進入SEH_FINALL!else分支,設定SEH處理結構__SEHTryLevel

                 */ 

                 { 

                     for(;;) 

                     { 

                         {

                     <-try/

                         {

                                 //(1)

                            //do sth,如果發生異常,沒有跳轉,确切的說是由系統在fs:[0]中查找上一層堆棧中提供的處理函數
                           //如果沒有發生異常,順序的執行到(2)處,執行善後處理
                             _asm int 0x03;

                         }

                       finall ->/

                        } 

     

                         break; 

                     } 

     

                     _SEHPortableFrame->SPF_TopTryLevel = _SEHPrevPortableTryLevel; 

                     break; 

                 } 

                 else 

                 { 

                     _SEHTryLevel.ST_Header.SPT_Handlers.SH_Filter = 0; 

                     /*

                     FINALLY_由_SEH_FINALLY(FINALLY_)傳入,設定收尾函數

                     */

                     _SEHTryLevel.ST_Header.SPT_Handlers.SH_Finally = (FINALLY_); 

     

                     _SEHTryLevel.ST_Header.SPT_Next = _SEHPrevPortableTryLevel; 

                     _SEHFrame.SEH_Header.SPF_TopTryLevel = &_SEHTryLevel.ST_Header; 

     

                     if(_SEHTopTryLevel) 

                     { 

                         if(&_SEHLocals != _SEHDummyLocals) 

                             _SEHFrame.SEH_Locals = &_SEHLocals; 

     

                         _SEH_EnableTracing(_SEH_DO_DEFAULT_TRACING); 

                         _SEHFrame.SEH_Header.SPF_Handler = _SEHCompilerSpecificHandler; 

                         _SEHEnterFrame(&_SEHFrame.SEH_Header); 

                     } 

                     /*

                     經過++ _SEHState; 

                     continue;

                     程式進入if(_SEHState),執行受保護的代碼(其實不算受保護的代碼,與

                     SEH_Except相比少了長跳轉)

                     */

                     ++ _SEHState; 

                     continue; 

                 } 

                 //(2)

                 break; 

             } 

             // _SEH_FINALLY(FINALLY_)

             /*

             執行這個回調有2種可能

             1.執行完(1)後,一路break出來,執行善後函數或者

             2.執行(1)時遇到異常,進入異常處理過程。期間執行unwind時會調用

             (SEHTryLevel.ST_Header.SPT_Handlers.SH_Finally)(&_SEHFrame.SEH_Header);

             */

             (FINALLY_)(&_SEHFrame.SEH_Header); 

     

             if(0) 

             {

     //

                         {

                             status = _SEH_GetExceptionCode();

                         }

         //

         } 

         } 

     

         if(_SEHTopTryLevel) 

             _SEHLeaveFrame(); 

     

         break; 

     }

 }      

繼續閱讀