精华内容
下载资源
问答
  • out of the office 离任;下班 表示人在公司上班,但是本人现在不在公司里面,可能出去有事了 out of office 去职 表示人不在公司上班了,可能被炒了,或者退休了等 常用邮件模板 Dear all,Thanks ...
    • out of the office

      离任;下班

      表示人在公司上班,但是本人现在不在公司里面,可能出去有事了

    • out of office

      去职

      表示人不在公司上班了,可能被炒了,或者退休了等

    常用邮件模板

    Dear all, Thanks for your email, I'm ooo from (Date ) with limited access to email, please find my back up (email)for help. Thanks and Best regards

    Hi Senders, Thanks for your email, i am out of office on(Date ). My backup is (email). If urgent, please call me via phone (Your Cell Phone Number)

    OOO就是Out Of Office的缩写,不要以为缩写了,我就不认识你了。那么让我们看一下我们邮件中OOO时都有哪些表达方式。

    1. Thank you for your email. I'm out of the office and will be back at (Date of Return).During this period I will have LIMITED access to my email. For imediate assistance please contact me on my cell phone at (Your Cell Phone Number).

    2. I will be out of the office from (Starting date) until (End Date). If you need immediate assistance please contact (Contact person).

    3. I will be out of the office starting (Starting Date) through (End Date) returning (Date of Return). If you need immediate assistance during my absence, please contact ( Contacts Name) at (Contacts Email Address). Otherwise I will respond to your emails as soon as possible upon my return.

    4. Thank you for your message. I am currently out of the office, with no email access. I will be returning on ( Date of Return). If you need immediate assistance before then, you may reach me at my mobile- (Your Mobile Number).

    1. I will be out of the office this week. If you need immediate assistance while I'm away, Please email (Contacts Email Address)

    2. I will be away from (Date) until (Return Date). For urgent matters, you can contat (Contact Person)

    3. Thank you for your email. Your message is important to ( Us/Me) and (I/We) will respond as soon as possible. Thank You!

     以下文章可以看看:

    When Professor Randy Pausch took a month off work for his honeymoon, his boss at Carnegie Mellon University insisted that he be reachable. So he recorded a message for when people tried to call. On it he explained that he’d waited until 39 to get married. Then he gave the names of his new in-laws and the town they lived in, so a caller could get their number from directory assistance. Then, lastly: “If you can convince my in-laws that your emergency merits interrupting their only daughter’s honeymoon, they have our number.”

    当兰迪波许(Randy Pausch)教授为了度蜜月而休假一个月时,他在卡内基梅隆大学(Carnegie Mellon University)的老板坚持要能联系上他。因此,他为打电话找他的人录了一段语音留言。在留言中,他解释说,自己一直等到39岁才结婚。然后,他说出了自己岳父母的名字及他们居住的小镇,这样来电者可以从查号服务台查到他们的电话号码。最后他说:“如果你能说服我岳父母,你的紧急情况值得打断他们的独女的蜜月,他们有我们的电话。”

    I was thinking about this clever out-of-office notification as I tried to construct my own in email form. Prof Pausch’s honeymoon message is a story from a more technologically innocent age — it was about 15 years ago, which is at least 100 in internet years. Back then, aside from the hurdles put in place by determined honeymooners, there were also plausible reasons to be out of touch. Now, technology is so good that it’s ruined our favourite excuses for not being reachable. Writing that one has “limited” or “intermittent” access to email is usually no more than a declaration that one intends to be choosy about dealing with it.

    当我试图构思我自己的“不在办公室”自动回复电子邮件时,我脑子里在想的就是这个聪明的“不在办公室”通知。波许教授的蜜月留言是科技还不那么发达时代的故事——发生在大约15年前,如果用互联网年计算,至少相当于100年前。那时候,除了决心度蜜月的新婚夫妇设置的障碍,也有其他貌似合理的理由失去联系。如今,科技如此发达,以至于已经毁掉了我们在希望不被打扰时最喜欢使用的借口。写下自己只能“有限地”或“间歇地”访问电子邮箱,通常无异于宣布你打算有选择性地处理电子邮件。

    But this is only half the story. The other is that technology, particularly when it comes to the out-of-office message, hasn’t kept up. There’s a robot that walks like a dog and cars drive themselves, so why don’t we have smarter ways to manage time spent away from work?

    但这只是故事的一面。故事的另一面是科技(尤其是当涉及到“不在办公室”的留言时)没能跟上时代。我们拥有可以像狗一样行走的机器人,有可以自动驾驶的汽车,但为什么我们没有更智能的方法来管理休假的时间呢?

    An obvious improvement would be to add functionality to email clients that spreadsheet software has had for years: warnings that self-referential loops, aka “circular references”, have been created. This affliction hits parts of Europe especially hard in August. Person A is out of the office, please contact Person B if it’s urgent. Person B says the same, refers emailer to Person C in an emergency. Person C refers to Person A. It is either a clever ruse or poor planning, but given that everyone is already emotionally and mentally, if not physically, out of the door when they set this up, it’s probably the latter.

    一个明显的改善可能是在电子邮件客户端添加电子表格软件多年前就具备的功能:已经产生自动指向循环(也叫“环状指向”)的警告。这一“克星”在8月的欧洲部分地区尤其折磨人。甲称自己不在办公室,如果情况紧急的话,请联系乙。乙重复甲的话,让发信人在紧急情况下去找丙。丙又将紧急联系人设为甲。这种情形如果不是一种聪明的策略,就是计划不周,但是考虑到在这种循环被设立时,每个人早已在心理上和头脑上(如果不是实际上)离开了办公室,很可能是后一种。

    From this it logically follows that any new out-of-office technology would have to respect the fact that having high quality time off is a team effort. So one of the top features for development should be a warning that pops up when you’re about to email someone from whom you’ve already received an out-of-office. The system will be smart enough to consider the dates that the holiday-maker said they were away in their email. This isn’t my idea. It’s covered by a US patent filed (grant pending) in 2006 that’s owned by IBM.

    由此可合理推断出,任何新的“不在办公室”技术都必须尊重这样的事实:享受高质量的休假时间要靠团队努力。因此,开发的首要功能之一应该是,当你要给一个你已经收到“不在办公室”回复的人发邮件时,系统会自动弹出警告。这一系统将足够智能,能够记住度假者在邮件中说过的休假日期。这不是我的主意。一项2006年申请的美国专利(等待许可)就包含此项功能,这项专利归IBM所有。

    I’d like it to go one further by having it hook up with an email scheduling service, giving you the option to forward the conversation to the well-slept sod on the day of their return in order to make absolutely clear that yes, they were right to wish that they could have just stayed in the Lake District forever.

    我想更进一步,让这一功能与电子邮件日程安排服务相连接,让你可以选择可以将邮件推迟至那个正在享受充足睡眠的讨厌鬼回来上班的那天发送,以清楚地表明,是的,他们本想永远待在湖区(Lake District)不回来的想法是正确的。

    Provided colleagues heeded the warnings, such functionality would be a boon to those of us who have poor self-control when it comes to unplugging from the Matrix. It would also, however, provide the added bonus of making it abundantly clear who the most and least helpful people are when we are attempting down time.

    如果你的同事听从了这些警告,这样的功能对于那些难以从旅行中收心、自制力较差的人将是一个福音。然而,它还将提供额外的好处:让你充分认清在你想要休息时,谁是最帮忙的,谁是最添乱的。

    Perhaps in the year after the release of a new add-in to Gmail or Outlook that provides this tool, the survey for the 100 Best Companies to Work For could include a Jerk Index measuring the number of out-of-office notices heeded versus overridden.

    也许在提供这种工具的Gmail或Outlook新插件发布之后,对100家最佳雇主(Best Companies to Work For)的调查可能包括一项“傻瓜指数”(Jerk Index)——测算 “不在办公室通知”被听从的与被无视的数量之比。

    The next new feature would generate a public plausibility score for a given out-of-office message. If the message says “intermittent access” but the person is replying to messages at a rate that implies that they want an excuse not to spend time with their family, their plausibility score would be near zero.

    下一个新功能将对某人的“不在办公室”留言打出一个公开的可信度评分。如果留言说可“间歇访问”邮箱,但此人回复信息的速度暗示他们想找个不跟家人待在一块儿的理由,他们的可信度评分将接近于零。

    If the message says “no access” and the person replies to anything, this system will send them an image of US talk-show host Maury Povich along with the text: “Your out-of-office said that you wouldn’t be replying to emails. The fact that you replied determined that was a lie.”

    如果留言说“无法访问”邮箱,而此人又回复所有邮件,该系统将给他们发送一张美国脱口秀主持人莫里波维奇(Maury Povich)的照片,并附上文字:“你的‘不在办公室’留言说你不会回复邮件。而你回复了,说明那是一个谎言。”

    As for my own message, I decided on something non-committal. Until technology catches up, I might as well keep my options open. Oh, and I left Person B out of it. He’s not in anyway.

    至于我自己的“不在办公室”留言,我决定含糊其辞。在科技手段还不足的时候,我还是保留自己的选择权吧。噢,我也没有设置乙为紧急联系人。反正他也休假了。

     

    展开全文
  • <p>Message boxes should appear on top of the existing progress dialog <h2>Actual Behavior <p>Message boxes appear behind the existing progress dialog <p><img alt="image" src=...
  • At its heart, Win32 structured exception handling is an operating system-provided service. All the docs you're likely to find about SEH describe one particular com-piler's runtime library wrapping aro
    At its heart, Win32 structured exception handling is an operating system-provided service. All the docs you're likely to find about SEH describe one particular com-piler's runtime library wrapping around the operating system implementation. I'll strip SEH to its most fundamental concepts.

    Matt Pietrek

    This article assumes you're familiar with C++, Win32
    Code for this article: Exception.exe (33KB)
    Matt Pietrek is the author of Windows 95 System Programming Secrets (IDG Books, 1995). He works at NuMega Technologies Inc., and can be reached atmpietrek@tiac.com.

    Of all the facilities provided by Win32®operating systems, perhaps the most widely used but underdocumented is structured exception handling (SEH). When you think of Win32 structured exception handling, you probably think of terms like _try, _finally, and _except. You can find good descriptions of SEH in just about any competent Win32 book (even the remedial ones). Even the Win32 SDK has a fairly complete overview of using structured exception handling with _try, _finally, and _except.
    With all this documentation, where do I get off saying that SEH is underdocumented? At its heart, Win32 structured exception handling is an operating system-provided service. All the documentation you're likely to find about SEH describes one particular compiler's runtime library wrapping around the operating system implementation. There's nothing magical about the keywords _try, _finally, or _except. Microsoft's OS and compiler groups defined these keywords and what they do. Other C++ compiler vendors have simply gone along with their semantics. While the compiler SEH layer tames the nastiness of raw operating system SEH, it's had the effect of keeping the raw operating system SEH details from public view.
    I've received numerous email messages from people who have needed to implement compiler-level SEH and couldn't find much in the way of documentation for the operating system facilities. In a rational world, I'd be able to point to the runtime library sources for Visual C++ or Borland C++ and be done with it. Alas, for some unknown reason, compiler-level SEH seems to be a big secret. Neither Microsoft nor Borland provide the source code for the innermost layer of their SEH support.
    In this article, I'll strip structured exception handling down to its most fundamental concepts. In doing so, I'll separate what the OS provides from what compilers provide via code generation and runtime library support. When I dive into the code for key operating system routines, I'll use the Intel version of Windows NT
    ® 4.0 as my base. Most of what I'll describe is equally applicable on other processors, however.
    I'm going to avoid the issue of true C++ exception handling, which uses catch() instead of _except. Under the hood, true C++ exception handling is implemented very similarly to what I'll describe here. However, true C++ exception handling has some additional complexities that would just cloud the concepts I want to cover.
    In digging through obscure .H and .INC files to piece together what constitutes Win32 SEH, one of the best sources of information turned out to be the IBM OS/2 header files (particularly BSEXCPT.H). This shouldn't be too surprising if you've been in this business for a while. The SEH mechanisms described here were defined back when Microsoft was still working on OS/2. For this reason, you'll find SEH under Win32 and OS/2 to be remarkably similar.

    SEH in the Buff

    Since the details of SEH can be overwhelming if taken all at once, I'll start out small and work my way up through the layers. If you've never worked with structured exception handling before, you're in good shape; you have no preconceived notions. If you've used SEH before, try to clear your head of words like _try, GetExceptionCode, and EXCEPTION_EXECUTE_HANDLER. Pretend that this is all new to you. Take a deep breath. Are you ready? Good.
    Imagine I told you that when a thread faults, the operating system gives you an opportunity to be informed of the fault. More specifically, when a thread faults, the operating system calls a user-defined callback function. This callback function can do pretty much whatever it wants. For instance, it might fix whatever caused the fault, or it might play a Beavis and Butt-head .WAV file. Regardless of what the callback function does, its last act is to return a value that tells the system what to do next. (This isn't strictly true, but it's close enough for now.)
    Given that the system calls you back when your code makes a mess, what should the callback function look like? In other words, what sort of information would you want to know about the exception? It really doesn't matter because Win32 has made up your mind for you. An exception callback function looks like this:

     EXCEPTION_DISPOSITION
     __cdecl _except_handler(
         struct _EXCEPTION_RECORD *ExceptionRecord,
         void * EstablisherFrame,
         struct _CONTEXT *ContextRecord,
         void * DispatcherContext
         );
    
    This prototype, which comes from the standard Win32 header file EXCPT.H, looks a little overwhelming at first. If you take it slowly, it's really not so bad. For starters, ignore the return type (EXCEPTION_DISPOSITION). What you basically have is a function called _except_handler that takes four parameters.
    The first parameter to an _except_handler callback is a pointer to an EXCEPTION_RECORD. This structure is defined in WINNT.H, shown below:
    
     typedef struct _EXCEPTION_RECORD {
     DWORD ExceptionCode;
     DWORD ExceptionFlags;
     struct _EXCEPTION_RECORD *ExceptionRecord;
     PVOID ExceptionAddress;
     DWORD NumberParameters;
     DWORD ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
     }  EXCEPTION_RECORD;
    
    The ExceptionCode parameter is the number that the operating system assigned to the exception. You can see a list of various exception codes in WINNT.H by searching for #defines that start with "STATUS_". For example, the code for the all-too-familiar STATUS_ACCESS_VIOLATION is 0xC0000005. A more complete set of exception codes can be found in NTSTATUS.H from the Windows NT DDK. The fourth element in the EXCEPTION_RECORD structure is the address where the exception occurred. The remaining EXCEPTION_RECORD fields can be ignored for the moment.
    The second parameter to the _except_handler function is a pointer to an establisher frame structure. This is a vital parameter in SEH, but for now you can ignore it. 
    The third parameter to the _except_handler callback is a pointer to a CONTEXT structure. The CONTEXT structure is defined in WINNT.H and represents the register values of a particular thread. Figure 1 shows the fields of a CONTEXT structure. When used for SEH, the CONTEXT structure represents the register values at the time of the exception. Incidentally, this CONTEXT structure is the same structure used with the GetThreadContext and SetThreadContext APIs.
    The fourth and final parameter to the _except_handler callback is called the DispatcherContext. It also can be ignored for the moment. 
    To briefly recap thus far, you have a callback function that's called when an exception occurs. The callback takes four parameters, three of which are pointers to structures. Within these structures, some fields are important, others not so important. The key point is that the _except_handler callback function receives a wealth of information, such as what type of exception occurred and where it occurred. Using this information, the exception callback needs to decide what to do.
    While it's tempting for me to throw together a quickie sample program that shows the _except_handler callback in action, there's still something missing. In particular, how does the operating system know where to call when a fault occurs? The answer is yet another structure called an EXCEPTION_REGISTRATION. You'll see this structure throughout this article, so don't skim past this part. The only place I could find a formal definition of an EXCEPTION_REGISTRATION was in the EXSUP.INC file from the Visual C++ runtime library sources:
    _EXCEPTION_REGISTRATION struc
         prev    dd      ?
         handler dd      ?
     _EXCEPTION_REGISTRATION ends
    
    You'll also see this structure referred to as an _EXCEPTION_REGISTRATION_RECORD in the definition of the NT_TIB structure from WINNT.H. Alas, nowhere is an _EXCEPTION_REGISTRATION_RECORD defined, so all I have to work from is the assembly language struc definition in EXSUP.INC. This is just one example of what I meant earlier when I said that SEH was underdocumented.
    In any event, let's return to the question at hand. How does the OS know where to call when an exception occurs? The EXCEPTION_REGISTRATION structure consists of two fields, the first of which you can ignore for now. The second field, handler, contains a pointer to an _except_ handler callback function. This gets you a little closer, but now the question becomes, where does the OS look to find the EXCEPTION_REGISTRATION structure?
    To answer this question, it's helpful to remember that structured exception handling works on a per-thread basis. That is, each thread has its own exception handler callback function. In my May 1996 column, I described a key Win32 data structure, the thread information block (aka the TEB or TIB). Certain fields of this data structure are the same between Windows NT, Windows
    ® 95, Win32s, and OS/2. The first DWORD in a TIB is a pointer to the thread's EXCEPTION_REGISTRATION structure. On the Intel Win32 platform, the FS register always points to the current TIB. Thus, at FS:[0] you can find a pointer to an EXCEPTION_REGISTRATION structure.
    Now I'm getting somewhere! When an exception occurs, the system looks at the TIB of the faulting thread and retrieves a pointer to an EXCEPTION_REGISTRATION structure. In this structure is a pointer to an _except_handler callback function. The operating system now knows enough to call the _except_handler function, as shown in Figure 2.
    Figure 2 _except_handler_function
    Figure 2 _except_handler_function

    With the minimal pieces finally put together, I wrote a small program to demonstrate this very simple description of OS-level structured exception handling.Figure 3 shows MYSEH.CPP, which has only two functions. Function main uses three inline ASM blocks. The first block builds an EXCEPTION_REGISTRATION structure on the stack via two PUSH instructions ("PUSH handler" and "PUSH FS:[0]"). The PUSH FS:[0] saves the previous value of FS:[0] as part of the structure, but that's not important at the moment. The significant thing is that there's an 8-byte EXCEPTION_REGISTRATION structure on the stack. The very next instruction (MOV FS:[0],ESP) makes the first DWORD in the thread information block point at the new EXCEPTION_REGISTRATION structure.
    If you're wondering why I built the EXCEPTION_REGISTRATION structure on the stack rather than using a global variable, there's a good reason. When you use a compiler's _try/_except syntax, the compiler also builds the EXCEPTION_REGISTRATION struct on the stack. I'm simply showing you a simplified version of what a compiler would do if you used _try/_except.
    Back to function main, the next __asm block intentionally causes a fault by zeroing out the EAX register (MOV EAX,0), and then uses the register's value as a memory address, which the next instruction writes to (MOV [EAX],1). The final __asm block removes this simple exception handler: first it restores the previous contents of FS:[0], and then it pops the EXCEPTION_REGISTRATION record off the stack (ADD ESP,8).
    Now, pretend that you're running MYSEH.EXE and you'll see what happens. When the MOV [EAX],1 instruction executes, it causes an access violation. The system looks at the FS:[0] in the TIB and finds a pointer to the EXCEPTION_REGISTRATION structure. In the structure is a pointer to the _except_handler function in MYSEH.CPP. The system then pushes the four required parameters (which I described earlier) onto the stack and calls the _except_handler function.
    Once inside _except_handler, the code first indicates "Yo! I made it here!" via a printf statement. Next, _except_handler fixes the problem that caused the fault. That is, the EAX register points to a memory address that can't be written to (address 0). The fix is to change the EAX value in the CONTEXT structure so that it points to a location where writing is allowed. In this simple program, a DWORD variable (scratch) has been designated for just this purpose. The last act of the _except_handler function is to return the value ExceptionContinueExecution, which is defined in the standard EXCPT.H file.
    When the operating system sees that ExceptionContinueExecution was returned, it interprets this to mean that you've fixed the problem and the faulting instruction should be restarted. Since my _except_handler function tweaked the EAX register to point to valid memory, the MOV EAX,1 instruction works the second time and function main continues normally. See, that wasn't so complicated, was it?

    Moving In a Little Deeper

    With this simplest of scenarios behind us, let's go back and fill in some of the blanks. While this exception callback is great, it's not a perfect solution. In an application of any size, it would be exceedingly messy to write a single function to handle exceptions that could occur anywhere in your application. A much more workable scenario would be to have multiple exception handling routines, each one customized to a particular section of your application. Wouldn't you know it, the operating system provides just this functionality.
    Remember the EXCEPTION_REGISTRATION structure that the system uses to find the exception callback function? The first member of this structure, which I ignored earlier, is called prev. It's really a pointer to another EXCEPTION_REGISTRATION structure. This second EXCEPTION_REGISTRATION structure can have a completely different handler function. What's more, its prev field can point to a third EXCEPTION_REGISTRATION structure, and so on. Simply put, there's a linked list of EXCEPTION_REGISTRATION structures. The head of the list is always pointed to by the first DWORD in the thread information block (FS:[0] on Intel-based machines).
    What does the operating system do with this linked list of EXCEPTION_REGISTRATION structures? When an exception occurs, the system walks the list of structures and looks for an EXCEPTION_REGISTRATION whose handler callback agrees to handle the exception. In the case of MYSEH.CPP, the handler callback agreed to handle the exception by returning the value ExceptionContinueExecution. The exception callback can also decline to handle the exception. In this case, the system moves on to the next EXCEPTION_REGISTRATION structure in the list and asks its exception callback if it wants to handle the exception. Figure 4 shows this process. Once the system finds a callback that handles the exception, it stops walking the linked list of EXCEPTION_REGISTRATIONs.
    To show an example of an exception callback that doesn't handle an exception, check out MYSEH2.CPP inFigure 5. To keep the code simple, I cheated a bit and used a little compiler-level exception handling. Function main just sets up a _try/_except block. Inside the _try block is a call to the HomeGrownFrame function. This function is very similar to the code in the earlier MYSEH program. It creates an EXCEPTION_REGISTRATION record on the stack and points FS:[0] at it. After establishing the new handler, the function intentionally causes a fault by writing to a NULL pointer:

    
     *(PDWORD)0 = 0;
    
    The exception callback function, again called _except_ handler, is quite different than the earlier version. The code first prints out the exception code and flags from the ExceptionRecord structure that the function received as a pointer parameter. The reason for printing out the exception flags will become clear later. Since this _except_handler function has no intention of fixing the offending code, the function returns ExceptionContinueSearch. This causes the operating system to continue its search at the next EXCEPTION_REGISTRATION record in the linked list. For now, take my word for it; the next installed exception callback is for the _try/_except code in function main. The _except block simply prints out "Caught the exception in main()". In this case, handling the exception is as simple as ignoring that it happened.
    A key point to bring up here is execution control. When a handler declines to handle an exception, it effectively declines to decide where control will eventually resume. The handler that accepts the exception is the one that decides where control will continue after all the exception handling code is finished. This has an important implication that's not immediately obvious.
    When using structured exception handling, a function may exit in an abnormal manner if it has an exception handler that doesn't handle the exception. For instance, in MYSEH2 the minimal handler in the HomeGrownFrame function didn't handle the exception. Since somebody later in the chain handled the exception (function main), the printf after the faulting instruction never executes. In some ways, using structured exception handling is similar to using the setjmp and longjmp runtime library functions.
    If you run MYSEH2, you'll find something surprising in the output. It seems that there's two calls to the _except_handler function. The first call is certainly understandable, given what you know so far. But why the second?
    
     Home Grown handler: Exception Code: C0000005 Exception Flags 0
     Home Grown handler: Exception Code: C0000027 Exception Flags 2
                                                  EH_UNWINDING
     Caught the Exception in main()
    
    There's obviously a difference: compare the two lines that start with "Home Grown Handler." In particular, the exception flags are zero the first time though, and 2 the second time. This brings me to the subject of unwinding. To jump ahead a bit, when an exception callback declines to handle an exception, it gets called a second time. This callback doesn't happen immediately, though. It's a bit more complicated then that. I'll need to refine the exception scenario one final time.
    When an exception occurs, the system walks the list of EXCEPTION_REGISTRATION structures until it finds a handler for the exception. Once a handler is found, the system walks the list again, up to the node that will handle the exception. During this second traversal, the system calls each handler function a second time. The key distinction is that in the second call, the value 2 is set in the exception flags. This value corresponds to EH_UNWINDING. (The definition for EH_UNWINDING is in EXCEPT.INC, which is in the Visual C++ runtime library sources, but nothing equivalent appears in the Win32 SDK.)
    What does EH_UNWINDING mean? When an exception callback is invoked a second time (with the EH_UNWINDING flag), the operating system is giving the handler function an opportunity to do any cleanup it needs to do. What sort of cleanup? A perfect example is that of a C++ class destructor. When a function's exception handler declines to handle an exception, control typically doesn't exit from that function in a normal manner. Now, consider a function with a C++ class declared as a local variable. The C++ specification says that the destructor must be called. The second exception handler callback with the EH_UNWINDING flag is the opportunity for the function to do cleanup work such as invoking destructors and _finally blocks.
    After an exception is handled and all the previous exception frames have been called to unwind, execution continues wherever the handling callback decides. Remember though that it's just not enough to set the instruction pointer to the desired code address and plunge ahead. The code where execution resumes expects that the stack and frame pointer (the ESP and EBP registers on Intel CPUs) are set to their values within the stack frame that handled the exception. Therefore, the handler that accepts a particular exception is responsible for setting the stack and frame pointers to values that they had in the stack frame that contains the SEH code that handled the exception.
    Figure 6  Unwinding from an Exception
    Figure 6 Unwinding from an Exception

    In more general terms, the act of unwinding from an exception causes all things on the stack below the handling frame's stack region to be removed. It's almost as if those functions were never called. Another effect of unwinding is that all EXCEPTION_REGISTRATIONs in the list prior to the one that handled the exception are removed from the list. This makes sense, as these EXCEPTION_REGISTRATIONs are typically built on the stack. After the exception has been handled, the stack and frame pointers will be higher in memory than the EXCEPTION_REGISTRATIONs that were removed from the list. Figure 6 shows what I'm talking about. 

    Help! Nobody Handled It!

    So far, I've implicitly assumed that the operating system always finds a handler somewhere in the linked list of EXCEPTION_REGISTRATIONs. What happens if nobody steps up to the plate? As it turns out, this almost never happens. The reason is that the operating system sneaks in a default exception handler for each and every thread. The default handler is always the last node in the linked list, and it always chooses to handle the exception. Its actions are somewhat different than a normal exception callback routine, as I'll show later.
    Let's look at where the system inserts the default, last resort exception handler. This obviously needs to occur very early in the thread's execution, before any user code executes. Figure 7 shows some pseudocode I wrote for BaseProcessStart, an internal routine in the Windows NT KERNEL32.DLL. BaseProcessStart takes one parameter, the address of the thread's entry point. BaseProcessStart runs in the context of the new process and calls the entry point to kick off execution of the first thread in the process.
    In the pseudocode, notice that the call to lpfnEntryPoint is wrapped within an _try and _except construct. This _try block is what installs the default, last resort exception handler in the linked list of handlers. All subsequent registered exception handlers will be inserted ahead of this handler in the list. If the lpfnEntryPoint function returns, the thread ran to completion without causing an exception. When this happens, BaseProcessStart calls ExitThread to terminate the tread.
    On the other hand, what if the thread faults and no other exception handlers handle it? In this case, control goes to the code inside the parens after the _except keyword. In BaseProcessStart, this code calls the UnhandledExceptionFilter API, which I'll come back to later. For now, the key point is that the UnhandledExceptionFilter API contains the meat of the default exception handler.
    If UnhandledExceptionFilter returns EXCEPTION_EXECUTE_HANDLER, the _except block in BaseProcessStart executes. All the _except block code does is terminate the current process by calling ExitProcess. Thinking about it for a second, this makes sense; it's common knowledge that if a program causes a fault and nobody handles the fault, the system terminates the process. What you're seeing in the pseudocode is exactly where and how this happens.
    There's one final addition to what I've just described. If the thread that faulted is running as a service and is for a thread-based service, the _except block code doesn't call ExitProcess—it calls ExitThread instead. You wouldn't want to terminate the entire service process just because one service went bad.
    So what does the default exception handler code in UnhandledExceptionFilter do? When I ask this question at seminars, very few people can guess what the default behavior of the operating system is when an unhandled exception occurs. With a very simple demonstration of the default handler's behavior, things usually click and people understand. I simply run a program that intentionally causes a fault, and point out the results (see Figure 8).

    Figure 8 Unhandled Exception Dialog
    Figure 8 Unhandled Exception Dialog

    At a high level, UnhandledExceptionFilter displays a dialog telling you that a fault occurred. At that point, you're given the opportunity to either terminate or debug the faulting process. Much more happens behind the scenes, and I'll describe these things towards the end of the article.
    As I've shown, when an exception occurs, user-written code can (and often does) get executed. Likewise, during an unwind operation, user-written code can execute. This user-written code may have bugs and could cause another exception. For this reason, there are two other values that an exception callback can return: ExceptionNestedException and ExceptionCollidedUnwind. While obviously important, this is pretty advanced stuff and I'm not going to dwell on it here. It's difficult enough to understand the basic facts.

    Compiler-level SEH

    While I've made occasional reference to _try and _except, just about everything I've written about so far is implemented by the operating system. However, in looking at the contortions of my two small programs that used raw system SEH, a compiler wrapper around this functionality is definitely in order. Let's now see how Visual C++ builds its structured exception handling support on top of the system-level SEH facilities.
    Before moving on, it's important to remember that another compiler could do something completely different with the raw system-level SEH facilities. Nothing says that a compiler must implement the _try/_except model that the Win32 SDK documentation describes. For example, the upcoming Visual Basic
    ® 5.0 uses structured exception handling in its runtime code, but the data structures and algorithms are completely different from what I'll describe here.
    If you read through the Win32 SDK documentation on structured exception handling, you'll come across the following syntax for a so called "frame-based" exception handler:

    
     try {
         // guarded body of code
     }
     except (filter-expression) {
         // exception-handler block
     }
    
    To be a bit simplistic, all of the code within a try block in a function is protected by an EXCEPTION_REGISTRATION that's built on the function's stack frame. On function entry, the new EXCEPTION_REGISTRATION is put at the head of the linked list of exception handlers. After the end of the _try block, its EXCEPTION_REGISTRATION is removed from the head of the list. As I mentioned earlier, the head of the exception handler chain is kept at FS:[0]. Thus, if you're stepping through assembly language in a debugger and you see instructions such as
    
     MOV DWORD PTR FS:[00000000],ESP
    
    or
    
     MOV DWORD PTR FS:[00000000],ECX
    
    you can be pretty sure that the code is setting up or tearing down a _try/_except block.
    Now that you know that a _try block corresponds to an EXCEPTION_REGISTRATION structure on the stack, what about the callback function within the EXCEPTION_ REGISTRATION? Using Win32 terminology, the exception callback function corresponds to the filter-expression code. To refresh your memory, the filter-expression is the code in parens after the _except keyword. It's this filter-expression code that decides whether the code in the subsequent {} block will execute. 
    Since you write the filter-expression code, you get to decide if a particular exception will be handled at this particular point in your code. Your filter-expression code might be as simple as saying "EXCEPTION_EXECUTE_ HANDLER." Alternatively, the filter-expression might invoke a function that calculates p to 20 million places before returning a code telling the system what to do next. It's your choice. The key point: your filter-expression code is effectively the exception callback that I described earlier.
    What I've just described, while reasonably simple, is nonetheless a rose-colored-glasses view of the world. The ugly reality is that things are more complicated. For starters, your filter-expression code isn't called directly by the operating system. Rather, the exception handler field in every EXCEPTION_REGISTRATION points to the same function. This function is in the Visual C++ runtime library and is called __except_handler3. It's __except_handler3 that calls your filter-expression code, and I'll come back to it a bit later.
    Another twist to the simplistic view that I described earlier is that EXCEPTION_REGISTRATIONs aren't built and torn down every time a _try block is entered or exits. Instead, there's just one EXCEPTION_REGISTRATION created in any function that uses SEH. In other words, you can have multiple _try/_except constructs in a function, yet only one EXCEPTION_REGISTRATION is created on the stack. Likewise, you might have a _try block nested within another _try block in a function. Still, Visual C++ creates only one EXCEPTION_REGISTRATION.
    If a single exception handler (that is, __except_handler3) suffices for the whole EXE or DLL, and if a single EXCEPTION_REGISTRATION handles multiple _try blocks, there's obviously more going on here than meets the eye. This magic is accomplished through data in tables that you don't normally see. However, since the whole purpose of this article is to dissect structured exception handling, let's take a look at these data structures.

    The Extended Exception Handling Frame

    The Visual C++ SEH implementation doesn't use the raw EXCEPTION_REGISTRATION structure. Instead, it adds additional data fields to the end of the structure. This additional data is critical to allowing a single function (__except_handler3) to handle all exceptions and route control to the appropriate filter-expressions and _except blocks throughout the code. A hint to the format of the Visual C++ extended EXCEPTION_REGISTRATION structure is found in the EXSUP.INC file from the Visual C++ runtime library sources. In this file, you'll find the following (commented out) definition:

    
     ;struct _EXCEPTION_REGISTRATION{
     ;     struct _EXCEPTION_REGISTRATION *prev;
     ;     void (*handler)(PEXCEPTION_RECORD,
     ;                     PEXCEPTION_REGISTRATION,
     ;                     PCONTEXT,
     ;                     PEXCEPTION_RECORD);
     ;     struct scopetable_entry *scopetable;
     ;     int trylevel;
     ;     int _ebp;
     ;     PEXCEPTION_POINTERS xpointers;
     ;};
    
    You've seen the first two fields, prev and handler, before. They make up the basic EXCEPTION_REGISTRATION structure. What's new are the last three fields: scopetable, trylevel, and _ebp. The scopetable field points to an array of structures of type scopetable_entries, while the trylevel field is essentially an index into this array. The last field, _ebp, is the value of the stack frame pointer (EBP) before the EXCEPTION_REGISTRATION was created.
    It's not coincidental that the _ebp field becomes part of the extended EXCEPTION_REGISTRATION structure. It's included in the structure via the PUSH EBP instruction that most functions begin with. This has the effect of making all of the other EXCEPTION_REGISTRATION fields accessible as negative displacements from the frame pointer. For example, the trylevel field is at [EBP-04], the scopetable pointer is at [EBP-08], and so on. 
    Immediately below its extended EXCEPTION_REGISTRATION structure, Visual C++ pushes two additional values. In the DWORD immediately below, it reserves space for a pointer to an EXCEPTION_POINTERS structure (a standard Win32 structure). This is the pointer returned when you call the GetExceptionInformation API. While the SDK documentation implies that GetException Information is a standard Win32 API, the truth is that GetExceptionInformation is a compiler-intrinsic function. When you call the function, Visual C++ generates the following:
    
     MOV EAX,DWORD PTR [EBP-14]
    
    Just as GetExceptionInformation is a compiler intrinsic function, so is the related function GetExceptionCode. GetExceptionCode just reaches in and returns the value of a field from one of the data structures that GetExceptionInformation returns. I'll leave it as an exercise for the reader to figure out exactly what's going on when Visual C++ generates the following instructions for GetExceptionCode:
    
     MOV EAX,DWORD PTR [EBP-14]
     MOV EAX,DWORD PTR [EAX]
     MOV EAX,DWORD PTR [EAX]
    
    Returning to the extended EXCEPTION_REGISTRATION structure, 8 bytes before the start of the structure, Visual C++ reserves a DWORD to hold the final stack pointer (ESP) after all the prologue code has executed. This DWORD is the normal value of the ESP register as the function executes (except of course when parameters are being pushed in preparation for calling another function). 
    If it seems like I've dumped a ton of information onto you, I have. Before moving on, let's pause for just a moment and review the standard exception frame that Visual C++ generates for a function that uses structured exception handling:
    
     EBP-00 _ebp
     EBP-04 trylevel
     EBP-08 scopetable pointer
     EBP-0C handler function address
     EBP-10 previous EXCEPTION_REGISTRATION
     EBP-14 GetExceptionPointers
     EBP-18 Standard ESP in frame
    
    From the operating system's point of view, the only fields that exist are the two fields that make up a raw EXCEPTION_REGISTRATION: the prev pointer at [EBP-10] and the handler function pointer at [EBP-0Ch]. Everything else in the frame is specific to the Visual C++ implementation. With this in mind, let's look at the Visual C++ runtime library routine that embodies compiler level SEH, __except_handler3. 

    __except_handler3 and the scopetable

    While I'd dearly love to point you to the Visual C++ runtime library sources and have you check out the __except_handler3 function yourself, I can't. It's conspicuously absent. In its place, you'll have to make due with some pseudocode for __except_handler3 that I cobbled together (see Figure 9).
    While __except_handler3 looks like a lot of code, remember that it's just an exception callback like I described at the beginning of this article. It takes the identical four parameters as my homegrown exception callbacks in MYSEH.EXE and MYSEH2.EXE. At the topmost level, __except_handler3 is split into two parts by an if statement. This is because the function can be called twice, once normally and once during the unwind phase. The larger portion of the function is devoted to the non-unwinding callback.
    The beginning of this code first creates an EXCEPTION_POINTERS structure on the stack, initializing it with two of the __except_handler3 parameters. The address of this structure, which I've called exceptPtrs in the pseudocode, is placed at [EBP-14]. This initializes the pointer that the GetExceptionInformation and GetExceptionCode functions use.
    Next, __except_handler3 retrieves the current trylevel from the EXCEPTION_REGISTRATION frame (at [EBP-04]). The trylevel variable acts as an index into the scopetable array, which allows a single EXCEPTION_REGISTRATION to be used for multiple _try blocks within a function, as well as nested _try blocks. Each scopetable entry looks like this:

    
     typedef struct _SCOPETABLE
     {
         DWORD       previousTryLevel;
         DWORD       lpfnFilter
         DWORD       lpfnHandler
     } SCOPETABLE, *PSCOPETABLE;

    The second and third parameters in a SCOPETABLE are easy to understand. They're the addresses of your filter-expression and the corresponding _except block code. The previous tryLevel field is bit trickier. In a nutshell, it's for nested try blocks. The important point here is that there's one SCOPETABLE entry for each _try block in a function.
    As I mentioned earlier, the current trylevel specifies the scopetable array entry to be used. This, in turn, specifies the filter-expression and _except block addresses. Now, consider a scenario with a _try block nested within another _try block. If the inner _try block's filter-expression doesn't handle the exception, the outer _try block's filter-expression must get a crack at it. How does __except_handler3 know which SCOPETABLE entry corresponds to the outer _try block? Its index is given by the previousTryLevel field in a SCOPETABLE entry. Using this scheme, you can create arbitrarily nested _try blocks. The previousTryLevel field acts as a node in a linked list of possible exception handlers within the function. The end of the list is indicated by a trylevel of 0xFFFFFFFF.
    Returning to the __except_handler3 code, after it retrieves the current trylevel the code points to the corresponding SCOPETABLE entry and calls the filter- expression code. If the filter-expression returns EXCEPTION_CONTINUE_SEARCH, __except_handler3 moves on to the next SCOPETABLE entry, which is specified in the previousTryLevel field. If no handler is found by traversing the list, __except_handler3 returns DISPOSITION_CONTINUE_SEARCH, which causes the system to move on to the next EXCEPTION_REGISTRATION frame. 
    If the filter-expression returns EXCEPTION_EXECUTE_HANDLER, it means that the exception should be handled by the corresponding _except block code. This means that any previous EXCEPTION_REGISTRATION frames have to be removed from the list and the _except block needs to be executed. The first of these chores is handled by calling __global_unwind2, which I'll describe later on. After some other intervening cleanup code that I'll ignore for the moment, execution leaves __except_handler3 and goes to the _except block. What's strange is that control never returns from the _except block, even though __except_handler3 makes a CALL to it. 
    How is the current trylevel set? This is handled implicitly by the compiler, which performs on-the-fly modifications of the trylevel field in the extended EXCEPTION_REGISTRATION structure. If you examine the assembler code generated for a function that uses SEH, you'll see code that modifies the current trylevel at [EBP-04] at different points in the function's code. 
    How does __except_handler3 make a CALL to the _except block code, yet control never returns? Since a CALL instruction pushes a return address onto the stack, you'd think this would mess up the stack. If you examine the generated code for an _except block, you'll find that the first thing it does is load the ESP register from the DWORD that's 8 bytes below the EXCEPTION_REGISTRATION structure. As part of its prologue code, the function saves the ESP value away so that an _except block can retrieve it later.

    The ShowSEHFrames Program

    If you're feeling a bit overwhelmed at this point by things like EXCEPTION_REGISTRATIONs, scopetables, trylevels, filter-expressions, and unwinding, so was I at first. The subject of compiler-level structured exception handling does not lend itself to learning incrementally. Much of it doesn't make sense unless you understand the whole ball of wax. When confronted with a lot of theory, my natural inclination is to write code that applies the concepts I'm learning. If the program works, I know that my understanding is (usually) correct.
     Figure 10 is the source code for ShowSEHFrames.EXE. It uses _try/_except blocks to set up a list of several Visual C++ SEH frames. Afterwards, it displays information about each frame, as well as the scopetables that Visual C++ builds for each frame. The program doesn't generate or expect any exceptions. Rather, I included all the _try blocks to force Visual C++ to generate multiple EXCEPTION_ REGISTRATION frames, with multiple scopetable entries per frame.
    The important functions in ShowSEHFrames are WalkSEHFrames and ShowSEHFrame. WalkSEHFrames first prints out the address of __except_handler3, the reason for which will be clear in a moment. Next, the function obtains a pointer to the head of the exception list from FS:[0] and walks each node in the list. Each node is of type VC_EXCEPTION_REGISTRATION, which is a structure that I defined to describe a Visual C++ exception handling frame. For each node in the list, WalkSEHFrames passes a pointer to the node to the ShowSEHFrame function.
    ShowSEHFrame starts by printing the address of the exception frame, the handler callback address, the address of the previous exception frame, and a pointer to the scopetable. Next, for each scopetable entry, the code prints out the previous trylevel, the filter-expression address, and the _except block address. How do I know how many entries are in a scopetable? I don't really. Rather, I assume that the current trylevel in the VC_EXCEPTION_REGISTRATION structure is one less than the total number of scopetable entries.
    Figure 11 shows the results of running ShowSEHFrames. First, examine every line that begins with "Frame:". Notice how each successive instance shows an exception frame that's at a higher address on the stack. Next, on the first three Frame: lines, notice that the Handler value is the same (004012A8). Looking at the beginning of the output, you'll see that this 004012A8 is none other than the address of the __except_handler3 function in the Visual C++ runtime library. This proves my earlier assertion that a single entry point handles all exceptions.
    You may be wondering why there are three exception frames using __except_handler3 as their callback since ShowSEHFrames plainly has only two functions that use SEH. The third frame comes from the Visual C++ runtime library. The code in CRT0.C from the Visual C++ runtime library sources shows that the call to main or WinMain is wrapped in an _try/_except block. The filter-expression code for this _try block is found in the WINXFLTR.C file. 
    Returning to ShowSEHFrames, the Handler for the last Frame: line contains a different address, 77F3AB6C. Poking around a bit, you'll find that this address is in KERNEL32.DLL. This particular frame is installed by KERNEL32.DLL in the BaseProcessStart function that I described earlier.

    Unwinding

    Let's briefly recap what unwinding means before digging into the code that implements it. Earlier, I described how potential exception handlers are kept in a linked list, pointed to by the first DWORD of the thread information block (FS:[0]). Since the handler for a particular exception may not be at the head of the list, there needs to be an orderly way of removing all exception handlers in the list that are ahead of the handler that actually deals with the exception.
    As you saw in the Visual C++ __except_handler3 function, unwinding is performed by the __global_unwind2 RTL function. This function is just a very thin wrapper around the undocumented RtlUnwind API:

    
     __global_unwind2(void * pRegistFrame)
     {
         _RtlUnwind( pRegistFrame,
                     &__ret_label,
                     0, 0 );
         __ret_label:
     }
    
    While RtlUnwind is a critical API for implementing compiler-level SEH, it's not documented anywhere. While technically a KERNEL32 function, the Windows NT KERNEL32.DLL forwards the call to NTDLL.DLL, which also has an RtlUnwind function. I was able to piece together some pseudocode for it, which appears inFigure 12.
    While RtlUnwind looks imposing, it's not hard to understand if you methodically break it down. The API begins by retrieving the current top and bottom of the thread's stack from FS:[4] and FS:[8]. These values are important later as sanity checks to ensure that all of the exception frames being unwound fall within the stack region.
    RtlUnwind next builds a dummy EXCEPTION_RECORD on the stack and sets the ExceptionCode field to STATUS_UNWIND. Also, the EXCEPTION_UNWINDING flag is set in the ExceptionFlags field of the EXCEPTION_RECORD. A pointer to this structure will later be passed as a parameter to each exception callback. Afterwards, the code calls the _RtlpCaptureContext function to create a dummy CONTEXT structure that also becomes a parameter for the unwind call of the exception callback.
    The remainder of RtlUnwind traverses the linked list of EXCEPTION_REGISTRATION structures. For each frame, the code calls the RtlpExecuteHandlerForUnwind function, which I'll cover later. It's this function that calls the exception callback with the EXCEPTION_UNWINDING flag set. After each callback, the corresponding exception frame is removed by calling RtlpUnlinkHandler.
    RtlUnwind stops unwinding frames when it gets to the frame with the address that was passed in as the first parameter. Interspersed with the code I've described is sanity-checking code to ensure that everything looks okay. If some sort of problem crops up, RtlUnwind raises an exception to indicate what the problem was, and this exception has the EXCEPTION_NONCONTINUABLE flag set. A process isn't allowed to continue execution when this flag is set, so it must terminate. 

    Unhandled Exceptions

    Earlier in the article, I put off a full description of the UnhandledExceptionFilter API. You normally don't call this API directly (although you can). Most of the time, it's invoked by the filter-expression code for KERNEL32's default exception callback. I showed this earlier in the pseudocode for BaseProcessStart.
     Figure 13 shows my pseudocode for UnhandledExceptionFilter. The API starts out a bit strangely (at least in my opinion). If the fault is an EXCEPTION_ACCESS_ VIOLATION, the code calls _BasepCheckForReadOnlyResource. While I haven't provided pseudocode for this function, I can summarize it. If the exception occurred because a resource section (.rsrc) of an EXE or DLL was written to, _BasepCurrentTopLevelFilter changes the faulting page's attributes from its normal read-only state, thereby allowing the write to occur. If this particular scenario occurs, UnhandledExceptionFilter returns EXCEPTION_ CONTINUE_EXECUTION and execution restarts at the faulting instruction.
    The next task of UnhandledExceptionFilter is to determine if the process is being run under a Win32 debugger. That is, the process was created with the DEBUG_PROCESS or DEBUG_ONLY_THIS_PROCESS flag. UnhandledExceptionFilter uses the NtQueryInformationProcess Function that I describe in this month's Under the Hood column to tell if the process is being debugged. If so, the API returns EXCEPTION_CONTINUE_SEARCH, which tells some other part of the system to wake up the debugger process and tell it that an exception occurred in the debuggee. 
    Next on UnhandledExceptionFilter's plate is a call to the user-installed unhandled exception filter, if present. Normally, there isn't a user-installed callback, but one can be installed via the SetUnhandledExceptionFilter API. I've also provided pseudocode for this API. The API simply bashes a global variable with the new user callback address, and returns the value of the old callback. 
    With the preliminaries out of the way, UnhandledExceptionFilter can get down to its primary job: informing you of your ignominious programming blunder with the ever- stylish Application Error dialog. There are two ways that this dialog can be avoided. The first is if the process has called SetErrorMode and specified the SEM_NOGPFAULTERRORBOX flag. The other method is to have the Auto value under the AeDebug registry key set to 1. In this case, UnhandledExceptionFilter skips the Application Error dialog and automatically fires up whatever debugger is specified in the Debugger value of the AeDebug key. If you're familiar with "just in time debugging," this is where the operating system supports it. More on this later.
    In most cases, neither of these dialog avoidance conditions are true and UnhandledExceptionFilter calls the NtRaiseHardError function in NTDLL.DLL. It's this function that brings up the Application Error dialog. This dialog waits for you to hit the OK button to terminate the process, or Cancel to debug it. (Maybe it's just me, but hitting Cancel to launch a debugger seems a little backward.)
    If you hit OK in the Application Error dialog box, UnhandledExceptionFilter returns EXCEPTION_EXECUTE_HANDLER. The code that called UnhandledExceptionFilter usually responds by terminating itself (as you saw in the BaseProcessStart code). This brings up an interesting point. Most people assume that the system terminates a process with an unhandled exception. It's actually more correct to say that the system sets up things so that an unhandled exception causes the process to terminate itself.
    The truly interesting code in UnhandledExceptionFilter executes if you select Cancel in the Application Error dialog, thereby bringing up a debugger on the faulting process. The code first calls CreateEvent to make an event that the debugger will signal after it has attached to the faulting process. This event handle, along with the current process ID, is passed to sprintf, which formats the command line used to start the debugger. Once everything is prepared, UnhandledExceptionFilter calls CreateProcess to start the debugger. If CreateProcess succeeds, the code calls NtWaitForSingleObject on the event created earlier. This call blocks until the debugger process signals the event, indicating that it has attached to the faulting process successfully. There are other little bits and pieces to the UnhandledExceptionFilter code, but I've covered the important highlights here.

    Into the Inferno

    If you've made it this far, it wouldn't be fair to finish without completing the entire circuit. I've shown how the operating system calls a user-defined function when an exception occurs. I've shown what typically goes on inside of those callbacks, and how compilers use them to implement _try and _catch. I've even shown what happens when nobody handles the exception and the system has to do the mopping up. All that remains is to show where the exception callbacks originate from in the first place. Yes, let's plunge into the bowels of the system and see the beginning stages of the structured exception handling sequence.
     Figure 14 shows some pseudocode I whipped up for KiUserExceptionDispatcher and some related functions. KiUserExceptionDispatcher is in NTDLL.DLL and is where execution begins after an exception occurs. To be 100 percent accurate, what I just said isn't exactly true. For instance, in the Intel architecture an exception causes control to vector to a ring 0 (kernel mode) handler. The handler is defined by the interrupt descriptor table entry that corresponds to an exception. I'm going to skip all that kernel mode code and pretend that the CPU goes straight to KiUserExceptionDispatcher upon an exception
    The heart of KiUserExceptionDispatcher is its call to RtlDispatchException. This kicks off the search for any registered exception handlers. If a handler handles the exception and continues execution, the call to RtlDispatchException never returns. If RtlDispatchException returns, there are two possible paths: either NtContinue is called, which lets the process continues, or another exception is raised. This time, the exception isn't continuable, and the process must terminate.
    Moving on to the RtlDispatchExceptionCode, this is where you'll find the exception frame walking code that I've referred to throughout this article. The function grabs a pointer to the linked list of EXCEPTION_REGISTRATIONs and iterates over every node, looking for a handler. Because of the possibility of stack corruption, the routine is very paranoid. Before calling the handler specified in each EXCEPTION_REGISTRATION, the code ensures that the EXCEPTION_REGISTRATION is DWORD-aligned, within the thread's stack, and higher on the stack than the previous EXCEPTION_REGISTRATION. 
    RtlDispatchException doesn't directly call the address specified in the EXCEPTION_REGISTRATION structure. Instead, it calls RtlpExecuteHandlerForException to do the dirty work. Depending on what happens inside RtlpExecuteHandlerForException, RtlDispatchException either continues walking the exception frames or raises another exception. This secondary exception indicates that something went wrong inside the exception callback and that execution can't continue.
    The code for RtlpExecuteHandlerForException is closely related to another function, RtlpExecutehandlerForUnwind. You may recall that I mentioned this function earlier when I described unwinding. Both of these "functions" simply load the EDX register with different values before sending control to the ExecuteHandler function. Put another way, RtlpExecuteHandlerForException and RtlpExecutehandlerForUnwind are separate front ends to a common function, ExecuteHandler.
    ExecuteHandler is where the handler field from the EXCEPTION_REGISTRATION is extracted and called. Strange as it may seem, the call to the exception callback is itself wrapped by a structured exception handler. Using SEH within itself seems a bit funky but it makes sense if you ponder it for a moment. If an exception callback causes another exception, the operating system needs to know about it. Depending on whether the exception occurred during the initial callback or during the unwind callback, ExecuteHandler returns either DISPOSITION_NESTED_ EXCEPTION or DISPOSITION_COLLIDED_UNWIND. Both are basically "Red Alert! Shut everything down now!" kind of codes.
    If you're like me, it's hard to keep all of the functions associated with SEH straight. Likewise, it's hard to remember who calls who. To help myself, I came up with the diagram shown in Figure 15.
    Now, what's the deal with setting EDX before getting to the ExecuteHandler code? It's simple, really. ExecuteHandler uses whatever's in EDX as the raw exception handler if something goes wrong while calling the user-installed handler. It pushes the EDX register onto the stack as the handler field for a minimal EXCEPTION_REGISTRATION structure. In essence, ExecuteHandler uses raw structured exception handling like I showed in the MYSEH and MYSEH2 programs.

    Conclusion

    Structured exception handling is a wonderful Win32 feature. Thanks to the supporting layers that compilers like Visual C++ put on top of it, the average programmer can benefit from SEH with a relatively small investment in learning. However, at the operating system level, things are more complicated than the Win32 documentation would lead you to believe.
    Unfortunately, not much has been written about system-level SEH to date because almost everyone considers it an extremely difficult subject. The lack of documentation on the system-level details hasn't helped. In this article, I've shown that system-level SEH revolves around a relatively simple callback. If you understand the nature of the callback, and then build additional layers of understanding on top of that, system-level structured exception handling really isn't so hard to grasp.

    From the January 1997 issue of Microsoft Systems Journal. Get it at your local newsstand, or better yet,subscribe.
    展开全文
  • <div><p>either fix the paginated view so is pops back to the top after ”Next” or "Previous” are pressed, or, even better, move to a continuous list.</p><p>该提问来源于开源项目:chocolatey...
  • The Architecture of the Java Virtual Machine In the Java virtual machine specification, the behavior of a virtual machine instance is described in terms of subsystems, memory areas, data types, and i

    The Architecture of the Java Virtual Machine

    In the Java virtual machine specification, the behavior of a virtual machine instance is described in terms of subsystems, memory areas, data types, and instructions. These components describe an abstract inner architecture for the abstract Java virtual machine. The purpose of these components is not so much to dictate an inner architecture for implementations. It is more to provide a way to strictly define the external behavior of implementations. The specification defines the required behavior of any Java virtual machine implementation in terms of these abstract components and their interactions.

    Figure 5-1 shows a block diagram of the Java virtual machine that includes the major subsystems and memory areas described in the specification. As mentioned in previous chapters, each Java virtual machine has aclass loader subsystem: a mechanism for loading types (classes and interfaces) given fully qualified names. Each Java virtual machine also has anexecution engine: a mechanism responsible for executing the instructions contained in the methods of loaded classes.



    Figure 5-1. The internal architecture of the Java virtual machine.

    When a Java virtual machine runs a program, it needs memory to store many things, including bytecodes and other information it extracts from loaded class files, objects the program instantiates, parameters to methods, return values, local variables, and intermediate results of computations. The Java virtual machine organizes the memory it needs to execute a program into severalruntime data areas.

    Although the same runtime data areas exist in some form in every Java virtual machine implementation, their specification is quite abstract. Many decisions about the structural details of the runtime data areas are left to the designers of individual implementations.

    Different implementations of the virtual machine can have very different memory constraints. Some implementations may have a lot of memory in which to work, others may have very little. Some implementations may be able to take advantage of virtual memory, others may not. The abstract nature of the specification of the runtime data areas helps make it easier to implement the Java virtual machine on a wide variety of computers and devices.

    Some runtime data areas are shared among all of an application's threads and others are unique to individual threads. Each instance of the Java virtual machine has onemethod area and one heap. These areas are shared by all threads running inside the virtual machine. When the virtual machine loads a class file, it parses information about a type from the binary data contained in the class file. It places this type information into the method area. As the program runs, the virtual machine places all objects the program instantiates onto the heap. See Figure 5-2 for a graphical depiction of these memory areas.



    Figure 5-2. Runtime data areas shared among all threads.

    As each new thread comes into existence, it gets its ownpc register (program counter) and Java stack. If the thread is executing a Java method (not a native method), the value of the pc register indicates the next instruction to execute. A thread's Java stack stores the state of Java (not native) method invocations for the thread. The state of a Java method invocation includes its local variables, the parameters with which it was invoked, its return value (if any), and intermediate calculations. The state of native method invocations is stored in an implementation-dependent way in native method stacks, as well as possibly in registers or other implementation-dependent memory areas.

    The Java stack is composed of stack frames (orframes). A stack frame contains the state of one Java method invocation. When a thread invokes a method, the Java virtual machine pushes a new frame onto that thread's Java stack. When the method completes, the virtual machine pops and discards the frame for that method.

    The Java virtual machine has no registers to hold intermediate data values. The instruction set uses the Java stack for storage of intermediate data values. This approach was taken by Java's designers to keep the Java virtual machine's instruction set compact and to facilitate implementation on architectures with few or irregular general purpose registers. In addition, the stack-based architecture of the Java virtual machine's instruction set facilitates the code optimization work done by just-in-time and dynamic compilers that operate at run-time in some virtual machine implementations.

    See Figure 5-3 for a graphical depiction of the memory areas the Java virtual machine creates for each thread. These areas are private to the owning thread. No thread can access the pc register or Java stack of another thread.



    Figure 5-3. Runtime data areas exclusive to each thread.

    Figure 5-3 shows a snapshot of a virtual machine instance in which three threads are executing. At the instant of the snapshot, threads one and two are executing Java methods. Thread three is executing a native method.

    In Figure 5-3, as in all graphical depictions of the Java stack in this book, the stacks are shown growing downwards. The "top" of each stack is shown at the bottom of the figure. Stack frames for currently executing methods are shown in a lighter shade. For threads that are currently executing a Java method, the pc register indicates the next instruction to execute. In Figure 5-3, such pc registers (the ones for threads one and two) are shown in a lighter shade. Because thread three is currently executing a native method, the contents of its pc register--the one shown in dark gray--is undefined. 

    展开全文
  • Implement a stack that pops out the most frequently added item. Stack supports 3 functions - push, pop,and top. Give complexity of each functions in your implementation. ---------------------------

    Implement a stack that pops out the most frequently added item. Stack supports 3 functions - push, pop,and top. Give complexity of each functions in your implementation.

    --------------------------------------------------------------

    One option is to combine heap (to get top) with hashtable (to find element in heap). That way insert is o(logn) and retrieval is o(1).


    展开全文
  • 嵌入式虚拟机CarpVM.zip

    2019-07-16 07:43:40
    SUB (): Pops the top two integers from the stack and pushes the difference (lower minus upper). MUL (): Pops the top two integers from the stack and pushes their product. MOD (rega, regb): Computes...
  • Memory Layout (Virtual address space of a C process) 分类:C语言基础2012-12-06 23:162174人阅读评论(0)收藏...found a good example to demostrate the memory layout and its stack info of a user-mode ...
  • The C API is the set of functions that allow C code to interact with Lua. It comprises functions to read and write Lua global variables, to call Lua functions, to run pieces of Lua code, to regist
  • Implement a stack that pops out the mostfrequently added item. Stack supports 3 functions – push, pop and top.Givecomplexity of each functions in your implementation 2、算法 实现有两种,一种...
  • For original article, you might take a look here: http://msdn.microsoft.com/en-us/magazine/cc164015.aspx ...Comparing the Timer Classes in the .NET Framework Class Library Alex Calvo ...
  • The Air Jordan 2012 pushes performance to new heights while packing the craftsmanship of a dress shoe. The Air Jordan 2012 features a mainly suede base and lightweight Flywire construction, along with...
  • Broadlink A1 is an Air Quality monitoring ... It has the capability to measure and report the air temperature, air quality, humidity, light and sound levels in real time. Based on the environmen...
  • 4-The Network Layer

    千次阅读 2016-09-21 20:00:00
    Please indicate the source: http://blog.csdn.net/gaoxiangnumber1Welcome to my github: https://github.com/gaoxiangnumber14.1 Introduction Figure 4.1 shows a network with two hosts, H1 and H2, and sever...
  • Computer Networking A Top-Down Approach 总结

    万次阅读 多人点赞 2017-06-18 15:13:00
    引言在这篇文章中,我主要对 Computer Networking: A Top-Down Approach (6th Edition) 一书进行总结,并把一些好的问题与 labs 记录下来,方便我日后在考研的时候 review.Computer Networks and the Internet对于第...
  • Working with the YUI DataTable (Updated for v2.6.0), Part 2: Changing the Contents of the DataTable October 27, 2008 at 8:23 am by Satyam | In Development | 28 Comments Don’t miss Part One of this ...
  • M001: MongoDB Basics chapter 2 The MongoDB Query Language + Atlas学习记录 运行环境 操作系统:windows 10 家庭中文版 Mongodb :Mongodb 3.4 Mongodb安装路径:E:&gt;MongoDB\Server\3.4\bin\ Mongodb...
  • Uva 107 The Cat in the Hat

    2014-07-24 11:38:27
    The Cat in the Hat  Background (An homage to Theodore Seuss Geisel) The Cat in the Hat is a nasty creature, But the striped hat he is wearing has a rather nifty feature. With one ...
  • The Cat in the Hat Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 1694 Accepted: 589 Description (An homage to Theodore Seuss Geisel) The Cat in the Hat is a nasty creature, But the stri...
  • If you changed the name on the top of the jerseys of Jed Lowrie, Josh Donaldson, Bartolo Colon and Grant Balfour to Boston or indiana, You'd likely be seeing a team with three to four AllStars. ...
  • The Tao of Windows Buffer Overflow

    千次阅读 2007-05-04 14:04:00
    ' executes it overflows the buffer, writing 'A's over the old value of EBP and over the return address. By overwriting the return address, you can seriously alter the course of program flow. All you ...
  • PIL--24 - An Overview of the C API C API概览

    千次阅读 2006-05-06 02:00:00
    24 - An Overview of the C API C API概览Lua is an embedded language. That means that Lua is not a stand-alone package, but a library that can be linked with other applications so as to incorporate Lua
  • 原文: www.csee.umbc.edu/~chang/cs313.s02/stack.shtml UMBC CMSC 313, Computer Organization & Assembly Language, Spring 2002, Section 0101 C Function Call Conventions and the Stack [Revised 10/
  • https://blog.forex4you.com/detection-and-analysis-of-candlestick-patterns/#prettyPhoto ...The importance of candlesticks to forex strategies cannot be overemphasized. Candlesticks are such an im
  • Part 1: InstallationInstallation Method 1: Python virtual environmentThe first method installs...
  • Two ways to describe the Internet 1. A nuts-and-bolt description (hardware&...The Internet is a computer network (of communication links and packet switches) that interconnects ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,267
精华内容 906
关键字:

ofpopsthetop